[
  {
    "path": ".clang-format",
    "content": "﻿---\nBasedOnStyle: Microsoft\nAccessModifierOffset: '-4'\nAlignAfterOpenBracket: AlwaysBreak\nAlignConsecutiveAssignments: 'true'\nAlignConsecutiveMacros: 'true'\nBinPackArguments: 'true'\nBinPackParameters: 'true'\nBreakBeforeBraces: Allman\nBreakConstructorInitializers: AfterColon\nBreakInheritanceList: AfterColon\nColumnLimit: '0'\nCpp11BracedListStyle: 'false'\nIncludeBlocks: 'Regroup'\nIncludeCategories:\n- Regex: '\".*\"'\n  Priority: 1\n- Regex: '<N(oesi)?s[[:alnum:]._/]+>'\n  Priority: 2\n- Regex: '<Q[[:alnum:]/]+>'\n  Priority: 3\n- Regex: '<[[:alnum:_]]+>'\n  Priority: 4\n- Regex: '<[[:alnum:]._]+\\>'\n  Priority: 5\nIndentCaseLabels: 'true'\nIndentWidth: '4'\nSortIncludes: 'true'\nSpaceBeforeCpp11BracedList: 'true'\nSpaceBeforeRangeBasedForLoopColon: 'true'\nSpaceInEmptyParentheses: 'false'\nSpacesInParentheses: 'true'\nTabWidth: '4'\nUseTab: ForContinuationAndIndentation\nPointerAlignment: Left\n\n...\n"
  },
  {
    "path": ".gitattributes",
    "content": "/src/gui/license.h \n\n*.h diff=cpp\n*.c diff=cpp\n*.cpp diff=cpp\n*.rc text=auto diff=cpp\n"
  },
  {
    "path": ".github/workflows/cmake.yml",
    "content": "name: CMake\n\non: [push, workflow_dispatch]\n\nenv:\n  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)\n  BUILD_TYPE: RelWithDebInfo\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/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n          - {\n            os: 'windows-2019',\n            sfml: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/SFML-2.5.1-windows-vc15-64-bit.zip',\n            noesis: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/NoesisGUI-NativeSDK-win-3.0.12.zip',\n            steam: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/steamworks_sdk_150.zip',\n          }\n          - {\n            os: 'ubuntu-18.04',\n            sfml: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/SFML-2.5.1-linux-gcc-64-bit.tar',\n            noesis: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/NoesisGUI-NativeSDK-linux-3.0.12.zip',\n            steam: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/steamworks_sdk_150.zip',\n          }\n    runs-on: ${{ matrix.config.os }}\n\n    steps:\n    - uses: actions/checkout@v2\n\n    - name: Get latest CMake\n      # Using 'latest' branch, the latest CMake is installed.\n      uses: lukka/get-cmake@latest\n\n    - name: Cache Qt\n      id: cache-qt\n      uses: actions/cache@v1\n      with:\n        path: '${{ github.workspace }}/Qt/'\n        key: ${{ runner.os }}-QtCache\n\n    - name: Install Qt\n      uses: jurplel/install-qt-action@v2\n      with:\n        version: '5.14.2'\n        dir: '${{ github.workspace }}/Qt/'\n        cached: ${{ steps.cache-qt.outputs.cache-hit }}\n\n    - name: Download Steam\n      uses: carlosperate/download-file-action@v1.0.3\n      id: download-steam\n      with:\n        file-url: ${{ matrix.config.steam }}\n\n    - name: Unpack Steam\n      uses: DuckSoft/extract-7z-action@v1.0\n      with:\n        pathSource: ${{ steps.download-steam.outputs.file-path }}\n        pathTarget: steamworks_sdk\n\n    - name: Download Noesis\n      uses: carlosperate/download-file-action@v1.0.3\n      id: download-noesis\n      with:\n        file-url: ${{ matrix.config.noesis }}\n\n    - name: Unpack Noesis\n      uses: DuckSoft/extract-7z-action@v1.0\n      with:\n        pathSource: ${{ steps.download-noesis.outputs.file-path }}\n        pathTarget: noesis_sdk\n\n    - name: Download BugSplat\n      uses: carlosperate/download-file-action@v1.0.3\n      id: download-bugsplat\n      with:\n        file-url: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/BugSplatNative.zip'\n\n    - name: Unpack BugSplat\n      uses: DuckSoft/extract-7z-action@v1.0\n      with:\n        pathSource: ${{ steps.download-bugsplat.outputs.file-path }}\n        pathTarget: bugsplat_sdk\n\n    - name: Install OpenAL Linux\n      if: (!startsWith(matrix.config.os, 'windows'))\n      shell: bash\n      run: sudo apt-get -yq install libopenal-dev\n\n    - name: Download OpenAL Windows\n      if: (startsWith(matrix.config.os, 'windows'))\n      uses: carlosperate/download-file-action@v1.0.3\n      id: download-openal\n      with:\n        file-url: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/openal.zip'\n\n    - name: Unpack OpenAL Windows\n      if: (startsWith(matrix.config.os, 'windows'))\n      uses: DuckSoft/extract-7z-action@v1.0\n      with:\n        pathSource: ${{ steps.download-openal.outputs.file-path }}\n        pathTarget: openal_sdk\n\n    - name: Download Tilesheets\n      uses: carlosperate/download-file-action@v1.0.3\n      id: download-tilesheet\n      with:\n        file-url: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/tilesheet.zip'\n\n    - name: Unpack Tilesheets\n      uses: DuckSoft/extract-7z-action@v1.0\n      with:\n        pathSource: ${{ steps.download-tilesheet.outputs.file-path }}\n        pathTarget: content\n\n    - name: Download Audio Files\n      uses: carlosperate/download-file-action@v1.0.3\n      id: download-audio\n      with:\n        file-url: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/audio.zip'\n\n    - name: Unpack Audio Files\n      uses: DuckSoft/extract-7z-action@v1.0\n      with:\n        pathSource: ${{ steps.download-audio.outputs.file-path }}\n        pathTarget: content\n\n    - name: Fix permissions\n      if: (!startsWith(matrix.config.os, 'windows'))\n      shell: bash\n      run: chmod +x ${{github.workspace}}/noesis_sdk/Src/Tools/Bin2h/bin2h.py\n\n    - name: Create Build Environment\n      run: cmake -E make_directory build\n\n    - name: Configure CMake\n      working-directory: ${{github.workspace}}/build\n      shell: bash\n      env:\n        NOESIS_LICENSE_KEY: ${{ secrets.NOESIS_LICENSE_KEY }}\n        NOESIS_LICENSE_NAME: ${{ secrets.NOESIS_LICENSE_NAME }}\n        BUGSPLAT_DB:  ${{ secrets.BUGSPLAT_DB }}\n      run: |\n        cmake -S .. -B . -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_BINDIR=\".\" -DSTEAM_SDK_ROOT=../steamworks_sdk/sdk -DNOESIS_ROOT=../noesis_sdk -DBUGSPLAT_SDK_ROOT=../bugsplat_sdk/bugsplat -DOPENAL_ROOT=../openal_sdk -DNOESIS_LICENSE_NAME=\"$NOESIS_LICENSE_NAME\" -DNOESIS_LICENSE_KEY=\"$NOESIS_LICENSE_KEY\" -DBUGSPLAT_DB=\"$BUGSPLAT_DB\" -DGIT_REPO=\"${{github.repository}}\" -DGIT_REF=\"${{github.ref}}\" -DGIT_SHA=\"${{github.sha}}\" -DBUILD_ID=\"${{github.run_id}}\"\n\n    - name: Build\n      working-directory: ${{github.workspace}}/build\n      shell: bash\n      run: |\n        cmake --build . --config ${{env.BUILD_TYPE}} --target Ingnomia\n        \n    - name: Install\n      working-directory: ${{github.workspace}}/build\n      shell: bash\n      run: |\n        cmake --install . --prefix ../install --config ${{env.BUILD_TYPE}}\n\n    - name: Find msbuild\n      if: (startsWith(matrix.config.os, 'windows'))\n      uses: microsoft/setup-msbuild@v1.0.2\n      id: msbuild\n\n    - name: Build Blend project\n      if: (startsWith(matrix.config.os, 'windows'))\n      working-directory: ${{github.workspace}}/gui\n      shell: pwsh\n      # Ignore errors for now\n      run: |\n        MSBuild.exe -t:restore gui.csproj\n        MSBuild.exe gui.csproj\n\n    - uses: actions/upload-artifact@v2\n      with:\n        name: \"${{matrix.config.os}}-${{github.run_id}}\"\n        path: |\n          install/\n          !**./*.iobj\n          !**./*.ipdb\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Docs\n\non:\n  push:\n    tags:\n      - '*'\n  workflow_dispatch:\n\njobs:\n  docs:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/setup-python@v2\n        with:\n          python-version: '3.9'\n      - uses: dschep/install-pipenv-action@v1\n      - uses: actions/checkout@v2\n\n      - name: Download Tilesheets\n        uses: carlosperate/download-file-action@v1.0.3\n        id: download-tilesheet\n        with:\n          file-url: 'https://github.com/rschurade/IngnomiaBuildDeps/raw/master/tilesheet.zip'\n\n      - name: Unpack Tilesheets\n        uses: DuckSoft/extract-7z-action@v1.0\n        with:\n          pathSource: ${{ steps.download-tilesheet.outputs.file-path }}\n          pathTarget: content\n\n      - name: Setup venv\n        working-directory: docs\n        run: |\n          pipenv install\n\n      - name: Generate docs\n        working-directory: docs\n        run: |\n          pipenv run ./generate.py --build ${GITHUB_REF#refs/*/}\n\n      - name: Deploy docs to gh-pages\n        uses: crazy-max/ghaction-github-pages@v2\n        with:\n          keep_history: true\n          build_dir: docs/html\n          fqdn: ${{ secrets.DOCS_DOMAIN }}\n          jekyll: false\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by https://www.gitignore.io/api/visualstudio\n# Edit at https://www.gitignore.io/?templates=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*.rsuser\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/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\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*_h.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*_wpftmp.csproj\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# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\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\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# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true\n**/wwwroot/lib/\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 personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\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# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# End of https://www.gitignore.io/api/visualstudio\nGeneratedFiles\n/RetrofitMenuCreator/settings.ini\n/spriteconv.json\n/file\n/src/gui/license.h\n/src/version.h\n/content/tilesheet\n/content/db/ingnomia.db\n\n# create by https://github.com/iamcco/coc-gitignore (Mon Aug 10 2020 12:20:22 GMT-0500 (hora estándar de Perú))\n# CMake.gitignore:\nCMakeLists.txt.user\nCMakeCache.txt\nCMakeFiles\nCMakeScripts\nTesting\nMakefile\ncmake_install.cmake\ninstall_manifest.txt\ncompile_commands.json\nCTestTestfile.cmake\n_deps\n\n# CMake.patch:\n# External projects\n*-prefix/\n\nbuild/\n/content/db/*.db\n\n# Visual studio code\n.vscode\n\n# Doc\n/docs/html\n\n/content/audio\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"src/base/beehive\"]\n\tpath = src/base/beehive\n\turl = https://github.com/crust/beehive.git\n"
  },
  {
    "path": "3rdparty/CMakeLists.txt",
    "content": "add_subdirectory(exprtk)\nadd_subdirectory(fastnoise)\nadd_subdirectory(NoesisApp)\nset_target_properties(exprtk PROPERTIES FOLDER 3rdParty)\nset_target_properties(fastnoise PROPERTIES FOLDER 3rdParty)\nset_target_properties(NoesisApp PROPERTIES FOLDER 3rdParty)\n"
  },
  {
    "path": "3rdparty/NoesisApp/CMakeLists.txt",
    "content": "project(NoesisApp)\n\nadd_library(${PROJECT_NAME})\n\n# All used packages. Same list of packages must be added to register.cpp\nset(NOESIS_APP_PACKAGES\n\tApp/ApplicationLauncher\n\tApp/DisplayLauncher\n\tApp/Display\n\tApp/Launcher\n\tApp/Providers\n\tApp/Theme\n\tApp/Interactivity\n\tApp/MediaElement\n\tRender/GLRenderContext\n\tRender/GLRenderDevice\n\tRender/RenderContext\n)\n\nfind_package(Noesis REQUIRED)\n\ntarget_link_libraries(${PROJECT_NAME}\n\tPUBLIC\n\t\tNoesis\n)\n\ntarget_compile_definitions(\n\t${PROJECT_NAME}\n\tPUBLIC\n\t\tNS_DEBUG\n\t\tNS_PROFILE\n\t\tNS_MINIMUM_LOG_LEVEL=0\n\tPRIVATE\n\t\tNS_APP_FRAMEWORK\n)\n\ntarget_precompile_headers(${PROJECT_NAME}\n\tPRIVATE\n\t\tpch.h\n)\n\n\n# Iterate over packages, and collect include + source directories\nforeach(PACKAGE ${NOESIS_APP_PACKAGES})\n\tset(PACKAGE_ROOT \"${NOESIS_ROOT}/Src/Packages/${PACKAGE}\")\n\tset(INCLUDE_DIR \"${PACKAGE_ROOT}/Include\")\n\n\tfile(GLOB_RECURSE PKG_SRCS \"${PACKAGE_ROOT}/*.cpp\"  \"${PACKAGE_ROOT}/*.h\")\n\tfile(GLOB_RECURSE PKG_RES \"${PACKAGE_ROOT}/*.xaml\" \"${PACKAGE_ROOT}/*.ttf\" \"${PACKAGE_ROOT}/*.ttf\" \"${PACKAGE_ROOT}/*.otf\")\n\n\tlist(APPEND NOESIS_APP_SRC ${PKG_SRCS})\n\tlist(APPEND NOESIS_APP_BIN2H ${PKG_RES})\n\n\tif(EXISTS ${INCLUDE_DIR})\n\t\ttarget_include_directories(${PROJECT_NAME}\n\t\t\tPUBLIC\n\t\t\t\t${INCLUDE_DIR}\n\t\t)\n\t\tstring(REPLACE \"/\" \";\" PACKAGE_SPLIT ${PACKAGE})\n\t\tlist(GET PACKAGE_SPLIT 0 PACKAGE_NAME)\n\t\tlist(GET PACKAGE_SPLIT 1 COMPONENT_NAME)\n\t\tset(MAIN_INCLUDE ${INCLUDE_DIR}/Ns${PACKAGE_NAME}/${COMPONENT_NAME}.h)\n\t\tif(EXISTS ${MAIN_INCLUDE})\n\t\t\ttarget_precompile_headers(${PROJECT_NAME}\n\t\t\t\tPRIVATE\n\t\t\t\t\t${MAIN_INCLUDE}\n\t\t\t)\n\t\tendif()\n\tendif()\n\n\t# Switch package to static linkage\n\tstring(REPLACE \"/\" \"_\" PACKAGENAME ${PACKAGE})\n\tstring(TOUPPER ${PACKAGENAME} PACKAGENAME)\n\ttarget_compile_definitions(${PROJECT_NAME}\n\t\tPUBLIC\n\t\t\t\"NS_${PACKAGENAME}_API=\"\n\t)\nendforeach()\n\n# Generated sources\nif(UNIX)\n\tset(BIN2H_EXE \"${NOESIS_ROOT}/Src/Tools/Bin2h/bin2h.py\")\nelseif(WIN32)\n\tset(BIN2H_EXE \"${NOESIS_ROOT}/Src/Tools/Bin2h/bin2h.exe\")\nendif()\nforeach(BIN2H_FILE ${NOESIS_APP_BIN2H})\n\tget_filename_component(BASENAME ${BIN2H_FILE} NAME)\n\tset(OUTPUTNAME \"${BASENAME}.bin.h\")\n\tset(OUTPUTPATH \"${CMAKE_CURRENT_BINARY_DIR}/${OUTPUTNAME}\")\n\tadd_custom_command(\n\t\tOUTPUT\n\t\t\t${OUTPUTNAME}\n\t\tCOMMAND\n\t\t\t${BIN2H_EXE} ${BIN2H_FILE} > ${OUTPUTPATH}\n\t\tDEPENDS\n\t\t\t${BIN2H_FILE}\n\t)\n\tlist(APPEND NOESIS_APP_GENERATED_PATHS ${OUTPUTPATH})\nendforeach()\n\ntarget_include_directories(${PROJECT_NAME}\n\tPRIVATE\n\t\t${CMAKE_CURRENT_BINARY_DIR}\n)\n\nfile(GLOB_RECURSE NOESIS_CORE_INCLUDES \"${NOESIS_ROOT}/Include/*.h\")\n\ntarget_sources(${PROJECT_NAME}\n\tPRIVATE\n\t\t${NOESIS_APP_GENERATED_PATHS}\n\t\t${NOESIS_APP_SRC}\n\t\t${NOESIS_APP_BIN2H}\n\t\t${NOESIS_CORE_INCLUDES}\n\t\tpch.h\n\t\tregister.cpp\n\t\tREADME.md\n)\n\nsource_group(TREE \"${CMAKE_CURRENT_BINARY_DIR}\" PREFIX \"Generated\" FILES ${NOESIS_APP_GENERATED_PATHS})\nsource_group(TREE \"${NOESIS_ROOT}/Src/Packages\" PREFIX \"NoesisApp\" FILES ${NOESIS_APP_SRC})\nsource_group(TREE \"${NOESIS_ROOT}/Src/Packages\" PREFIX \"Resources\" FILES ${NOESIS_APP_BIN2H})\nsource_group(TREE \"${NOESIS_ROOT}/Include\" PREFIX \"Core\" FILES ${NOESIS_CORE_INCLUDES})\n\nif(UNIX)\n\t# NoesisApp requires several additional libraries on Linux\n\tfind_package(Threads REQUIRED)\n\tfind_package(OpenGL REQUIRED)\n\tfind_package(X11 REQUIRED)\n\ttarget_link_libraries(${PROJECT_NAME}\n\t\tPRIVATE\n\t\t\tOpenGL::GL\n\t\t\tThreads::Threads\n\t\t\t${X11_LIBRARIES}\n\t\t\t${CMAKE_DL_LIBS}\n\t)\nendif()\n"
  },
  {
    "path": "3rdparty/NoesisApp/README.md",
    "content": "Do NOT add the source code here. Noesis is not under a license which would allow redistribution in source code form.\n\nProvide NOESIS_ROOT to CMake and let the source be pulled in from there."
  },
  {
    "path": "3rdparty/NoesisApp/pch.h",
    "content": "#pragma once\n#include <NoesisPCH.h>\n"
  },
  {
    "path": "3rdparty/NoesisApp/register.cpp",
    "content": "////////////////////////////////////////////////////////////////////////////////////////////////////\n// NoesisGUI - http://www.noesisengine.com\n// Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved.\n////////////////////////////////////////////////////////////////////////////////////////////////////\n\n\n#include <NsCore/CompilerSettings.h>\n\n\n#define PACKAGE_REGISTER(MODULE, PACKAGE) \\\n    void NsRegisterReflection##MODULE##PACKAGE(); \\\n    NsRegisterReflection##MODULE##PACKAGE()\n\n#define PACKAGE_INIT(MODULE, PACKAGE) \\\n    void NsInitPackage##MODULE##PACKAGE(); \\\n    NsInitPackage##MODULE##PACKAGE()\n\n#define PACKAGE_SHUTDOWN(MODULE, PACKAGE) \\\n    void NsShutdownPackage##MODULE##PACKAGE(); \\\n    NsShutdownPackage##MODULE##PACKAGE()\n\n\n////////////////////////////////////////////////////////////////////////////////////////////////////\nextern \"C\" void NsRegisterReflection_NoesisApp()\n{\n    PACKAGE_REGISTER(Render, RenderContext);\n    PACKAGE_REGISTER(Render, GLRenderDevice);\n    PACKAGE_REGISTER(App, Display);\n    PACKAGE_REGISTER(Render, GLRenderContext);\n    PACKAGE_REGISTER(App, Providers);\n    PACKAGE_REGISTER(App, Launcher);\n    PACKAGE_REGISTER(App, Theme);\n    PACKAGE_REGISTER(App, DisplayLauncher);\n    PACKAGE_REGISTER(App, ApplicationLauncher);\n\tPACKAGE_REGISTER(App, Interactivity);\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////\nextern \"C\" void NsInitPackages_NoesisApp()\n{\n    PACKAGE_INIT(Render, RenderContext);\n    PACKAGE_INIT(Render, GLRenderDevice);\n    PACKAGE_INIT(App, Display);\n    PACKAGE_INIT(Render, GLRenderContext);\n    PACKAGE_INIT(App, Providers);\n    PACKAGE_INIT(App, Launcher);\n    PACKAGE_INIT(App, Theme);\n    PACKAGE_INIT(App, DisplayLauncher);\n    PACKAGE_INIT(App, ApplicationLauncher);\n\tPACKAGE_INIT(App, Interactivity);\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////////////\nextern \"C\" void NsShutdownPackages_NoesisApp()\n{\n\tPACKAGE_SHUTDOWN(App, Interactivity);\n    PACKAGE_SHUTDOWN(App, ApplicationLauncher);\n    PACKAGE_SHUTDOWN(App, DisplayLauncher);\n    PACKAGE_SHUTDOWN(App, Theme);\n    PACKAGE_SHUTDOWN(App, Launcher);\n    PACKAGE_SHUTDOWN(App, Providers);\n    PACKAGE_SHUTDOWN(Render, GLRenderContext);\n    PACKAGE_SHUTDOWN(App, Display);\n    PACKAGE_SHUTDOWN(Render, GLRenderDevice);\n    PACKAGE_SHUTDOWN(Render, RenderContext);\n}\n"
  },
  {
    "path": "3rdparty/exprtk/CMakeLists.txt",
    "content": "add_library(exprtk)\n\ntarget_include_directories(exprtk\n\tPUBLIC\n\t\t${CMAKE_CURRENT_SOURCE_DIR}\n)\n\ntarget_sources(exprtk\n\tPRIVATE\n\t\texprtk.hpp\n\t\texprtk.cpp\n)"
  },
  {
    "path": "3rdparty/exprtk/exprtk.cpp",
    "content": "#include \"exprtk.hpp\""
  },
  {
    "path": "3rdparty/exprtk/exprtk.hpp",
    "content": "/*\n ******************************************************************\n *           C++ Mathematical Expression Toolkit Library          *\n *                                                                *\n * Author: Arash Partow (1999-2017)                               *\n * URL: http://www.partow.net/programming/exprtk/index.html       *\n *                                                                *\n * Copyright notice:                                              *\n * Free use of the C++ Mathematical Expression Toolkit Library is *\n * permitted under the guidelines and in accordance with the most *\n * current version of the MIT License.                            *\n * http://www.opensource.org/licenses/MIT                         *\n *                                                                *\n * Example expressions:                                           *\n * (00) (y + x / y) * (x - y / x)                                 *\n * (01) (x^2 / sin(2 * pi / y)) - x / 2                           *\n * (02) sqrt(1 - (x^2))                                           *\n * (03) 1 - sin(2 * x) + cos(pi / y)                              *\n * (04) a * exp(2 * t) + c                                        *\n * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)        *\n * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x          *\n * (07) z := x + sin(2 * pi / y)                                  *\n * (08) u := 2 * (pi * z) / (w := x + cos(y / pi))                *\n * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1)            *\n * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)     *\n * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1)  *\n * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *\n *                                                                *\n ******************************************************************\n*/\n\n\n#ifndef INCLUDE_EXPRTK_HPP\n#define INCLUDE_EXPRTK_HPP\n\n\n#include <algorithm>\n#include <cctype>\n#include <cmath>\n#include <complex>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <deque>\n#include <exception>\n#include <functional>\n#include <iterator>\n#include <limits>\n#include <list>\n#include <map>\n#include <set>\n#include <stack>\n#include <stdexcept>\n#include <string>\n#include <utility>\n#include <vector>\n\n\nnamespace exprtk\n{\n   #ifdef exprtk_enable_debugging\n     #define exprtk_debug(params) printf params\n   #else\n     #define exprtk_debug(params) (void)0\n   #endif\n\n   #define exprtk_error_location             \\\n   \"exprtk.hpp:\" + details::to_str(__LINE__) \\\n\n   #if __GNUC__  >= 7\n\n      #define exprtk_disable_fallthrough_begin                      \\\n      _Pragma (\"GCC diagnostic push\")                               \\\n      _Pragma (\"GCC diagnostic ignored \\\"-Wimplicit-fallthrough\\\"\") \\\n\n      #define exprtk_disable_fallthrough_end                        \\\n      _Pragma (\"GCC diagnostic pop\")                                \\\n\n   #else\n      #define exprtk_disable_fallthrough_begin (void)0;\n      #define exprtk_disable_fallthrough_end   (void)0;\n   #endif\n\n   namespace details\n   {\n      typedef unsigned char uchar_t;\n      typedef char           char_t;\n\n      inline bool is_whitespace(const char_t c)\n      {\n         return (' '  == c) || ('\\n' == c) ||\n                ('\\r' == c) || ('\\t' == c) ||\n                ('\\b' == c) || ('\\v' == c) ||\n                ('\\f' == c) ;\n      }\n\n      inline bool is_operator_char(const char_t c)\n      {\n         return ('+' == c) || ('-' == c) ||\n                ('*' == c) || ('/' == c) ||\n                ('^' == c) || ('<' == c) ||\n                ('>' == c) || ('=' == c) ||\n                (',' == c) || ('!' == c) ||\n                ('(' == c) || (')' == c) ||\n                ('[' == c) || (']' == c) ||\n                ('{' == c) || ('}' == c) ||\n                ('%' == c) || (':' == c) ||\n                ('?' == c) || ('&' == c) ||\n                ('|' == c) || (';' == c) ;\n      }\n\n      inline bool is_letter(const char_t c)\n      {\n         return (('a' <= c) && (c <= 'z')) ||\n                (('A' <= c) && (c <= 'Z')) ;\n      }\n\n      inline bool is_digit(const char_t c)\n      {\n         return ('0' <= c) && (c <= '9');\n      }\n\n      inline bool is_letter_or_digit(const char_t c)\n      {\n         return is_letter(c) || is_digit(c);\n      }\n\n      inline bool is_left_bracket(const char_t c)\n      {\n         return ('(' == c) || ('[' == c) || ('{' == c);\n      }\n\n      inline bool is_right_bracket(const char_t c)\n      {\n         return (')' == c) || (']' == c) || ('}' == c);\n      }\n\n      inline bool is_bracket(const char_t c)\n      {\n         return is_left_bracket(c) || is_right_bracket(c);\n      }\n\n      inline bool is_sign(const char_t c)\n      {\n         return ('+' == c) || ('-' == c);\n      }\n\n      inline bool is_invalid(const char_t c)\n      {\n         return !is_whitespace   (c) &&\n                !is_operator_char(c) &&\n                !is_letter       (c) &&\n                !is_digit        (c) &&\n                ('.'  != c)          &&\n                ('_'  != c)          &&\n                ('$'  != c)          &&\n                ('~'  != c)          &&\n                ('\\'' != c);\n      }\n\n      #ifndef exprtk_disable_caseinsensitivity\n      inline void case_normalise(std::string& s)\n      {\n         for (std::size_t i = 0; i < s.size(); ++i)\n         {\n            s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));\n         }\n      }\n\n      inline bool imatch(const char_t c1, const char_t c2)\n      {\n         return std::tolower(c1) == std::tolower(c2);\n      }\n\n      inline bool imatch(const std::string& s1, const std::string& s2)\n      {\n         if (s1.size() == s2.size())\n         {\n            for (std::size_t i = 0; i < s1.size(); ++i)\n            {\n               if (std::tolower(s1[i]) != std::tolower(s2[i]))\n               {\n                  return false;\n               }\n            }\n\n            return true;\n         }\n\n         return false;\n      }\n\n      struct ilesscompare\n      {\n         inline bool operator() (const std::string& s1, const std::string& s2) const\n         {\n            const std::size_t length = std::min(s1.size(),s2.size());\n\n            for (std::size_t i = 0; i < length;  ++i)\n            {\n               const char_t c1 = static_cast<char>(std::tolower(s1[i]));\n               const char_t c2 = static_cast<char>(std::tolower(s2[i]));\n\n               if (c1 > c2)\n                  return false;\n               else if (c1 < c2)\n                  return true;\n            }\n\n            return s1.size() < s2.size();\n         }\n      };\n\n      #else\n      inline void case_normalise(std::string&)\n      {}\n\n      inline bool imatch(const char_t c1, const char_t c2)\n      {\n         return c1 == c2;\n      }\n\n      inline bool imatch(const std::string& s1, const std::string& s2)\n      {\n         return s1 == s2;\n      }\n\n      struct ilesscompare\n      {\n         inline bool operator() (const std::string& s1, const std::string& s2) const\n         {\n            return s1 < s2;\n         }\n      };\n      #endif\n\n      inline bool is_valid_sf_symbol(const std::string& symbol)\n      {\n         // Special function: $f12 or $F34\n         return (4 == symbol.size())  &&\n                ('$' == symbol[0])    &&\n                imatch('f',symbol[1]) &&\n                is_digit(symbol[2])   &&\n                is_digit(symbol[3]);\n      }\n\n      inline const char_t& front(const std::string& s)\n      {\n         return s[0];\n      }\n\n      inline const char_t& back(const std::string& s)\n      {\n         return s[s.size() - 1];\n      }\n\n      inline std::string to_str(int i)\n      {\n         if (0 == i)\n            return std::string(\"0\");\n\n         std::string result;\n\n         if (i < 0)\n         {\n            for ( ; i; i /= 10)\n            {\n               result += '0' + char(-(i % 10));\n            }\n\n            result += '-';\n         }\n         else\n         {\n            for ( ; i; i /= 10)\n            {\n               result += '0' + char(i % 10);\n            }\n         }\n\n         std::reverse(result.begin(), result.end());\n\n         return result;\n      }\n\n      inline std::string to_str(std::size_t i)\n      {\n         return to_str(static_cast<int>(i));\n      }\n\n      inline bool is_hex_digit(const std::string::value_type digit)\n      {\n         return (('0' <= digit) && (digit <= '9')) ||\n                (('A' <= digit) && (digit <= 'F')) ||\n                (('a' <= digit) && (digit <= 'f')) ;\n      }\n\n      inline uchar_t hex_to_bin(uchar_t h)\n      {\n         if (('0' <= h) && (h <= '9'))\n            return (h - '0');\n         else\n            return static_cast<unsigned char>(std::toupper(h) - 'A');\n      }\n\n      template <typename Iterator>\n      inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)\n      {\n         if (\n              (end !=  (itr    )) &&\n              (end !=  (itr + 1)) &&\n              (end !=  (itr + 2)) &&\n              (end !=  (itr + 3)) &&\n              ('0' == *(itr    )) &&\n              (\n                ('x' == *(itr + 1)) ||\n                ('X' == *(itr + 1))\n              ) &&\n              (is_hex_digit(*(itr + 2))) &&\n              (is_hex_digit(*(itr + 3)))\n            )\n         {\n            result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |\n                     hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;\n            itr += 3;\n         }\n         else\n            result = '\\0';\n      }\n\n      inline void cleanup_escapes(std::string& s)\n      {\n         typedef std::string::iterator str_itr_t;\n\n         str_itr_t itr1 = s.begin();\n         str_itr_t itr2 = s.begin();\n         str_itr_t end  = s.end  ();\n\n         std::size_t removal_count  = 0;\n\n         while (end != itr1)\n         {\n            if ('\\\\' == (*itr1))\n            {\n               ++removal_count;\n\n               if (end == ++itr1)\n                  break;\n               else if ('\\\\' != (*itr1))\n               {\n                  switch (*itr1)\n                  {\n                     case 'n' : (*itr1) = '\\n'; break;\n                     case 'r' : (*itr1) = '\\r'; break;\n                     case 't' : (*itr1) = '\\t'; break;\n                     case '0' : parse_hex(itr1, end, (*itr1));\n                                removal_count += 3;\n                                break;\n                  }\n\n                  continue;\n               }\n            }\n\n            if (itr1 != itr2)\n            {\n               (*itr2) = (*itr1);\n            }\n\n            ++itr1;\n            ++itr2;\n         }\n\n         s.resize(s.size() - removal_count);\n      }\n\n      class build_string\n      {\n      public:\n\n         build_string(const std::size_t& initial_size = 64)\n         {\n            data_.reserve(initial_size);\n         }\n\n         inline build_string& operator << (const std::string& s)\n         {\n            data_ += s;\n            return (*this);\n         }\n\n         inline build_string& operator << (const char_t* s)\n         {\n            data_ += std::string(s);\n            return (*this);\n         }\n\n         inline operator std::string () const\n         {\n            return data_;\n         }\n\n         inline std::string as_string() const\n         {\n            return data_;\n         }\n\n      private:\n\n         std::string data_;\n      };\n\n      static const std::string reserved_words[] =\n                                  {\n                                    \"break\",  \"case\",  \"continue\",  \"default\",  \"false\",  \"for\",\n                                    \"if\", \"else\", \"ilike\",  \"in\", \"like\", \"and\",  \"nand\", \"nor\",\n                                    \"not\",  \"null\",  \"or\",   \"repeat\", \"return\",  \"shl\",  \"shr\",\n                                    \"swap\", \"switch\", \"true\",  \"until\", \"var\",  \"while\", \"xnor\",\n                                    \"xor\", \"&\", \"|\"\n                                  };\n\n      static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);\n\n      static const std::string reserved_symbols[] =\n                                  {\n                                    \"abs\",  \"acos\",  \"acosh\",  \"and\",  \"asin\",  \"asinh\", \"atan\",\n                                    \"atanh\", \"atan2\", \"avg\",  \"break\", \"case\", \"ceil\",  \"clamp\",\n                                    \"continue\",   \"cos\",   \"cosh\",   \"cot\",   \"csc\",  \"default\",\n                                    \"deg2grad\",  \"deg2rad\",   \"equal\",  \"erf\",   \"erfc\",  \"exp\",\n                                    \"expm1\",  \"false\",   \"floor\",  \"for\",   \"frac\",  \"grad2deg\",\n                                    \"hypot\", \"iclamp\", \"if\",  \"else\", \"ilike\", \"in\",  \"inrange\",\n                                    \"like\",  \"log\",  \"log10\", \"log2\",  \"logn\",  \"log1p\", \"mand\",\n                                    \"max\", \"min\",  \"mod\", \"mor\",  \"mul\", \"ncdf\",  \"nand\", \"nor\",\n                                    \"not\",   \"not_equal\",   \"null\",   \"or\",   \"pow\",  \"rad2deg\",\n                                    \"repeat\", \"return\", \"root\", \"round\", \"roundn\", \"sec\", \"sgn\",\n                                    \"shl\", \"shr\", \"sin\", \"sinc\", \"sinh\", \"sqrt\",  \"sum\", \"swap\",\n                                    \"switch\", \"tan\",  \"tanh\", \"true\",  \"trunc\", \"until\",  \"var\",\n                                    \"while\", \"xnor\", \"xor\", \"&\", \"|\"\n                                  };\n\n      static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);\n\n      static const std::string base_function_list[] =\n                                  {\n                                    \"abs\", \"acos\",  \"acosh\", \"asin\",  \"asinh\", \"atan\",  \"atanh\",\n                                    \"atan2\",  \"avg\",  \"ceil\",  \"clamp\",  \"cos\",  \"cosh\",  \"cot\",\n                                    \"csc\",  \"equal\",  \"erf\",  \"erfc\",  \"exp\",  \"expm1\", \"floor\",\n                                    \"frac\", \"hypot\", \"iclamp\",  \"like\", \"log\", \"log10\",  \"log2\",\n                                    \"logn\", \"log1p\", \"mand\", \"max\", \"min\", \"mod\", \"mor\",  \"mul\",\n                                    \"ncdf\",  \"pow\",  \"root\",  \"round\",  \"roundn\",  \"sec\", \"sgn\",\n                                    \"sin\", \"sinc\", \"sinh\", \"sqrt\", \"sum\", \"swap\", \"tan\", \"tanh\",\n                                    \"trunc\",  \"not_equal\",  \"inrange\",  \"deg2grad\",   \"deg2rad\",\n                                    \"rad2deg\", \"grad2deg\"\n                                  };\n\n      static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);\n\n      static const std::string logic_ops_list[] =\n                                  {\n                                    \"and\", \"nand\", \"nor\", \"not\", \"or\",  \"xnor\", \"xor\", \"&\", \"|\"\n                                  };\n\n      static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);\n\n      static const std::string cntrl_struct_list[] =\n                                  {\n                                     \"if\", \"switch\", \"for\", \"while\", \"repeat\", \"return\"\n                                  };\n\n      static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);\n\n      static const std::string arithmetic_ops_list[] =\n                                  {\n                                    \"+\", \"-\", \"*\", \"/\", \"%\", \"^\"\n                                  };\n\n      static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);\n\n      static const std::string assignment_ops_list[] =\n                                  {\n                                    \":=\", \"+=\", \"-=\",\n                                    \"*=\", \"/=\", \"%=\"\n                                  };\n\n      static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);\n\n      static const std::string inequality_ops_list[] =\n                                  {\n                                     \"<\",  \"<=\", \"==\",\n                                     \"=\",  \"!=\", \"<>\",\n                                    \">=\",  \">\"\n                                  };\n\n      static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);\n\n      inline bool is_reserved_word(const std::string& symbol)\n      {\n         for (std::size_t i = 0; i < reserved_words_size; ++i)\n         {\n            if (imatch(symbol, reserved_words[i]))\n            {\n               return true;\n            }\n         }\n\n         return false;\n      }\n\n      inline bool is_reserved_symbol(const std::string& symbol)\n      {\n         for (std::size_t i = 0; i < reserved_symbols_size; ++i)\n         {\n            if (imatch(symbol, reserved_symbols[i]))\n            {\n               return true;\n            }\n         }\n\n         return false;\n      }\n\n      inline bool is_base_function(const std::string& function_name)\n      {\n         for (std::size_t i = 0; i < base_function_list_size; ++i)\n         {\n            if (imatch(function_name, base_function_list[i]))\n            {\n               return true;\n            }\n         }\n\n         return false;\n      }\n\n      inline bool is_control_struct(const std::string& cntrl_strct)\n      {\n         for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)\n         {\n            if (imatch(cntrl_strct, cntrl_struct_list[i]))\n            {\n               return true;\n            }\n         }\n\n         return false;\n      }\n\n      inline bool is_logic_opr(const std::string& lgc_opr)\n      {\n         for (std::size_t i = 0; i < logic_ops_list_size; ++i)\n         {\n            if (imatch(lgc_opr, logic_ops_list[i]))\n            {\n               return true;\n            }\n         }\n\n         return false;\n      }\n\n      struct cs_match\n      {\n         static inline bool cmp(const char_t c0, const char_t c1)\n         {\n            return (c0 == c1);\n         }\n      };\n\n      struct cis_match\n      {\n         static inline bool cmp(const char_t c0, const char_t c1)\n         {\n            return (std::tolower(c0) == std::tolower(c1));\n         }\n      };\n\n      template <typename Iterator, typename Compare>\n      inline bool match_impl(const Iterator pattern_begin,\n                             const Iterator pattern_end,\n                             const Iterator data_begin,\n                             const Iterator data_end,\n                             const typename std::iterator_traits<Iterator>::value_type& zero_or_more,\n                             const typename std::iterator_traits<Iterator>::value_type& zero_or_one)\n      {\n         if (0 == std::distance(data_begin,data_end))\n         {\n            return false;\n         }\n\n         Iterator d_itr = data_begin;\n         Iterator p_itr = pattern_begin;\n         Iterator c_itr = data_begin;\n         Iterator m_itr = data_begin;\n\n         while ((data_end != d_itr) && (zero_or_more != (*p_itr)))\n         {\n            if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))\n            {\n               return false;\n            }\n\n            ++p_itr;\n            ++d_itr;\n         }\n\n         while (data_end != d_itr)\n         {\n            if (zero_or_more == (*p_itr))\n            {\n               if (pattern_end == (++p_itr))\n               {\n                  return true;\n               }\n\n               m_itr = p_itr;\n               c_itr = d_itr;\n               ++c_itr;\n            }\n            else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))\n            {\n               ++p_itr;\n               ++d_itr;\n            }\n            else\n            {\n               p_itr = m_itr;\n               d_itr = c_itr++;\n            }\n         }\n\n         while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) { ++p_itr; }\n\n         return (p_itr == pattern_end);\n      }\n\n      inline bool wc_match(const std::string& wild_card,\n                           const std::string& str)\n      {\n         return match_impl<const char_t*,cs_match>(wild_card.data(),\n                                                   wild_card.data() + wild_card.size(),\n                                                   str.data(),\n                                                   str.data() + str.size(),\n                                                   '*',\n                                                   '?');\n      }\n\n      inline bool wc_imatch(const std::string& wild_card,\n                            const std::string& str)\n      {\n         return match_impl<const char_t*,cis_match>(wild_card.data(),\n                                                    wild_card.data() + wild_card.size(),\n                                                    str.data(),\n                                                    str.data() + str.size(),\n                                                    '*',\n                                                    '?');\n      }\n\n      inline bool sequence_match(const std::string& pattern,\n                                 const std::string& str,\n                                 std::size_t&       diff_index,\n                                 char_t&            diff_value)\n      {\n         if (str.empty())\n         {\n            return (\"Z\" == pattern);\n         }\n         else if ('*' == pattern[0])\n            return false;\n\n         typedef std::string::const_iterator itr_t;\n\n         itr_t p_itr = pattern.begin();\n         itr_t s_itr = str    .begin();\n\n         itr_t p_end = pattern.end();\n         itr_t s_end = str    .end();\n\n         while ((s_end != s_itr) && (p_end != p_itr))\n         {\n            if ('*' == (*p_itr))\n            {\n               const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));\n\n               if ('*' == target)\n               {\n                  diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));\n                  diff_value = static_cast<char>(std::toupper(*p_itr));\n\n                  return false;\n               }\n               else\n                  ++p_itr;\n\n               while (s_itr != s_end)\n               {\n                  if (target != std::toupper(*s_itr))\n                     break;\n                  else\n                     ++s_itr;\n               }\n\n               continue;\n            }\n            else if (\n                      ('?' != *p_itr) &&\n                      std::toupper(*p_itr) != std::toupper(*s_itr)\n                    )\n            {\n               diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));\n               diff_value = static_cast<char>(std::toupper(*p_itr));\n\n               return false;\n            }\n\n            ++p_itr;\n            ++s_itr;\n         }\n\n         return (\n                  (s_end == s_itr) &&\n                  (\n                    (p_end ==  p_itr) ||\n                    ('*'   == *p_itr)\n                  )\n                );\n      }\n\n      static const double pow10[] = {\n                                      1.0,\n                                      1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,\n                                      1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,\n                                      1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,\n                                      1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016\n                                    };\n\n     static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);\n\n      namespace numeric\n      {\n         namespace constant\n         {\n            static const double e       =  2.71828182845904523536028747135266249775724709369996;\n            static const double pi      =  3.14159265358979323846264338327950288419716939937510;\n            static const double pi_2    =  1.57079632679489661923132169163975144209858469968755;\n            static const double pi_4    =  0.78539816339744830961566084581987572104929234984378;\n            static const double pi_180  =  0.01745329251994329576923690768488612713442871888542;\n            static const double _1_pi   =  0.31830988618379067153776752674502872406891929148091;\n            static const double _2_pi   =  0.63661977236758134307553505349005744813783858296183;\n            static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;\n            static const double log2    =  0.69314718055994530941723212145817656807550013436026;\n            static const double sqrt2   =  1.41421356237309504880168872420969807856967187537695;\n         }\n\n         namespace details\n         {\n            struct unknown_type_tag { unknown_type_tag() {} };\n            struct real_type_tag    { real_type_tag   () {} };\n            struct complex_type_tag { complex_type_tag() {} };\n            struct int_type_tag     { int_type_tag    () {} };\n\n            template <typename T>\n            struct number_type\n            {\n               typedef unknown_type_tag type;\n               number_type() {}\n            };\n\n            #define exprtk_register_real_type_tag(T)             \\\n            template<> struct number_type<T>                     \\\n            { typedef real_type_tag type; number_type() {} };    \\\n\n            #define exprtk_register_complex_type_tag(T)          \\\n            template<> struct number_type<std::complex<T> >      \\\n            { typedef complex_type_tag type; number_type() {} }; \\\n\n            #define exprtk_register_int_type_tag(T)              \\\n            template<> struct number_type<T>                     \\\n            { typedef int_type_tag type; number_type() {} };     \\\n\n            exprtk_register_real_type_tag(double     )\n            exprtk_register_real_type_tag(long double)\n            exprtk_register_real_type_tag(float      )\n\n            exprtk_register_complex_type_tag(double     )\n            exprtk_register_complex_type_tag(long double)\n            exprtk_register_complex_type_tag(float      )\n\n            exprtk_register_int_type_tag(short                 )\n            exprtk_register_int_type_tag(int                   )\n            exprtk_register_int_type_tag(long long int         )\n            exprtk_register_int_type_tag(unsigned short        )\n            exprtk_register_int_type_tag(unsigned int          )\n            exprtk_register_int_type_tag(unsigned long long int)\n\n            #undef exprtk_register_real_type_tag\n            #undef exprtk_register_int_type_tag\n\n            template <typename T>\n            struct epsilon_type\n            {\n               static inline T value()\n               {\n                  const T epsilon = T(0.0000000001);\n                  return epsilon;\n               }\n            };\n\n            template <>\n            struct epsilon_type <float>\n            {\n               static inline float value()\n               {\n                  const float epsilon = float(0.000001f);\n                  return epsilon;\n               }\n            };\n\n            template <>\n            struct epsilon_type <long double>\n            {\n               static inline long double value()\n               {\n                  const long double epsilon = (long double)(0.000000000001);\n                  return epsilon;\n               }\n            };\n\n            template <typename T>\n            inline bool is_nan_impl(const T v, real_type_tag)\n            {\n               return std::not_equal_to<T>()(v,v);\n            }\n\n            template <typename T>\n            inline int to_int32_impl(const T v, real_type_tag)\n            {\n               return static_cast<int>(v);\n            }\n\n            template <typename T>\n            inline long long int to_int64_impl(const T v, real_type_tag)\n            {\n               return static_cast<long long int>(v);\n            }\n\n            template <typename T>\n            inline bool is_true_impl(const T v)\n            {\n               return std::not_equal_to<T>()(T(0),v);\n            }\n\n            template <typename T>\n            inline bool is_false_impl(const T v)\n            {\n               return std::equal_to<T>()(T(0),v);\n            }\n\n            template <typename T>\n            inline T abs_impl(const T v, real_type_tag)\n            {\n               return ((v < T(0)) ? -v : v);\n            }\n\n            template <typename T>\n            inline T min_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::min<T>(v0,v1);\n            }\n\n            template <typename T>\n            inline T max_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::max<T>(v0,v1);\n            }\n\n            template <typename T>\n            inline T equal_impl(const T v0, const T v1, real_type_tag)\n            {\n               const T epsilon = epsilon_type<T>::value();\n               return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);\n            }\n\n            inline float equal_impl(const float v0, const float v1, real_type_tag)\n            {\n               const float epsilon = epsilon_type<float>::value();\n               return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;\n            }\n\n            template <typename T>\n            inline T equal_impl(const T v0, const T v1, int_type_tag)\n            {\n               return (v0 == v1) ? 1 : 0;\n            }\n\n            template <typename T>\n            inline T expm1_impl(const T v, real_type_tag)\n            {\n               // return std::expm1<T>(v);\n               if (abs_impl(v,real_type_tag()) < T(0.00001))\n                  return v + (T(0.5) * v * v);\n               else\n                  return std::exp(v) - T(1);\n            }\n\n            template <typename T>\n            inline T expm1_impl(const T v, int_type_tag)\n            {\n               return T(std::exp<double>(v)) - T(1);\n            }\n\n            template <typename T>\n            inline T nequal_impl(const T v0, const T v1, real_type_tag)\n            {\n               typedef real_type_tag rtg;\n               const T epsilon = epsilon_type<T>::value();\n               return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);\n            }\n\n            inline float nequal_impl(const float v0, const float v1, real_type_tag)\n            {\n               typedef real_type_tag rtg;\n               const float epsilon = epsilon_type<float>::value();\n               return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;\n            }\n\n            template <typename T>\n            inline T nequal_impl(const T v0, const T v1, int_type_tag)\n            {\n               return (v0 != v1) ? 1 : 0;\n            }\n\n            template <typename T>\n            inline T modulus_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::fmod(v0,v1);\n            }\n\n            template <typename T>\n            inline T modulus_impl(const T v0, const T v1, int_type_tag)\n            {\n               return v0 % v1;\n            }\n\n            template <typename T>\n            inline T pow_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::pow(v0,v1);\n            }\n\n            template <typename T>\n            inline T pow_impl(const T v0, const T v1, int_type_tag)\n            {\n               return std::pow(static_cast<double>(v0),static_cast<double>(v1));\n            }\n\n            template <typename T>\n            inline T logn_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::log(v0) / std::log(v1);\n            }\n\n            template <typename T>\n            inline T logn_impl(const T v0, const T v1, int_type_tag)\n            {\n               return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));\n            }\n\n            template <typename T>\n            inline T log1p_impl(const T v, real_type_tag)\n            {\n               if (v > T(-1))\n               {\n                  if (abs_impl(v,real_type_tag()) > T(0.0001))\n                  {\n                     return std::log(T(1) + v);\n                  }\n                  else\n                     return (T(-0.5) * v + T(1)) * v;\n               }\n               else\n                  return std::numeric_limits<T>::quiet_NaN();\n            }\n\n            template <typename T>\n            inline T log1p_impl(const T v, int_type_tag)\n            {\n               if (v > T(-1))\n               {\n                  return std::log(T(1) + v);\n               }\n               else\n                  return std::numeric_limits<T>::quiet_NaN();\n            }\n\n            template <typename T>\n            inline T root_impl(const T v0, const T v1, real_type_tag)\n            {\n               if (v1 < T(0))\n                  return std::numeric_limits<T>::quiet_NaN();\n\n               const std::size_t n = static_cast<std::size_t>(v1);\n\n               if ((v0 < T(0)) && (0 == (n % 2)))\n                  return std::numeric_limits<T>::quiet_NaN();\n\n               return std::pow(v0, T(1) / n);\n            }\n\n            template <typename T>\n            inline T root_impl(const T v0, const T v1, int_type_tag)\n            {\n               return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());\n            }\n\n            template <typename T>\n            inline T round_impl(const T v, real_type_tag)\n            {\n               return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));\n            }\n\n            template <typename T>\n            inline T roundn_impl(const T v0, const T v1, real_type_tag)\n            {\n               const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));\n               const T p10 = T(pow10[index]);\n\n               if (v0 < T(0))\n                  return T(std::ceil ((v0 * p10) - T(0.5)) / p10);\n               else\n                  return T(std::floor((v0 * p10) + T(0.5)) / p10);\n            }\n\n            template <typename T>\n            inline T roundn_impl(const T v0, const T, int_type_tag)\n            {\n               return v0;\n            }\n\n            template <typename T>\n            inline T hypot_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::sqrt((v0 * v0) + (v1 * v1));\n            }\n\n            template <typename T>\n            inline T hypot_impl(const T v0, const T v1, int_type_tag)\n            {\n               return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));\n            }\n\n            template <typename T>\n            inline T atan2_impl(const T v0, const T v1, real_type_tag)\n            {\n               return std::atan2(v0,v1);\n            }\n\n            template <typename T>\n            inline T atan2_impl(const T, const T, int_type_tag)\n            {\n               return 0;\n            }\n\n            template <typename T>\n            inline T shr_impl(const T v0, const T v1, real_type_tag)\n            {\n               return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));\n            }\n\n            template <typename T>\n            inline T shr_impl(const T v0, const T v1, int_type_tag)\n            {\n               return v0 >> v1;\n            }\n\n            template <typename T>\n            inline T shl_impl(const T v0, const T v1, real_type_tag)\n            {\n               return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));\n            }\n\n            template <typename T>\n            inline T shl_impl(const T v0, const T v1, int_type_tag)\n            {\n               return v0 << v1;\n            }\n\n            template <typename T>\n            inline T sgn_impl(const T v, real_type_tag)\n            {\n                    if (v > T(0)) return T(+1);\n               else if (v < T(0)) return T(-1);\n               else               return T( 0);\n            }\n\n            template <typename T>\n            inline T sgn_impl(const T v, int_type_tag)\n            {\n                    if (v > T(0)) return T(+1);\n               else if (v < T(0)) return T(-1);\n               else               return T( 0);\n            }\n\n            template <typename T>\n            inline T and_impl(const T v0, const T v1, real_type_tag)\n            {\n               return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);\n            }\n\n            template <typename T>\n            inline T and_impl(const T v0, const T v1, int_type_tag)\n            {\n               return v0 && v1;\n            }\n\n            template <typename T>\n            inline T nand_impl(const T v0, const T v1, real_type_tag)\n            {\n               return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);\n            }\n\n            template <typename T>\n            inline T nand_impl(const T v0, const T v1, int_type_tag)\n            {\n               return !(v0 && v1);\n            }\n\n            template <typename T>\n            inline T or_impl(const T v0, const T v1, real_type_tag)\n            {\n               return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);\n            }\n\n            template <typename T>\n            inline T or_impl(const T v0, const T v1, int_type_tag)\n            {\n               return (v0 || v1);\n            }\n\n            template <typename T>\n            inline T nor_impl(const T v0, const T v1, real_type_tag)\n            {\n               return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);\n            }\n\n            template <typename T>\n            inline T nor_impl(const T v0, const T v1, int_type_tag)\n            {\n               return !(v0 || v1);\n            }\n\n            template <typename T>\n            inline T xor_impl(const T v0, const T v1, real_type_tag)\n            {\n               return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);\n            }\n\n            template <typename T>\n            inline T xor_impl(const T v0, const T v1, int_type_tag)\n            {\n               return v0 ^ v1;\n            }\n\n            template <typename T>\n            inline T xnor_impl(const T v0, const T v1, real_type_tag)\n            {\n               const bool v0_true = is_true_impl(v0);\n               const bool v1_true = is_true_impl(v1);\n\n               if ((v0_true &&  v1_true) || (!v0_true && !v1_true))\n                  return T(1);\n               else\n                  return T(0);\n            }\n\n            template <typename T>\n            inline T xnor_impl(const T v0, const T v1, int_type_tag)\n            {\n               const bool v0_true = is_true_impl(v0);\n               const bool v1_true = is_true_impl(v1);\n\n               if ((v0_true &&  v1_true) || (!v0_true && !v1_true))\n                  return T(1);\n               else\n                  return T(0);\n            }\n\n            #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)\n            #define exprtk_define_erf(TT,impl)           \\\n            inline TT erf_impl(TT v) { return impl(v); } \\\n\n            exprtk_define_erf(      float,::erff)\n            exprtk_define_erf(     double,::erf )\n            exprtk_define_erf(long double,::erfl)\n            #undef exprtk_define_erf\n            #endif\n\n            template <typename T>\n            inline T erf_impl(T v, real_type_tag)\n            {\n               #if defined(_MSC_VER) && (_MSC_VER < 1900)\n               // Credits: Abramowitz & Stegun Equations 7.1.25-28\n               static const T c[] = {\n                                      T( 1.26551223), T(1.00002368),\n                                      T( 0.37409196), T(0.09678418),\n                                      T(-0.18628806), T(0.27886807),\n                                      T(-1.13520398), T(1.48851587),\n                                      T(-0.82215223), T(0.17087277)\n                                    };\n\n               const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));\n\n               T result = T(1) - t * std::exp((-v * v) -\n                                      c[0] + t * (c[1] + t *\n                                     (c[2] + t * (c[3] + t *\n                                     (c[4] + t * (c[5] + t *\n                                     (c[6] + t * (c[7] + t *\n                                     (c[8] + t * (c[9]))))))))));\n\n               return (v >= T(0)) ? result : -result;\n               #else\n               return erf_impl(v);\n               #endif\n            }\n\n            template <typename T>\n            inline T erf_impl(T v, int_type_tag)\n            {\n               return erf_impl(static_cast<double>(v),real_type_tag());\n            }\n\n            #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)\n            #define exprtk_define_erfc(TT,impl)           \\\n            inline TT erfc_impl(TT v) { return impl(v); } \\\n\n            exprtk_define_erfc(      float,::erfcf)\n            exprtk_define_erfc(     double,::erfc )\n            exprtk_define_erfc(long double,::erfcl)\n            #undef exprtk_define_erfc\n            #endif\n\n            template <typename T>\n            inline T erfc_impl(T v, real_type_tag)\n            {\n               #if defined(_MSC_VER) && (_MSC_VER < 1900)\n               return T(1) - erf_impl(v,real_type_tag());\n               #else\n               return erfc_impl(v);\n               #endif\n            }\n\n            template <typename T>\n            inline T erfc_impl(T v, int_type_tag)\n            {\n               return erfc_impl(static_cast<double>(v),real_type_tag());\n            }\n\n            template <typename T>\n            inline T ncdf_impl(T v, real_type_tag)\n            {\n               T cnd = T(0.5) * (T(1) + erf_impl(\n                                           abs_impl(v,real_type_tag()) /\n                                           T(numeric::constant::sqrt2),real_type_tag()));\n               return  (v < T(0)) ? (T(1) - cnd) : cnd;\n            }\n\n            template <typename T>\n            inline T ncdf_impl(T v, int_type_tag)\n            {\n               return ncdf_impl(static_cast<double>(v),real_type_tag());\n            }\n\n            template <typename T>\n            inline T sinc_impl(T v, real_type_tag)\n            {\n               if (std::abs(v) >= std::numeric_limits<T>::epsilon())\n                   return(std::sin(v) / v);\n               else\n                  return T(1);\n            }\n\n            template <typename T>\n            inline T sinc_impl(T v, int_type_tag)\n            {\n               return sinc_impl(static_cast<double>(v),real_type_tag());\n            }\n\n            template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }\n            template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }\n            template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }\n            template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }\n            template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }\n            template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); }\n            template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }\n            template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }\n            template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }\n            template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }\n            template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }\n            template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }\n            template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }\n            template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }\n            template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }\n            template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }\n            template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }\n            template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }\n            template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }\n            template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }\n            template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }\n            template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }\n            template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }\n            template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }\n            template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }\n            template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }\n            template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }\n            template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }\n            template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }\n            template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }\n            template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }\n\n            template <typename T> inline T const_pi_impl(real_type_tag) { return numeric::constant::pi; }\n            template <typename T> inline T const_e_impl (real_type_tag) { return numeric::constant::e;  }\n\n            template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }\n            template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }\n            template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }\n            template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }\n            template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }\n            template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }\n            template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }\n            template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }\n            template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }\n            template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }\n            template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }\n            template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }\n            template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }\n            template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }\n            template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n            template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }\n\n            template <typename T>\n            inline bool is_integer_impl(const T& v, real_type_tag)\n            {\n               return std::equal_to<T>()(T(0),std::fmod(v,T(1)));\n            }\n\n            template <typename T>\n            inline bool is_integer_impl(const T&, int_type_tag)\n            {\n               return true;\n            }\n         }\n\n         template <typename Type>\n         struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };\n\n         template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length = 9}; };\n         template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };\n         template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };\n         template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };\n\n         template <typename T>\n         inline int to_int32(const T v)\n         {\n            const typename details::number_type<T>::type num_type;\n            return to_int32_impl(v, num_type);\n         }\n\n         template <typename T>\n         inline long long int to_int64(const T v)\n         {\n            const typename details::number_type<T>::type num_type;\n            return to_int64_impl(v, num_type);\n         }\n\n         template <typename T>\n         inline bool is_nan(const T v)\n         {\n            const typename details::number_type<T>::type num_type;\n            return is_nan_impl(v, num_type);\n         }\n\n         template <typename T>\n         inline T min(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return min_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T max(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return max_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T equal(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return equal_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T nequal(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return nequal_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T modulus(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return modulus_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T pow(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return pow_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T logn(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return logn_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T root(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return root_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T roundn(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return roundn_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T hypot(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return hypot_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T atan2(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return atan2_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T shr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return shr_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T shl(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return shl_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T and_opr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return and_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T nand_opr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return nand_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T or_opr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return or_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T nor_opr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return nor_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T xor_opr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return xor_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline T xnor_opr(const T v0, const T v1)\n         {\n            const typename details::number_type<T>::type num_type;\n            return xnor_impl(v0, v1, num_type);\n         }\n\n         template <typename T>\n         inline bool is_integer(const T v)\n         {\n            const typename details::number_type<T>::type num_type;\n            return is_integer_impl(v, num_type);\n         }\n\n         template <typename T, unsigned int N>\n         struct fast_exp\n         {\n            static inline T result(T v)\n            {\n               unsigned int k = N;\n               T l = T(1);\n\n               while (k)\n               {\n                  if (k & 1)\n                  {\n                     l *= v;\n                     --k;\n                  }\n\n                  v *= v;\n                  k >>= 1;\n               }\n\n               return l;\n            }\n         };\n\n         template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };\n         template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };\n         template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };\n         template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };\n         template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };\n         template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };\n         template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };\n         template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };\n         template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };\n         template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };\n         template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };\n\n         #define exprtk_define_unary_function(FunctionName)        \\\n         template <typename T>                                     \\\n         inline T FunctionName (const T v)                         \\\n         {                                                         \\\n            const typename details::number_type<T>::type num_type; \\\n            return  FunctionName##_impl(v,num_type);               \\\n         }                                                         \\\n\n         exprtk_define_unary_function(abs  )\n         exprtk_define_unary_function(acos )\n         exprtk_define_unary_function(acosh)\n         exprtk_define_unary_function(asin )\n         exprtk_define_unary_function(asinh)\n         exprtk_define_unary_function(atan )\n         exprtk_define_unary_function(atanh)\n         exprtk_define_unary_function(ceil )\n         exprtk_define_unary_function(cos  )\n         exprtk_define_unary_function(cosh )\n         exprtk_define_unary_function(exp  )\n         exprtk_define_unary_function(expm1)\n         exprtk_define_unary_function(floor)\n         exprtk_define_unary_function(log  )\n         exprtk_define_unary_function(log10)\n         exprtk_define_unary_function(log2 )\n         exprtk_define_unary_function(log1p)\n         exprtk_define_unary_function(neg  )\n         exprtk_define_unary_function(pos  )\n         exprtk_define_unary_function(round)\n         exprtk_define_unary_function(sin  )\n         exprtk_define_unary_function(sinc )\n         exprtk_define_unary_function(sinh )\n         exprtk_define_unary_function(sqrt )\n         exprtk_define_unary_function(tan  )\n         exprtk_define_unary_function(tanh )\n         exprtk_define_unary_function(cot  )\n         exprtk_define_unary_function(sec  )\n         exprtk_define_unary_function(csc  )\n         exprtk_define_unary_function(r2d  )\n         exprtk_define_unary_function(d2r  )\n         exprtk_define_unary_function(d2g  )\n         exprtk_define_unary_function(g2d  )\n         exprtk_define_unary_function(notl )\n         exprtk_define_unary_function(sgn  )\n         exprtk_define_unary_function(erf  )\n         exprtk_define_unary_function(erfc )\n         exprtk_define_unary_function(ncdf )\n         exprtk_define_unary_function(frac )\n         exprtk_define_unary_function(trunc)\n         #undef exprtk_define_unary_function\n      }\n\n      template <typename T>\n      inline T compute_pow10(T d, const int exponent)\n      {\n         static const double fract10[] =\n         {\n           0.0,\n           1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,\n           1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,\n           1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,\n           1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,\n           1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,\n           1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,\n           1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,\n           1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,\n           1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,\n           1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,\n           1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,\n           1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,\n           1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,\n           1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,\n           1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,\n           1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,\n           1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,\n           1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,\n           1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,\n           1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,\n           1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,\n           1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,\n           1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,\n           1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,\n           1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,\n           1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,\n           1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,\n           1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,\n           1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,\n           1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,\n           1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308\n         };\n\n         static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));\n\n         const int e = std::abs(exponent);\n\n         if (exponent >= std::numeric_limits<T>::min_exponent10)\n         {\n            if (e < fract10_size)\n            {\n               if (exponent > 0)\n                  return T(d * fract10[e]);\n               else\n                  return T(d / fract10[e]);\n            }\n            else\n               return T(d * std::pow(10.0, 10.0 * exponent));\n         }\n         else\n         {\n                     d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);\n            return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);\n         }\n      }\n\n      template <typename Iterator, typename T>\n      inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)\n      {\n         if (itr == end)\n            return false;\n\n         const bool negative = ('-' == (*itr));\n\n         if (negative || ('+' == (*itr)))\n         {\n            if (end == ++itr)\n               return false;\n         }\n\n         static const uchar_t zero = static_cast<uchar_t>('0');\n\n         while ((end != itr) && (zero == (*itr))) ++itr;\n\n         bool return_result = true;\n         unsigned int digit = 0;\n         const std::size_t length  = static_cast<std::size_t>(std::distance(itr,end));\n\n         if (length <= 4)\n         {\n            exprtk_disable_fallthrough_begin\n            switch (length)\n            {\n               #ifdef exprtk_use_lut\n\n               #define exprtk_process_digit                          \\\n               if ((digit = details::digit_table[(int)*itr++]) < 10) \\\n                  result = result * 10 + (digit);                    \\\n               else                                                  \\\n               {                                                     \\\n                  return_result = false;                             \\\n                  break;                                             \\\n               }                                                     \\\n\n               #else\n\n               #define exprtk_process_digit         \\\n               if ((digit = (*itr++ - zero)) < 10)  \\\n                  result = result * T(10) + digit;  \\\n               else                                 \\\n               {                                    \\\n                  return_result = false;            \\\n                  break;                            \\\n               }                                    \\\n\n               #endif\n\n               case  4 : exprtk_process_digit\n               case  3 : exprtk_process_digit\n               case  2 : exprtk_process_digit\n               case  1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }\n\n               #undef exprtk_process_digit\n            }\n            exprtk_disable_fallthrough_end\n         }\n         else\n            return_result = false;\n\n         if (length && return_result)\n         {\n            result = result * 10 + static_cast<T>(digit);\n            ++itr;\n         }\n\n         result = negative ? -result : result;\n         return return_result;\n      }\n\n      template <typename Iterator, typename T>\n      static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)\n      {\n         typedef typename std::iterator_traits<Iterator>::value_type type;\n\n         static const std::size_t nan_length = 3;\n\n         if (std::distance(itr,end) != static_cast<int>(nan_length))\n            return false;\n\n         if (static_cast<type>('n') == (*itr))\n         {\n            if (\n                 (static_cast<type>('a') != *(itr + 1)) ||\n                 (static_cast<type>('n') != *(itr + 2))\n               )\n            {\n               return false;\n            }\n         }\n         else if (\n                   (static_cast<type>('A') != *(itr + 1)) ||\n                   (static_cast<type>('N') != *(itr + 2))\n                 )\n         {\n            return false;\n         }\n\n         t = std::numeric_limits<T>::quiet_NaN();\n\n         return true;\n      }\n\n      template <typename Iterator, typename T>\n      static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)\n      {\n         static const char_t inf_uc[] = \"INFINITY\";\n         static const char_t inf_lc[] = \"infinity\";\n         static const std::size_t inf_length = 8;\n\n         const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));\n\n         if ((3 != length) && (inf_length != length))\n            return false;\n\n         const char_t* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;\n\n         while (end != itr)\n         {\n            if (*inf_itr == static_cast<char>(*itr))\n            {\n               ++itr;\n               ++inf_itr;\n               continue;\n            }\n            else\n               return false;\n         }\n\n         if (negative)\n            t = -std::numeric_limits<T>::infinity();\n         else\n            t =  std::numeric_limits<T>::infinity();\n\n         return true;\n      }\n\n      template <typename Iterator, typename T>\n      inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)\n      {\n         if (end == itr_external) return false;\n\n         Iterator itr = itr_external;\n\n         T d = T(0);\n\n         const bool negative = ('-' == (*itr));\n\n         if (negative || '+' == (*itr))\n         {\n            if (end == ++itr)\n               return false;\n         }\n\n         bool instate = false;\n\n         static const char zero = static_cast<uchar_t>('0');\n\n         #define parse_digit_1(d)          \\\n         if ((digit = (*itr - zero)) < 10) \\\n            { d = d * T(10) + digit; }     \\\n         else                              \\\n            { break; }                     \\\n         if (end == ++itr) break;          \\\n\n         #define parse_digit_2(d)          \\\n         if ((digit = (*itr - zero)) < 10) \\\n            { d = d * T(10) + digit; }     \\\n         else { break; }                   \\\n            ++itr;                         \\\n\n         if ('.' != (*itr))\n         {\n            const Iterator curr = itr;\n\n            while ((end != itr) && (zero == (*itr))) ++itr;\n\n            unsigned int digit;\n\n            while (end != itr)\n            {\n               // Note: For 'physical' superscalar architectures it\n               // is advised that the following loop be: 4xPD1 and 1xPD2\n               #ifdef exprtk_enable_superscalar\n               parse_digit_1(d)\n               parse_digit_1(d)\n               #endif\n               parse_digit_1(d)\n               parse_digit_1(d)\n               parse_digit_2(d)\n            }\n\n            if (curr != itr) instate = true;\n         }\n\n         int exponent = 0;\n\n         if (end != itr)\n         {\n            if ('.' == (*itr))\n            {\n               const Iterator curr = ++itr;\n               unsigned int digit;\n               T tmp_d = T(0);\n\n               while (end != itr)\n               {\n                  #ifdef exprtk_enable_superscalar\n                  parse_digit_1(tmp_d)\n                  parse_digit_1(tmp_d)\n                  parse_digit_1(tmp_d)\n                  #endif\n                  parse_digit_1(tmp_d)\n                  parse_digit_1(tmp_d)\n                  parse_digit_2(tmp_d)\n               }\n\n               if (curr != itr)\n               {\n                  instate = true;\n                  d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));\n               }\n\n               #undef parse_digit_1\n               #undef parse_digit_2\n            }\n\n            if (end != itr)\n            {\n               typename std::iterator_traits<Iterator>::value_type c = (*itr);\n\n               if (('e' == c) || ('E' == c))\n               {\n                  int exp = 0;\n\n                  if (!details::string_to_type_converter_impl_ref(++itr, end, exp))\n                  {\n                     if (end == itr)\n                        return false;\n                     else\n                        c = (*itr);\n                  }\n\n                  exponent += exp;\n               }\n\n               if (end != itr)\n               {\n                  if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))\n                     ++itr;\n                  else if ('#' == c)\n                  {\n                     if (end == ++itr)\n                        return false;\n                     else if (('I' <= (*itr)) && ((*itr) <= 'n'))\n                     {\n                        if (('i' == (*itr)) || ('I' == (*itr)))\n                        {\n                           return parse_inf(itr, end, t, negative);\n                        }\n                        else if (('n' == (*itr)) || ('N' == (*itr)))\n                        {\n                           return parse_nan(itr, end, t);\n                        }\n                        else\n                           return false;\n                     }\n                     else\n                        return false;\n                  }\n                  else if (('I' <= (*itr)) && ((*itr) <= 'n'))\n                  {\n                     if (('i' == (*itr)) || ('I' == (*itr)))\n                     {\n                        return parse_inf(itr, end, t, negative);\n                     }\n                     else if (('n' == (*itr)) || ('N' == (*itr)))\n                     {\n                        return parse_nan(itr, end, t);\n                     }\n                     else\n                        return false;\n                  }\n                  else\n                     return false;\n               }\n            }\n         }\n\n         if ((end != itr) || (!instate))\n            return false;\n         else if (exponent)\n            d = compute_pow10(d,exponent);\n\n         t = static_cast<T>((negative) ? -d : d);\n         return true;\n      }\n\n      template <typename T>\n      inline bool string_to_real(const std::string& s, T& t)\n      {\n         const typename numeric::details::number_type<T>::type num_type;\n\n         const char_t* begin = s.data();\n         const char_t* end   = s.data() + s.size();\n\n         return string_to_real(begin, end, t, num_type);\n      }\n\n      template <typename T>\n      struct functor_t\n      {\n         /*\n            Note: The following definitions for Type, may require tweaking\n                  based on the compiler and target architecture. The benchmark\n                  should provide enough information to make the right choice.\n         */\n         //typedef T Type;\n         //typedef const T Type;\n         typedef const T& Type;\n         typedef       T& RefType;\n         typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);\n         typedef T (*tfunc_t)(Type t0, Type t1, Type t2);\n         typedef T (*bfunc_t)(Type t0, Type t1);\n         typedef T (*ufunc_t)(Type t0);\n      };\n\n   } // namespace details\n\n   namespace lexer\n   {\n      struct token\n      {\n         enum token_type\n         {\n            e_none        =   0, e_error       =   1, e_err_symbol  =   2,\n            e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,\n            e_eof         =   6, e_number      =   7, e_symbol      =   8,\n            e_string      =   9, e_assign      =  10, e_addass      =  11,\n            e_subass      =  12, e_mulass      =  13, e_divass      =  14,\n            e_modass      =  15, e_shr         =  16, e_shl         =  17,\n            e_lte         =  18, e_ne          =  19, e_gte         =  20,\n            e_swap        =  21, e_lt          = '<', e_gt          = '>',\n            e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',\n            e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',\n            e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',\n            e_sub         = '-', e_div         = '/', e_mul         = '*',\n            e_mod         = '%', e_pow         = '^', e_colon       = ':',\n            e_ternary     = '?'\n         };\n\n         token()\n         : type(e_none),\n           value(\"\"),\n           position(std::numeric_limits<std::size_t>::max())\n         {}\n\n         void clear()\n         {\n            type     = e_none;\n            value    = \"\";\n            position = std::numeric_limits<std::size_t>::max();\n         }\n\n         template <typename Iterator>\n         inline token& set_operator(const token_type tt,\n                                    const Iterator begin, const Iterator end,\n                                    const Iterator base_begin = Iterator(0))\n         {\n            type = tt;\n            value.assign(begin,end);\n            if (base_begin)\n               position = static_cast<std::size_t>(std::distance(base_begin,begin));\n            return (*this);\n         }\n\n         template <typename Iterator>\n         inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))\n         {\n            type = e_symbol;\n            value.assign(begin,end);\n            if (base_begin)\n               position = static_cast<std::size_t>(std::distance(base_begin,begin));\n            return (*this);\n         }\n\n         template <typename Iterator>\n         inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))\n         {\n            type = e_number;\n            value.assign(begin,end);\n            if (base_begin)\n               position = static_cast<std::size_t>(std::distance(base_begin,begin));\n            return (*this);\n         }\n\n         template <typename Iterator>\n         inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))\n         {\n            type = e_string;\n            value.assign(begin,end);\n            if (base_begin)\n               position = static_cast<std::size_t>(std::distance(base_begin,begin));\n            return (*this);\n         }\n\n         inline token& set_string(const std::string& s, const std::size_t p)\n         {\n            type     = e_string;\n            value    = s;\n            position = p;\n            return (*this);\n         }\n\n         template <typename Iterator>\n         inline token& set_error(const token_type et,\n                                 const Iterator begin, const Iterator end,\n                                 const Iterator base_begin = Iterator(0))\n         {\n            if (\n                 (e_error      == et) ||\n                 (e_err_symbol == et) ||\n                 (e_err_number == et) ||\n                 (e_err_string == et) ||\n                 (e_err_sfunc  == et)\n               )\n            {\n               type = et;\n            }\n            else\n               type = e_error;\n\n            value.assign(begin,end);\n\n            if (base_begin)\n               position = static_cast<std::size_t>(std::distance(base_begin,begin));\n\n            return (*this);\n         }\n\n         static inline std::string to_str(token_type t)\n         {\n            switch (t)\n            {\n               case e_none        : return \"NONE\";\n               case e_error       : return \"ERROR\";\n               case e_err_symbol  : return \"ERROR_SYMBOL\";\n               case e_err_number  : return \"ERROR_NUMBER\";\n               case e_err_string  : return \"ERROR_STRING\";\n               case e_eof         : return \"EOF\";\n               case e_number      : return \"NUMBER\";\n               case e_symbol      : return \"SYMBOL\";\n               case e_string      : return \"STRING\";\n               case e_assign      : return \":=\";\n               case e_addass      : return \"+=\";\n               case e_subass      : return \"-=\";\n               case e_mulass      : return \"*=\";\n               case e_divass      : return \"/=\";\n               case e_modass      : return \"%=\";\n               case e_shr         : return \">>\";\n               case e_shl         : return \"<<\";\n               case e_lte         : return \"<=\";\n               case e_ne          : return \"!=\";\n               case e_gte         : return \">=\";\n               case e_lt          : return \"<\";\n               case e_gt          : return \">\";\n               case e_eq          : return \"=\";\n               case e_rbracket    : return \")\";\n               case e_lbracket    : return \"(\";\n               case e_rsqrbracket : return \"]\";\n               case e_lsqrbracket : return \"[\";\n               case e_rcrlbracket : return \"}\";\n               case e_lcrlbracket : return \"{\";\n               case e_comma       : return \",\";\n               case e_add         : return \"+\";\n               case e_sub         : return \"-\";\n               case e_div         : return \"/\";\n               case e_mul         : return \"*\";\n               case e_mod         : return \"%\";\n               case e_pow         : return \"^\";\n               case e_colon       : return \":\";\n               case e_ternary     : return \"?\";\n               case e_swap        : return \"<=>\";\n               default            : return \"UNKNOWN\";\n            }\n         }\n\n         inline bool is_error() const\n         {\n            return (\n                     (e_error      == type) ||\n                     (e_err_symbol == type) ||\n                     (e_err_number == type) ||\n                     (e_err_string == type) ||\n                     (e_err_sfunc  == type)\n                   );\n         }\n\n         token_type type;\n         std::string value;\n         std::size_t position;\n      };\n\n      class generator\n      {\n      public:\n\n         typedef token token_t;\n         typedef std::vector<token_t> token_list_t;\n         typedef std::vector<token_t>::iterator token_list_itr_t;\n         typedef details::char_t char_t;\n\n         generator()\n         : base_itr_(0),\n           s_itr_   (0),\n           s_end_   (0)\n         {\n            clear();\n         }\n\n         inline void clear()\n         {\n            base_itr_ = 0;\n            s_itr_    = 0;\n            s_end_    = 0;\n            token_list_.clear();\n            token_itr_ = token_list_.end();\n            store_token_itr_ = token_list_.end();\n         }\n\n         inline bool process(const std::string& str)\n         {\n            base_itr_ = str.data();\n            s_itr_    = str.data();\n            s_end_    = str.data() + str.size();\n\n            eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);\n            token_list_.clear();\n\n            while (!is_end(s_itr_))\n            {\n               scan_token();\n\n               if (token_list_.empty())\n                  return true;\n               else if (token_list_.back().is_error())\n                  return false;\n            }\n\n            return true;\n         }\n\n         inline bool empty() const\n         {\n            return token_list_.empty();\n         }\n\n         inline std::size_t size() const\n         {\n            return token_list_.size();\n         }\n\n         inline void begin()\n         {\n            token_itr_ = token_list_.begin();\n            store_token_itr_ = token_list_.begin();\n         }\n\n         inline void store()\n         {\n            store_token_itr_ = token_itr_;\n         }\n\n         inline void restore()\n         {\n            token_itr_ = store_token_itr_;\n         }\n\n         inline token_t& next_token()\n         {\n            if (token_list_.end() != token_itr_)\n            {\n               return *token_itr_++;\n            }\n            else\n               return eof_token_;\n         }\n\n         inline token_t& peek_next_token()\n         {\n            if (token_list_.end() != token_itr_)\n            {\n               return *token_itr_;\n            }\n            else\n               return eof_token_;\n         }\n\n         inline token_t& operator[](const std::size_t& index)\n         {\n            if (index < token_list_.size())\n               return token_list_[index];\n            else\n               return eof_token_;\n         }\n\n         inline token_t operator[](const std::size_t& index) const\n         {\n            if (index < token_list_.size())\n               return token_list_[index];\n            else\n               return eof_token_;\n         }\n\n         inline bool finished() const\n         {\n            return (token_list_.end() == token_itr_);\n         }\n\n         inline void insert_front(token_t::token_type tk_type)\n         {\n            if (\n                 !token_list_.empty() &&\n                 (token_list_.end() != token_itr_)\n               )\n            {\n               token_t t = *token_itr_;\n\n               t.type     = tk_type;\n               token_itr_ = token_list_.insert(token_itr_,t);\n            }\n         }\n\n         inline std::string substr(const std::size_t& begin, const std::size_t& end)\n         {\n            const char_t* begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;\n            const char_t* end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;\n\n            return std::string(begin_itr,end_itr);\n         }\n\n         inline std::string remaining() const\n         {\n            if (finished())\n               return \"\";\n            else if (token_list_.begin() != token_itr_)\n               return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_);\n            else\n               return std::string(base_itr_ + token_itr_->position,s_end_);\n         }\n\n      private:\n\n         inline bool is_end(const char_t* itr)\n         {\n            return (s_end_ == itr);\n         }\n\n         inline void skip_whitespace()\n         {\n            while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))\n            {\n               ++s_itr_;\n            }\n         }\n\n         inline void skip_comments()\n         {\n            #ifndef exprtk_disable_comments\n            // The following comment styles are supported:\n            // 1. // .... \\n\n            // 2. #  .... \\n\n            // 3. /* .... */\n            struct test\n            {\n               static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)\n               {\n                  mode = 0;\n                       if ('#' == c0)    { mode = 1; incr = 1; }\n                  else if ('/' == c0)\n                  {\n                          if ('/' == c1) { mode = 1; incr = 2; }\n                     else if ('*' == c1) { mode = 2; incr = 2; }\n                  }\n                  return (0 != mode);\n               }\n\n               static inline bool comment_end(const char_t c0, const char_t c1, const int mode)\n               {\n                  return (\n                           ((1 == mode) && ('\\n' == c0)) ||\n                           ((2 == mode) && ( '*' == c0) && ('/' == c1))\n                         );\n               }\n            };\n\n            int mode      = 0;\n            int increment = 0;\n\n            if (is_end(s_itr_) || is_end((s_itr_ + 1)))\n               return;\n            else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))\n               return;\n\n            s_itr_ += increment;\n\n            while (!is_end(s_itr_) && !test::comment_end(*s_itr_, *(s_itr_ + 1), mode))\n            {\n               ++s_itr_;\n            }\n\n            if (!is_end(s_itr_))\n            {\n               s_itr_ += mode;\n\n               skip_whitespace();\n               skip_comments  ();\n            }\n            #endif\n         }\n\n         inline void scan_token()\n         {\n            skip_whitespace();\n            skip_comments  ();\n\n            if (is_end(s_itr_))\n            {\n               return;\n            }\n            else if (details::is_operator_char(*s_itr_))\n            {\n               scan_operator();\n               return;\n            }\n            else if (details::is_letter(*s_itr_))\n            {\n               scan_symbol();\n               return;\n            }\n            else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))\n            {\n               scan_number();\n               return;\n            }\n            else if ('$' == (*s_itr_))\n            {\n               scan_special_function();\n               return;\n            }\n            #ifndef exprtk_disable_string_capabilities\n            else if ('\\'' == (*s_itr_))\n            {\n               scan_string();\n               return;\n            }\n            #endif\n            else if ('~' == (*s_itr_))\n            {\n               token_t t;\n               t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);\n               token_list_.push_back(t);\n               ++s_itr_;\n               return;\n            }\n            else\n            {\n               token_t t;\n               t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);\n               token_list_.push_back(t);\n               ++s_itr_;\n            }\n         }\n\n         inline void scan_operator()\n         {\n            token_t t;\n\n            const char_t c0 = s_itr_[0];\n\n            if (!is_end(s_itr_ + 1))\n            {\n               const char_t c1 = s_itr_[1];\n\n               if (!is_end(s_itr_ + 2))\n               {\n                  const char_t c2 = s_itr_[2];\n\n                  if ((c0 == '<') && (c1 == '=') && (c2 == '>'))\n                  {\n                     t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);\n                     token_list_.push_back(t);\n                     s_itr_ += 3;\n                     return;\n                  }\n               }\n\n               token_t::token_type ttype = token_t::e_none;\n\n                    if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;\n               else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;\n               else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;\n               else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;\n               else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;\n               else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;\n               else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;\n               else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;\n               else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;\n               else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;\n               else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;\n               else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;\n               else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;\n\n               if (token_t::e_none != ttype)\n               {\n                  t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);\n                  token_list_.push_back(t);\n                  s_itr_ += 2;\n                  return;\n               }\n            }\n\n            if ('<' == c0)\n               t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);\n            else if ('>' == c0)\n               t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);\n            else if (';' == c0)\n               t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);\n            else if ('&' == c0)\n               t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);\n            else if ('|' == c0)\n               t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);\n            else\n               t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);\n\n            token_list_.push_back(t);\n            ++s_itr_;\n         }\n\n         inline void scan_symbol()\n         {\n            const char_t* initial_itr = s_itr_;\n\n            while (!is_end(s_itr_))\n            {\n               if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))\n               {\n                  if ('.' != (*s_itr_))\n                     break;\n                  /*\n                     Permit symbols that contain a 'dot'\n                     Allowed   : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123\n                     Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>\n                  */\n                  if (\n                       (s_itr_ != initial_itr)                     &&\n                       !is_end(s_itr_ + 1)                         &&\n                       !details::is_letter_or_digit(*(s_itr_ + 1)) &&\n                       ('_' != (*(s_itr_ + 1)))\n                     )\n                     break;\n               }\n\n               ++s_itr_;\n            }\n\n            token_t t;\n            t.set_symbol(initial_itr,s_itr_,base_itr_);\n            token_list_.push_back(t);\n         }\n\n         inline void scan_number()\n         {\n            /*\n               Attempt to match a valid numeric value in one of the following formats:\n               (01) 123456\n               (02) 123456.\n               (03) 123.456\n               (04) 123.456e3\n               (05) 123.456E3\n               (06) 123.456e+3\n               (07) 123.456E+3\n               (08) 123.456e-3\n               (09) 123.456E-3\n               (00) .1234\n               (11) .1234e3\n               (12) .1234E+3\n               (13) .1234e+3\n               (14) .1234E-3\n               (15) .1234e-3\n            */\n\n            const char_t* initial_itr = s_itr_;\n            bool dot_found            = false;\n            bool e_found              = false;\n            bool post_e_sign_found    = false;\n            bool post_e_digit_found   = false;\n            token_t t;\n\n            while (!is_end(s_itr_))\n            {\n               if ('.' == (*s_itr_))\n               {\n                  if (dot_found)\n                  {\n                     t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);\n                     token_list_.push_back(t);\n                     return;\n                  }\n\n                  dot_found = true;\n                  ++s_itr_;\n\n                  continue;\n               }\n               else if ('e' == std::tolower(*s_itr_))\n               {\n                  const char_t& c = *(s_itr_ + 1);\n\n                  if (is_end(s_itr_ + 1))\n                  {\n                     t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);\n                     token_list_.push_back(t);\n\n                     return;\n                  }\n                  else if (\n                            ('+' != c) &&\n                            ('-' != c) &&\n                            !details::is_digit(c)\n                          )\n                  {\n                     t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);\n                     token_list_.push_back(t);\n\n                     return;\n                  }\n\n                  e_found = true;\n                  ++s_itr_;\n\n                  continue;\n               }\n               else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)\n               {\n                  if (post_e_sign_found)\n                  {\n                     t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);\n                     token_list_.push_back(t);\n\n                     return;\n                  }\n\n                  post_e_sign_found = true;\n                  ++s_itr_;\n\n                  continue;\n               }\n               else if (e_found && details::is_digit(*s_itr_))\n               {\n                  post_e_digit_found = true;\n                  ++s_itr_;\n\n                  continue;\n               }\n               else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))\n                  break;\n               else\n                  ++s_itr_;\n            }\n\n            t.set_numeric(initial_itr, s_itr_, base_itr_);\n            token_list_.push_back(t);\n\n            return;\n         }\n\n         inline void scan_special_function()\n         {\n            const char_t* initial_itr = s_itr_;\n            token_t t;\n\n            // $fdd(x,x,x) = at least 11 chars\n            if (std::distance(s_itr_,s_end_) < 11)\n            {\n               t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);\n               token_list_.push_back(t);\n\n               return;\n            }\n\n            if (\n                 !(('$' == *s_itr_)                       &&\n                   (details::imatch  ('f',*(s_itr_ + 1))) &&\n                   (details::is_digit(*(s_itr_ + 2)))     &&\n                   (details::is_digit(*(s_itr_ + 3))))\n               )\n            {\n               t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);\n               token_list_.push_back(t);\n\n               return;\n            }\n\n            s_itr_ += 4; // $fdd = 4chars\n\n            t.set_symbol(initial_itr, s_itr_, base_itr_);\n            token_list_.push_back(t);\n\n            return;\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline void scan_string()\n         {\n            const char_t* initial_itr = s_itr_ + 1;\n            token_t t;\n\n            if (std::distance(s_itr_,s_end_) < 2)\n            {\n               t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_);\n               token_list_.push_back(t);\n               return;\n            }\n\n            ++s_itr_;\n\n            bool escaped_found = false;\n            bool escaped = false;\n\n            while (!is_end(s_itr_))\n            {\n               if (!escaped && ('\\\\' == *s_itr_))\n               {\n                  escaped_found = true;\n                  escaped = true;\n                  ++s_itr_;\n\n                  continue;\n               }\n               else if (!escaped)\n               {\n                  if ('\\'' == *s_itr_)\n                     break;\n               }\n               else if (escaped)\n               {\n                  if (!is_end(s_itr_) && ('0' == *(s_itr_)))\n                  {\n                     /*\n                        Note: The following 'awkward' conditional is\n                              due to various broken msvc compilers.\n                     */\n                     #if _MSC_VER == 1600\n                     const bool within_range = !is_end(s_itr_ + 2) &&\n                                               !is_end(s_itr_ + 3) ;\n                     #else\n                     const bool within_range = !is_end(s_itr_ + 1) &&\n                                               !is_end(s_itr_ + 2) &&\n                                               !is_end(s_itr_ + 3) ;\n                     #endif\n\n                     const bool x_seperator  = ('x' == *(s_itr_ + 1)) ||\n                                               ('X' == *(s_itr_ + 1)) ;\n\n                     const bool both_digits  = details::is_hex_digit(*(s_itr_ + 2)) &&\n                                               details::is_hex_digit(*(s_itr_ + 3)) ;\n\n                     if (!within_range || !x_seperator || !both_digits)\n                     {\n                        t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);\n                        token_list_.push_back(t);\n\n                        return;\n                     }\n                     else\n                        s_itr_ += 3;\n                  }\n\n                  escaped = false;\n               }\n\n               ++s_itr_;\n            }\n\n            if (is_end(s_itr_))\n            {\n               t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);\n               token_list_.push_back(t);\n\n               return;\n            }\n\n            if (!escaped_found)\n               t.set_string(initial_itr, s_itr_, base_itr_);\n            else\n            {\n               std::string parsed_string(initial_itr,s_itr_);\n\n               details::cleanup_escapes(parsed_string);\n\n               t.set_string(\n                    parsed_string,\n                    static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));\n            }\n\n            token_list_.push_back(t);\n            ++s_itr_;\n\n            return;\n         }\n         #endif\n\n      private:\n\n         token_list_t     token_list_;\n         token_list_itr_t token_itr_;\n         token_list_itr_t store_token_itr_;\n         token_t eof_token_;\n         const char_t* base_itr_;\n         const char_t* s_itr_;\n         const char_t* s_end_;\n\n         friend class token_scanner;\n         friend class token_modifier;\n         friend class token_inserter;\n         friend class token_joiner;\n      };\n\n      class helper_interface\n      {\n      public:\n\n         virtual void init()                     {              }\n         virtual void reset()                    {              }\n         virtual bool result()                   { return true; }\n         virtual std::size_t process(generator&) { return 0;    }\n         virtual ~helper_interface()             {              }\n      };\n\n      class token_scanner : public helper_interface\n      {\n      public:\n\n         virtual ~token_scanner()\n         {}\n\n         explicit token_scanner(const std::size_t& stride)\n         : stride_(stride)\n         {\n            if (stride > 4)\n            {\n               throw std::invalid_argument(\"token_scanner() - Invalid stride value\");\n            }\n         }\n\n         inline std::size_t process(generator& g)\n         {\n            if (g.token_list_.size() >= stride_)\n            {\n               for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)\n               {\n                  token t;\n\n                  switch (stride_)\n                  {\n                     case 1 :\n                              {\n                                 const token& t0 = g.token_list_[i];\n\n                                 if (!operator()(t0))\n                                 {\n                                    return i;\n                                 }\n                              }\n                              break;\n\n                     case 2 :\n                              {\n                                 const token& t0 = g.token_list_[i    ];\n                                 const token& t1 = g.token_list_[i + 1];\n\n                                 if (!operator()(t0, t1))\n                                 {\n                                    return i;\n                                 }\n                              }\n                              break;\n\n                     case 3 :\n                              {\n                                 const token& t0 = g.token_list_[i    ];\n                                 const token& t1 = g.token_list_[i + 1];\n                                 const token& t2 = g.token_list_[i + 2];\n\n                                 if (!operator()(t0, t1, t2))\n                                 {\n                                    return i;\n                                 }\n                              }\n                              break;\n\n                     case 4 :\n                              {\n                                 const token& t0 = g.token_list_[i    ];\n                                 const token& t1 = g.token_list_[i + 1];\n                                 const token& t2 = g.token_list_[i + 2];\n                                 const token& t3 = g.token_list_[i + 3];\n\n                                 if (!operator()(t0, t1, t2, t3))\n                                 {\n                                    return i;\n                                 }\n                              }\n                              break;\n                  }\n               }\n            }\n\n            return (g.token_list_.size() - stride_ + 1);\n         }\n\n         virtual bool operator() (const token&)\n         {\n            return false;\n         }\n\n         virtual bool operator() (const token&, const token&)\n         {\n            return false;\n         }\n\n         virtual bool operator() (const token&, const token&, const token&)\n         {\n            return false;\n         }\n\n         virtual bool operator() (const token&, const token&, const token&, const token&)\n         {\n            return false;\n         }\n\n      private:\n\n         const std::size_t stride_;\n      };\n\n      class token_modifier : public helper_interface\n      {\n      public:\n\n         inline std::size_t process(generator& g)\n         {\n            std::size_t changes = 0;\n\n            for (std::size_t i = 0; i < g.token_list_.size(); ++i)\n            {\n               if (modify(g.token_list_[i])) changes++;\n            }\n\n            return changes;\n         }\n\n         virtual bool modify(token& t) = 0;\n      };\n\n      class token_inserter : public helper_interface\n      {\n      public:\n\n         explicit token_inserter(const std::size_t& stride)\n         : stride_(stride)\n         {\n            if (stride > 5)\n            {\n               throw std::invalid_argument(\"token_inserter() - Invalid stride value\");\n            }\n         }\n\n         inline std::size_t process(generator& g)\n         {\n            if (g.token_list_.empty())\n               return 0;\n            else if (g.token_list_.size() < stride_)\n               return 0;\n\n            std::size_t changes = 0;\n\n            for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)\n            {\n               int insert_index = -1;\n               token t;\n\n               switch (stride_)\n               {\n                  case 1 : insert_index = insert(g.token_list_[i],t);\n                           break;\n\n                  case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);\n                           break;\n\n                  case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);\n                           break;\n\n                  case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t);\n                           break;\n\n                  case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t);\n                           break;\n               }\n\n               typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;\n\n               if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))\n               {\n                  g.token_list_.insert(\n                     g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);\n\n                  changes++;\n               }\n            }\n\n            return changes;\n         }\n\n         #define token_inserter_empty_body \\\n         {                                 \\\n            return -1;                     \\\n         }                                 \\\n\n         inline virtual int insert(const token&, token&)\n         token_inserter_empty_body\n\n         inline virtual int insert(const token&, const token&, token&)\n         token_inserter_empty_body\n\n         inline virtual int insert(const token&, const token&, const token&, token&)\n         token_inserter_empty_body\n\n         inline virtual int insert(const token&, const token&, const token&, const token&, token&)\n         token_inserter_empty_body\n\n         inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)\n         token_inserter_empty_body\n\n         #undef token_inserter_empty_body\n\n      private:\n\n         const std::size_t stride_;\n      };\n\n      class token_joiner : public helper_interface\n      {\n      public:\n\n         token_joiner(const std::size_t& stride)\n         : stride_(stride)\n         {}\n\n         inline std::size_t process(generator& g)\n         {\n            if (g.token_list_.empty())\n               return 0;\n\n            switch (stride_)\n            {\n               case 2  : return process_stride_2(g);\n               case 3  : return process_stride_3(g);\n               default : return 0;\n            }\n         }\n\n         virtual bool join(const token&, const token&, token&)               { return false; }\n         virtual bool join(const token&, const token&, const token&, token&) { return false; }\n\n      private:\n\n         inline std::size_t process_stride_2(generator& g)\n         {\n            typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;\n\n            if (g.token_list_.size() < 2)\n               return 0;\n\n            std::size_t changes = 0;\n\n            for (std::size_t i = 0; i < (g.token_list_.size() - 1); ++i)\n            {\n               token t;\n\n               while (join(g[i], g[i + 1], t))\n               {\n                  g.token_list_[i] = t;\n\n                  g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));\n\n                  ++changes;\n               }\n            }\n\n            return changes;\n         }\n\n         inline std::size_t process_stride_3(generator& g)\n         {\n            typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;\n\n            if (g.token_list_.size() < 3)\n               return 0;\n\n            std::size_t changes = 0;\n\n            for (std::size_t i = 0; i < (g.token_list_.size() - 2); ++i)\n            {\n               token t;\n\n               while (join(g[i], g[i + 1], g[i + 2], t))\n               {\n                  g.token_list_[i] = t;\n\n                  g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),\n                                      g.token_list_.begin() + static_cast<diff_t>(i + 3));\n                  ++changes;\n               }\n            }\n\n            return changes;\n         }\n\n         const std::size_t stride_;\n      };\n\n      namespace helper\n      {\n\n         inline void dump(lexer::generator& generator)\n         {\n            for (std::size_t i = 0; i < generator.size(); ++i)\n            {\n               lexer::token t = generator[i];\n               printf(\"Token[%02d] @ %03d  %6s  -->  '%s'\\n\",\n                      static_cast<int>(i),\n                      static_cast<int>(t.position),\n                      t.to_str(t.type).c_str(),\n                      t.value.c_str());\n            }\n         }\n\n         class commutative_inserter : public lexer::token_inserter\n         {\n         public:\n\n            using lexer::token_inserter::insert;\n\n            commutative_inserter()\n            : lexer::token_inserter(2)\n            {}\n\n            inline void ignore_symbol(const std::string& symbol)\n            {\n               ignore_set_.insert(symbol);\n            }\n\n            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)\n            {\n               bool match         = false;\n               new_token.type     = lexer::token::e_mul;\n               new_token.value    = \"*\";\n               new_token.position = t1.position;\n\n               if (t0.type == lexer::token::e_symbol)\n               {\n                  if (ignore_set_.end() != ignore_set_.find(t0.value))\n                  {\n                     return -1;\n                  }\n                  else if (!t0.value.empty() && ('$' == t0.value[0]))\n                  {\n                     return -1;\n                  }\n               }\n\n               if (t1.type == lexer::token::e_symbol)\n               {\n                  if (ignore_set_.end() != ignore_set_.find(t1.value))\n                  {\n                     return -1;\n                  }\n               }\n                    if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;\n               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;\n               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;\n               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;\n               else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;\n               else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;\n               else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;\n               else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;\n               else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;\n               else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;\n               else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;\n\n               return (match) ? 1 : -1;\n            }\n\n         private:\n\n            std::set<std::string,details::ilesscompare> ignore_set_;\n         };\n\n         class operator_joiner : public token_joiner\n         {\n         public:\n\n            operator_joiner(const std::size_t& stride)\n            : token_joiner(stride)\n            {}\n\n            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)\n            {\n               // ': =' --> ':='\n               if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_assign;\n                  t.value    = \":=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '+ =' --> '+='\n               else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_addass;\n                  t.value    = \"+=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '- =' --> '-='\n               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_subass;\n                  t.value    = \"-=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '* =' --> '*='\n               else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_mulass;\n                  t.value    = \"*=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '/ =' --> '/='\n               else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_divass;\n                  t.value    = \"/=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '% =' --> '%='\n               else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_modass;\n                  t.value    = \"%=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '> =' --> '>='\n               else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_gte;\n                  t.value    = \">=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '< =' --> '<='\n               else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_lte;\n                  t.value    = \"<=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '= =' --> '=='\n               else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_eq;\n                  t.value    = \"==\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '! =' --> '!='\n               else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))\n               {\n                  t.type     = lexer::token::e_ne;\n                  t.value    = \"!=\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '< >' --> '<>'\n               else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))\n               {\n                  t.type     = lexer::token::e_ne;\n                  t.value    = \"<>\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '<= >' --> '<=>'\n               else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))\n               {\n                  t.type     = lexer::token::e_swap;\n                  t.value    = \"<=>\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '+ -' --> '-'\n               else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))\n               {\n                  t.type     = lexer::token::e_sub;\n                  t.value    = \"-\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '- +' --> '-'\n               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))\n               {\n                  t.type     = lexer::token::e_sub;\n                  t.value    = \"-\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               // '- -' --> '+'\n               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))\n               {\n                  /*\n                     Note: May need to reconsider this when wanting to implement\n                     pre/postfix decrement operator\n                  */\n                  t.type     = lexer::token::e_add;\n                  t.value    = \"+\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               else\n                  return false;\n            }\n\n            inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)\n            {\n               // '[ * ]' --> '[*]'\n               if (\n                    (t0.type == lexer::token::e_lsqrbracket) &&\n                    (t1.type == lexer::token::e_mul        ) &&\n                    (t2.type == lexer::token::e_rsqrbracket)\n                  )\n               {\n                  t.type     = lexer::token::e_symbol;\n                  t.value    = \"[*]\";\n                  t.position = t0.position;\n\n                  return true;\n               }\n               else\n                  return false;\n            }\n         };\n\n         class bracket_checker : public lexer::token_scanner\n         {\n         public:\n\n            using lexer::token_scanner::operator();\n\n            bracket_checker()\n            : token_scanner(1),\n              state_(true)\n            {}\n\n            bool result()\n            {\n               if (!stack_.empty())\n               {\n                  lexer::token t;\n                  t.value      = stack_.top().first;\n                  t.position   = stack_.top().second;\n                  error_token_ = t;\n                  state_       = false;\n\n                  return false;\n               }\n               else\n                  return state_;\n            }\n\n            lexer::token error_token()\n            {\n               return error_token_;\n            }\n\n            void reset()\n            {\n               // Why? because msvc doesn't support swap properly.\n               stack_ = std::stack<std::pair<char,std::size_t> >();\n               state_ = true;\n               error_token_.clear();\n            }\n\n            bool operator() (const lexer::token& t)\n            {\n               if (\n                    !t.value.empty()                       &&\n                    (lexer::token::e_string != t.type)     &&\n                    (lexer::token::e_symbol != t.type)     &&\n                    exprtk::details::is_bracket(t.value[0])\n                  )\n               {\n                  details::char_t c = t.value[0];\n\n                       if (t.type == lexer::token::e_lbracket   ) stack_.push(std::make_pair(')',t.position));\n                  else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));\n                  else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));\n                  else if (exprtk::details::is_right_bracket(c))\n                  {\n                     if (stack_.empty())\n                     {\n                        state_       = false;\n                        error_token_ = t;\n\n                        return false;\n                     }\n                     else if (c != stack_.top().first)\n                     {\n                        state_       = false;\n                        error_token_ = t;\n\n                        return false;\n                     }\n                     else\n                        stack_.pop();\n                  }\n               }\n\n               return true;\n            }\n\n         private:\n\n            bool state_;\n            std::stack<std::pair<char,std::size_t> > stack_;\n            lexer::token error_token_;\n         };\n\n         class numeric_checker : public lexer::token_scanner\n         {\n         public:\n\n            using lexer::token_scanner::operator();\n\n            numeric_checker()\n            : token_scanner (1),\n              current_index_(0)\n            {}\n\n            bool result()\n            {\n               return error_list_.empty();\n            }\n\n            void reset()\n            {\n               error_list_.clear();\n               current_index_ = 0;\n            }\n\n            bool operator() (const lexer::token& t)\n            {\n               if (token::e_number == t.type)\n               {\n                  double v;\n\n                  if (!exprtk::details::string_to_real(t.value,v))\n                  {\n                     error_list_.push_back(current_index_);\n                  }\n               }\n\n               ++current_index_;\n\n               return true;\n            }\n\n            std::size_t error_count() const\n            {\n               return error_list_.size();\n            }\n\n            std::size_t error_index(const std::size_t& i)\n            {\n               if (i < error_list_.size())\n                  return error_list_[i];\n               else\n                  return std::numeric_limits<std::size_t>::max();\n            }\n\n            void clear_errors()\n            {\n               error_list_.clear();\n            }\n\n         private:\n\n            std::size_t current_index_;\n            std::vector<std::size_t> error_list_;\n         };\n\n         class symbol_replacer : public lexer::token_modifier\n         {\n         private:\n\n            typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;\n\n         public:\n\n            bool remove(const std::string& target_symbol)\n            {\n               const replace_map_t::iterator itr = replace_map_.find(target_symbol);\n\n               if (replace_map_.end() == itr)\n                  return false;\n\n               replace_map_.erase(itr);\n\n               return true;\n            }\n\n            bool add_replace(const std::string& target_symbol,\n                             const std::string& replace_symbol,\n                             const lexer::token::token_type token_type = lexer::token::e_symbol)\n            {\n               const replace_map_t::iterator itr = replace_map_.find(target_symbol);\n\n               if (replace_map_.end() != itr)\n               {\n                  return false;\n               }\n\n               replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);\n\n               return true;\n            }\n\n            void clear()\n            {\n               replace_map_.clear();\n            }\n\n         private:\n\n            bool modify(lexer::token& t)\n            {\n               if (lexer::token::e_symbol == t.type)\n               {\n                  if (replace_map_.empty())\n                     return false;\n\n                  const replace_map_t::iterator itr = replace_map_.find(t.value);\n\n                  if (replace_map_.end() != itr)\n                  {\n                     t.value = itr->second.first;\n                     t.type  = itr->second.second;\n\n                     return true;\n                  }\n               }\n\n               return false;\n            }\n\n            replace_map_t replace_map_;\n         };\n\n         class sequence_validator : public lexer::token_scanner\n         {\n         private:\n\n            typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;\n            typedef std::set<token_pair_t> set_t;\n\n         public:\n\n            using lexer::token_scanner::operator();\n\n            sequence_validator()\n            : lexer::token_scanner(2)\n            {\n               add_invalid(lexer::token::e_number ,lexer::token::e_number );\n               add_invalid(lexer::token::e_string ,lexer::token::e_string );\n               add_invalid(lexer::token::e_number ,lexer::token::e_string );\n               add_invalid(lexer::token::e_string ,lexer::token::e_number );\n               add_invalid_set1(lexer::token::e_assign );\n               add_invalid_set1(lexer::token::e_shr    );\n               add_invalid_set1(lexer::token::e_shl    );\n               add_invalid_set1(lexer::token::e_lte    );\n               add_invalid_set1(lexer::token::e_ne     );\n               add_invalid_set1(lexer::token::e_gte    );\n               add_invalid_set1(lexer::token::e_lt     );\n               add_invalid_set1(lexer::token::e_gt     );\n               add_invalid_set1(lexer::token::e_eq     );\n               add_invalid_set1(lexer::token::e_comma  );\n               add_invalid_set1(lexer::token::e_add    );\n               add_invalid_set1(lexer::token::e_sub    );\n               add_invalid_set1(lexer::token::e_div    );\n               add_invalid_set1(lexer::token::e_mul    );\n               add_invalid_set1(lexer::token::e_mod    );\n               add_invalid_set1(lexer::token::e_pow    );\n               add_invalid_set1(lexer::token::e_colon  );\n               add_invalid_set1(lexer::token::e_ternary);\n            }\n\n            bool result()\n            {\n               return error_list_.empty();\n            }\n\n            bool operator() (const lexer::token& t0, const lexer::token& t1)\n            {\n               set_t::value_type p = std::make_pair(t0.type,t1.type);\n\n               if (invalid_bracket_check(t0.type,t1.type))\n               {\n                  error_list_.push_back(std::make_pair(t0,t1));\n               }\n               else if (invalid_comb_.find(p) != invalid_comb_.end())\n               {\n                  error_list_.push_back(std::make_pair(t0,t1));\n               }\n\n               return true;\n            }\n\n            std::size_t error_count()\n            {\n               return error_list_.size();\n            }\n\n            std::pair<lexer::token,lexer::token> error(const std::size_t index)\n            {\n               if (index < error_list_.size())\n               {\n                  return error_list_[index];\n               }\n               else\n               {\n                  static const lexer::token error_token;\n                  return std::make_pair(error_token,error_token);\n               }\n            }\n\n            void clear_errors()\n            {\n               error_list_.clear();\n            }\n\n         private:\n\n            void add_invalid(lexer::token::token_type base, lexer::token::token_type t)\n            {\n               invalid_comb_.insert(std::make_pair(base,t));\n            }\n\n            void add_invalid_set1(lexer::token::token_type t)\n            {\n               add_invalid(t,lexer::token::e_assign);\n               add_invalid(t,lexer::token::e_shr   );\n               add_invalid(t,lexer::token::e_shl   );\n               add_invalid(t,lexer::token::e_lte   );\n               add_invalid(t,lexer::token::e_ne    );\n               add_invalid(t,lexer::token::e_gte   );\n               add_invalid(t,lexer::token::e_lt    );\n               add_invalid(t,lexer::token::e_gt    );\n               add_invalid(t,lexer::token::e_eq    );\n               add_invalid(t,lexer::token::e_comma );\n               add_invalid(t,lexer::token::e_div   );\n               add_invalid(t,lexer::token::e_mul   );\n               add_invalid(t,lexer::token::e_mod   );\n               add_invalid(t,lexer::token::e_pow   );\n               add_invalid(t,lexer::token::e_colon );\n            }\n\n            bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)\n            {\n               if (details::is_right_bracket(static_cast<char>(base)))\n               {\n                  switch (t)\n                  {\n                     case lexer::token::e_assign : return (']' != base);\n                     case lexer::token::e_string : return true;\n                     default                     : return false;\n                  }\n               }\n               else if (details::is_left_bracket(static_cast<char>(base)))\n               {\n                  if (details::is_right_bracket(static_cast<char>(t)))\n                     return false;\n                  else if (details::is_left_bracket(static_cast<char>(t)))\n                     return false;\n                  else\n                  {\n                     switch (t)\n                     {\n                        case lexer::token::e_number  : return false;\n                        case lexer::token::e_symbol  : return false;\n                        case lexer::token::e_string  : return false;\n                        case lexer::token::e_add     : return false;\n                        case lexer::token::e_sub     : return false;\n                        case lexer::token::e_colon   : return false;\n                        case lexer::token::e_ternary : return false;\n                        default                      : return true;\n                     }\n                  }\n               }\n               else if (details::is_right_bracket(static_cast<char>(t)))\n               {\n                  switch (base)\n                  {\n                     case lexer::token::e_number  : return false;\n                     case lexer::token::e_symbol  : return false;\n                     case lexer::token::e_string  : return false;\n                     case lexer::token::e_eof     : return false;\n                     case lexer::token::e_colon   : return false;\n                     case lexer::token::e_ternary : return false;\n                     default                      : return true;\n                  }\n               }\n               else if (details::is_left_bracket(static_cast<char>(t)))\n               {\n                  switch (base)\n                  {\n                     case lexer::token::e_rbracket    : return true;\n                     case lexer::token::e_rsqrbracket : return true;\n                     case lexer::token::e_rcrlbracket : return true;\n                     default                          : return false;\n                  }\n               }\n\n               return false;\n            }\n\n            set_t invalid_comb_;\n            std::vector<std::pair<lexer::token,lexer::token> > error_list_;\n         };\n\n         struct helper_assembly\n         {\n            inline bool register_scanner(lexer::token_scanner* scanner)\n            {\n               if (token_scanner_list.end() != std::find(token_scanner_list.begin(),\n                                                         token_scanner_list.end  (),\n                                                         scanner))\n               {\n                  return false;\n               }\n\n               token_scanner_list.push_back(scanner);\n\n               return true;\n            }\n\n            inline bool register_modifier(lexer::token_modifier* modifier)\n            {\n               if (token_modifier_list.end() != std::find(token_modifier_list.begin(),\n                                                          token_modifier_list.end  (),\n                                                          modifier))\n               {\n                  return false;\n               }\n\n               token_modifier_list.push_back(modifier);\n\n               return true;\n            }\n\n            inline bool register_joiner(lexer::token_joiner* joiner)\n            {\n               if (token_joiner_list.end() != std::find(token_joiner_list.begin(),\n                                                        token_joiner_list.end  (),\n                                                        joiner))\n               {\n                  return false;\n               }\n\n               token_joiner_list.push_back(joiner);\n\n               return true;\n            }\n\n            inline bool register_inserter(lexer::token_inserter* inserter)\n            {\n               if (token_inserter_list.end() != std::find(token_inserter_list.begin(),\n                                                          token_inserter_list.end  (),\n                                                          inserter))\n               {\n                  return false;\n               }\n\n               token_inserter_list.push_back(inserter);\n\n               return true;\n            }\n\n            inline bool run_modifiers(lexer::generator& g)\n            {\n               error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);\n\n               for (std::size_t i = 0; i < token_modifier_list.size(); ++i)\n               {\n                  lexer::token_modifier& modifier = (*token_modifier_list[i]);\n\n                  modifier.reset();\n                  modifier.process(g);\n\n                  if (!modifier.result())\n                  {\n                     error_token_modifier = token_modifier_list[i];\n\n                     return false;\n                  }\n               }\n\n               return true;\n            }\n\n            inline bool run_joiners(lexer::generator& g)\n            {\n               error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);\n\n               for (std::size_t i = 0; i < token_joiner_list.size(); ++i)\n               {\n                  lexer::token_joiner& joiner = (*token_joiner_list[i]);\n\n                  joiner.reset();\n                  joiner.process(g);\n\n                  if (!joiner.result())\n                  {\n                     error_token_joiner = token_joiner_list[i];\n\n                     return false;\n                  }\n               }\n\n               return true;\n            }\n\n            inline bool run_inserters(lexer::generator& g)\n            {\n               error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);\n\n               for (std::size_t i = 0; i < token_inserter_list.size(); ++i)\n               {\n                  lexer::token_inserter& inserter = (*token_inserter_list[i]);\n\n                  inserter.reset();\n                  inserter.process(g);\n\n                  if (!inserter.result())\n                  {\n                     error_token_inserter = token_inserter_list[i];\n\n                     return false;\n                  }\n               }\n\n               return true;\n            }\n\n            inline bool run_scanners(lexer::generator& g)\n            {\n               error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);\n\n               for (std::size_t i = 0; i < token_scanner_list.size(); ++i)\n               {\n                  lexer::token_scanner& scanner = (*token_scanner_list[i]);\n\n                  scanner.reset();\n                  scanner.process(g);\n\n                  if (!scanner.result())\n                  {\n                     error_token_scanner = token_scanner_list[i];\n\n                     return false;\n                  }\n               }\n\n               return true;\n            }\n\n            std::vector<lexer::token_scanner*>  token_scanner_list;\n            std::vector<lexer::token_modifier*> token_modifier_list;\n            std::vector<lexer::token_joiner*>   token_joiner_list;\n            std::vector<lexer::token_inserter*> token_inserter_list;\n\n            lexer::token_scanner*  error_token_scanner;\n            lexer::token_modifier* error_token_modifier;\n            lexer::token_joiner*   error_token_joiner;\n            lexer::token_inserter* error_token_inserter;\n         };\n      }\n\n      class parser_helper\n      {\n      public:\n\n         typedef token         token_t;\n         typedef generator generator_t;\n\n         inline bool init(const std::string& str)\n         {\n            if (!lexer_.process(str))\n            {\n               return false;\n            }\n\n            lexer_.begin();\n\n            next_token();\n\n            return true;\n         }\n\n         inline generator_t& lexer()\n         {\n            return lexer_;\n         }\n\n         inline const generator_t& lexer() const\n         {\n            return lexer_;\n         }\n\n         inline void store_token()\n         {\n            lexer_.store();\n            store_current_token_ = current_token_;\n         }\n\n         inline void restore_token()\n         {\n            lexer_.restore();\n            current_token_ = store_current_token_;\n         }\n\n         inline void next_token()\n         {\n            current_token_ = lexer_.next_token();\n         }\n\n         inline const token_t& current_token() const\n         {\n            return current_token_;\n         }\n\n         enum token_advance_mode\n         {\n            e_hold    = 0,\n            e_advance = 1\n         };\n\n         inline void advance_token(const token_advance_mode mode)\n         {\n            if (e_advance == mode)\n            {\n               next_token();\n            }\n         }\n\n         inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)\n         {\n            if (current_token().type != ttype)\n            {\n               return false;\n            }\n\n            advance_token(mode);\n\n            return true;\n         }\n\n         inline bool token_is(const token_t::token_type& ttype,\n                              const std::string& value,\n                              const token_advance_mode mode = e_advance)\n         {\n            if (\n                 (current_token().type != ttype) ||\n                 !exprtk::details::imatch(value,current_token().value)\n               )\n            {\n               return false;\n            }\n\n            advance_token(mode);\n\n            return true;\n         }\n\n         inline bool token_is_then_assign(const token_t::token_type& ttype,\n                                          std::string& token,\n                                          const token_advance_mode mode = e_advance)\n         {\n            if (current_token_.type != ttype)\n            {\n               return false;\n            }\n\n            token = current_token_.value;\n\n            advance_token(mode);\n\n            return true;\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Container>\n         inline bool token_is_then_assign(const token_t::token_type& ttype,\n                                          Container<std::string,Allocator>& token_list,\n                                          const token_advance_mode mode = e_advance)\n         {\n            if (current_token_.type != ttype)\n            {\n               return false;\n            }\n\n            token_list.push_back(current_token_.value);\n\n            advance_token(mode);\n\n            return true;\n         }\n\n         inline bool peek_token_is(const token_t::token_type& ttype)\n         {\n            return (lexer_.peek_next_token().type == ttype);\n         }\n\n         inline bool peek_token_is(const std::string& s)\n         {\n            return (exprtk::details::imatch(lexer_.peek_next_token().value,s));\n         }\n\n      private:\n\n         generator_t lexer_;\n         token_t     current_token_;\n         token_t     store_current_token_;\n      };\n   }\n\n   template <typename T>\n   class vector_view\n   {\n   public:\n\n      typedef T* data_ptr_t;\n\n      vector_view(data_ptr_t data, const std::size_t& size)\n      : size_(size),\n        data_(data),\n        data_ref_(0)\n      {}\n\n      vector_view(const vector_view<T>& vv)\n      : size_(vv.size_),\n        data_(vv.data_),\n        data_ref_(0)\n      {}\n\n      inline void rebase(data_ptr_t data)\n      {\n         data_ = data;\n\n         if (!data_ref_.empty())\n         {\n            for (std::size_t i = 0; i < data_ref_.size(); ++i)\n            {\n               (*data_ref_[i]) = data;\n            }\n         }\n      }\n\n      inline data_ptr_t data() const\n      {\n         return data_;\n      }\n\n      inline std::size_t size() const\n      {\n         return size_;\n      }\n\n      inline const T& operator[](const std::size_t index) const\n      {\n         return data_[index];\n      }\n\n      inline T& operator[](const std::size_t index)\n      {\n         return data_[index];\n      }\n\n      void set_ref(data_ptr_t* data_ref)\n      {\n         data_ref_.push_back(data_ref);\n      }\n\n   private:\n\n      const std::size_t size_;\n      data_ptr_t  data_;\n      std::vector<data_ptr_t*> data_ref_;\n   };\n\n   template <typename T>\n   inline vector_view<T> make_vector_view(T* data,\n                                          const std::size_t size, const std::size_t offset = 0)\n   {\n      return vector_view<T>(data + offset,size);\n   }\n\n   template <typename T>\n   inline vector_view<T> make_vector_view(std::vector<T>& v,\n                                          const std::size_t size, const std::size_t offset = 0)\n   {\n      return vector_view<T>(v.data() + offset,size);\n   }\n\n   template <typename T> class results_context;\n\n   template <typename T>\n   struct type_store\n   {\n      enum store_type\n      {\n         e_unknown,\n         e_scalar ,\n         e_vector ,\n         e_string\n      };\n\n      type_store()\n      : size(0),\n        data(0),\n        type(e_unknown)\n      {}\n\n      std::size_t size;\n      void*       data;\n      store_type  type;\n\n      class parameter_list\n      {\n      public:\n\n         parameter_list(std::vector<type_store>& pl)\n         : parameter_list_(pl)\n         {}\n\n         inline bool empty() const\n         {\n            return parameter_list_.empty();\n         }\n\n         inline std::size_t size() const\n         {\n            return parameter_list_.size();\n         }\n\n         inline type_store& operator[](const std::size_t& index)\n         {\n            return parameter_list_[index];\n         }\n\n         inline const type_store& operator[](const std::size_t& index) const\n         {\n            return parameter_list_[index];\n         }\n\n         inline type_store& front()\n         {\n            return parameter_list_[0];\n         }\n\n         inline const type_store& front() const\n         {\n            return parameter_list_[0];\n         }\n\n         inline type_store& back()\n         {\n            return parameter_list_.back();\n         }\n\n         inline const type_store& back() const\n         {\n            return parameter_list_.back();\n         }\n\n      private:\n\n         std::vector<type_store>& parameter_list_;\n\n         friend class results_context<T>;\n      };\n\n      template <typename ViewType>\n      struct type_view\n      {\n         typedef type_store<T> type_store_t;\n         typedef ViewType      value_t;\n\n         type_view(type_store_t& ts)\n         : ts_(ts),\n           data_(reinterpret_cast<value_t*>(ts_.data))\n         {}\n\n         type_view(const type_store_t& ts)\n         : ts_(const_cast<type_store_t&>(ts)),\n           data_(reinterpret_cast<value_t*>(ts_.data))\n         {}\n\n         inline std::size_t size() const\n         {\n            return ts_.size;\n         }\n\n         inline value_t& operator[](const std::size_t& i)\n         {\n            return data_[i];\n         }\n\n         inline const value_t& operator[](const std::size_t& i) const\n         {\n            return data_[i];\n         }\n\n         inline const value_t* begin() const { return data_; }\n         inline       value_t* begin()       { return data_; }\n\n         inline const value_t* end() const\n         {\n            return static_cast<value_t*>(data_ + ts_.size);\n         }\n\n         inline value_t* end()\n         {\n            return static_cast<value_t*>(data_ + ts_.size);\n         }\n\n         type_store_t& ts_;\n         value_t* data_;\n      };\n\n      typedef type_view<T>    vector_view;\n      typedef type_view<char> string_view;\n\n      struct scalar_view\n      {\n         typedef type_store<T> type_store_t;\n         typedef T value_t;\n\n         scalar_view(type_store_t& ts)\n         : v_(*reinterpret_cast<value_t*>(ts.data))\n         {}\n\n         scalar_view(const type_store_t& ts)\n         : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))\n         {}\n\n         inline value_t& operator() ()\n         {\n            return v_;\n         }\n\n         inline const value_t& operator() () const\n         {\n            return v_;\n         }\n\n         template <typename IntType>\n         inline bool to_int(IntType& i) const\n         {\n            if (!exprtk::details::numeric::is_integer(v_))\n               return false;\n\n            i = static_cast<IntType>(v_);\n\n            return true;\n         }\n\n         template <typename UIntType>\n         inline bool to_uint(UIntType& u) const\n         {\n            if (v_ < T(0))\n               return false;\n            else if (!exprtk::details::numeric::is_integer(v_))\n               return false;\n\n            u = static_cast<UIntType>(v_);\n\n            return true;\n         }\n\n         T& v_;\n      };\n   };\n\n   template <typename StringView>\n   inline std::string to_str(const StringView& view)\n   {\n      return std::string(view.begin(),view.size());\n   }\n\n   #ifndef exprtk_disable_return_statement\n   namespace details\n   {\n      template <typename T> class return_node;\n      template <typename T> class return_envelope_node;\n   }\n   #endif\n\n   template <typename T>\n   class results_context\n   {\n   public:\n\n      typedef type_store<T> type_store_t;\n\n      results_context()\n      : results_available_(false)\n      {}\n\n      inline std::size_t count() const\n      {\n         if (results_available_)\n            return parameter_list_.size();\n         else\n            return 0;\n      }\n\n      inline type_store_t& operator[](const std::size_t& index)\n      {\n         return parameter_list_[index];\n      }\n\n      inline const type_store_t& operator[](const std::size_t& index) const\n      {\n         return parameter_list_[index];\n      }\n\n   private:\n\n      inline void clear()\n      {\n         results_available_ = false;\n      }\n\n      typedef std::vector<type_store_t> ts_list_t;\n      typedef typename type_store_t::parameter_list parameter_list_t;\n\n      inline void assign(const parameter_list_t& pl)\n      {\n         parameter_list_    = pl.parameter_list_;\n         results_available_ = true;\n      }\n\n      bool results_available_;\n      ts_list_t parameter_list_;\n\n      #ifndef exprtk_disable_return_statement\n      friend class details::return_node<T>;\n      friend class details::return_envelope_node<T>;\n      #endif\n   };\n\n   namespace details\n   {\n      enum operator_type\n      {\n         e_default , e_null    , e_add     , e_sub     ,\n         e_mul     , e_div     , e_mod     , e_pow     ,\n         e_atan2   , e_min     , e_max     , e_avg     ,\n         e_sum     , e_prod    , e_lt      , e_lte     ,\n         e_eq      , e_equal   , e_ne      , e_nequal  ,\n         e_gte     , e_gt      , e_and     , e_nand    ,\n         e_or      , e_nor     , e_xor     , e_xnor    ,\n         e_mand    , e_mor     , e_scand   , e_scor    ,\n         e_shr     , e_shl     , e_abs     , e_acos    ,\n         e_acosh   , e_asin    , e_asinh   , e_atan    ,\n         e_atanh   , e_ceil    , e_cos     , e_cosh    ,\n         e_exp     , e_expm1   , e_floor   , e_log     ,\n         e_log10   , e_log2    , e_log1p   , e_logn    ,\n         e_neg     , e_pos     , e_round   , e_roundn  ,\n         e_root    , e_sqrt    , e_sin     , e_sinc    ,\n         e_sinh    , e_sec     , e_csc     , e_tan     ,\n         e_tanh    , e_cot     , e_clamp   , e_iclamp  ,\n         e_inrange , e_sgn     , e_r2d     , e_d2r     ,\n         e_d2g     , e_g2d     , e_hypot   , e_notl    ,\n         e_erf     , e_erfc    , e_ncdf    , e_frac    ,\n         e_trunc   , e_assign  , e_addass  , e_subass  ,\n         e_mulass  , e_divass  , e_modass  , e_in      ,\n         e_like    , e_ilike   , e_multi   , e_smulti  ,\n         e_swap    ,\n\n         // Do not add new functions/operators after this point.\n         e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,\n         e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,\n         e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,\n         e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,\n         e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,\n         e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,\n         e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,\n         e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,\n         e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,\n         e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,\n         e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,\n         e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,\n         e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,\n         e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,\n         e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,\n         e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,\n         e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,\n         e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,\n         e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,\n         e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,\n         e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,\n         e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,\n         e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,\n         e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,\n         e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,\n         e_sffinal  = 1100,\n         e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,\n         e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,\n         e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,\n         e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,\n         e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,\n         e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,\n         e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,\n         e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,\n         e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,\n         e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,\n         e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,\n         e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,\n         e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,\n         e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,\n         e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,\n         e_sf4ext60 = 2060, e_sf4ext61 = 2061\n      };\n\n      inline std::string to_str(const operator_type opr)\n      {\n         switch (opr)\n         {\n            case e_add    : return  \"+\";\n            case e_sub    : return  \"-\";\n            case e_mul    : return  \"*\";\n            case e_div    : return  \"/\";\n            case e_mod    : return  \"%\";\n            case e_pow    : return  \"^\";\n            case e_assign : return \":=\";\n            case e_addass : return \"+=\";\n            case e_subass : return \"-=\";\n            case e_mulass : return \"*=\";\n            case e_divass : return \"/=\";\n            case e_modass : return \"%=\";\n            case e_lt     : return  \"<\";\n            case e_lte    : return \"<=\";\n            case e_eq     : return \"==\";\n            case e_equal  : return  \"=\";\n            case e_ne     : return \"!=\";\n            case e_nequal : return \"<>\";\n            case e_gte    : return \">=\";\n            case e_gt     : return  \">\";\n            default       : return\"N/A\";\n         }\n      }\n\n      struct base_operation_t\n      {\n         base_operation_t(const operator_type t, const unsigned int& np)\n         : type(t),\n           num_params(np)\n         {}\n\n         operator_type type;\n         unsigned int num_params;\n      };\n\n      namespace loop_unroll\n      {\n         #ifndef exprtk_disable_superscalar_unroll\n         const unsigned int global_loop_batch_size = 16;\n         #else\n         const unsigned int global_loop_batch_size = 4;\n         #endif\n\n         struct details\n         {\n            details(const std::size_t& vsize,\n                    const unsigned int loop_batch_size = global_loop_batch_size)\n            : batch_size(loop_batch_size   ),\n              remainder (vsize % batch_size),\n              upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))\n            {}\n\n            unsigned int batch_size;\n            int   remainder;\n            int upper_bound;\n         };\n      }\n\n      #ifdef exprtk_enable_debugging\n      inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)\n      {\n         if (size)\n            exprtk_debug((\"%s - addr: %p\\n\",s.c_str(),ptr));\n         else\n            exprtk_debug((\"%s - addr: %p size: %d\\n\",\n                          s.c_str(),\n                          ptr,\n                          static_cast<unsigned int>(size)));\n      }\n      #else\n      inline void dump_ptr(const std::string&, const void*) {}\n      inline void dump_ptr(const std::string&, const void*, const std::size_t) {}\n      #endif\n\n      template <typename T>\n      class vec_data_store\n      {\n      public:\n\n         typedef vec_data_store<T> type;\n         typedef T* data_t;\n\n      private:\n\n         struct control_block\n         {\n            control_block()\n            : ref_count(1),\n              size     (0),\n              data     (0),\n              destruct (true)\n            {}\n\n            control_block(const std::size_t& dsize)\n            : ref_count(1),\n              size     (dsize),\n              data     (0),\n              destruct (true)\n            { create_data(); }\n\n            control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)\n            : ref_count(1),\n              size     (dsize),\n              data     (dptr ),\n              destruct (dstrct)\n            {}\n\n           ~control_block()\n            {\n               if (data && destruct && (0 == ref_count))\n               {\n                  dump_ptr(\"~control_block() data\",data);\n                  delete[] data;\n                  data = reinterpret_cast<data_t>(0);\n               }\n            }\n\n            static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)\n            {\n               if (dsize)\n               {\n                  if (0 == data_ptr)\n                     return (new control_block(dsize));\n                  else\n                     return (new control_block(dsize, data_ptr, dstrct));\n               }\n               else\n                  return (new control_block);\n            }\n\n            static inline void destroy(control_block*& cntrl_blck)\n            {\n               if (cntrl_blck)\n               {\n                  if (\n                       (0 !=   cntrl_blck->ref_count) &&\n                       (0 == --cntrl_blck->ref_count)\n                     )\n                  {\n                     delete cntrl_blck;\n                  }\n\n                  cntrl_blck = 0;\n               }\n            }\n\n            std::size_t ref_count;\n            std::size_t size;\n            data_t      data;\n            bool        destruct;\n\n         private:\n\n            control_block(const control_block&);\n            control_block& operator=(const control_block&);\n\n            inline void create_data()\n            {\n               destruct = true;\n               data     = new T[size];\n               std::fill_n(data,size,T(0));\n               dump_ptr(\"control_block::create_data() - data\",data,size);\n            }\n         };\n\n      public:\n\n         vec_data_store()\n         : control_block_(control_block::create(0))\n         {}\n\n         vec_data_store(const std::size_t& size)\n         : control_block_(control_block::create(size,(data_t)(0),true))\n         {}\n\n         vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)\n         : control_block_(control_block::create(size, data, dstrct))\n         {}\n\n         vec_data_store(const type& vds)\n         {\n            control_block_ = vds.control_block_;\n            control_block_->ref_count++;\n         }\n\n        ~vec_data_store()\n         {\n            control_block::destroy(control_block_);\n         }\n\n         type& operator=(const type& vds)\n         {\n            if (this != &vds)\n            {\n               std::size_t final_size = min_size(control_block_, vds.control_block_);\n\n               vds.control_block_->size = final_size;\n                   control_block_->size = final_size;\n\n               if (control_block_->destruct || (0 == control_block_->data))\n               {\n                  control_block::destroy(control_block_);\n\n                  control_block_ = vds.control_block_;\n                  control_block_->ref_count++;\n               }\n            }\n\n            return (*this);\n         }\n\n         inline data_t data()\n         {\n            return control_block_->data;\n         }\n\n         inline data_t data() const\n         {\n            return control_block_->data;\n         }\n\n         inline std::size_t size()\n         {\n            return control_block_->size;\n         }\n\n         inline std::size_t size() const\n         {\n            return control_block_->size;\n         }\n\n         inline data_t& ref()\n         {\n            return control_block_->data;\n         }\n\n         inline void dump() const\n         {\n            #ifdef exprtk_enable_debugging\n            exprtk_debug((\"size: %d\\taddress:%p\\tdestruct:%c\\n\",\n                          size(),\n                          data(),\n                          (control_block_->destruct ? 'T' : 'F')));\n\n            for (std::size_t i = 0; i < size(); ++i)\n            {\n               if (5 == i)\n                  exprtk_debug((\"\\n\"));\n\n               exprtk_debug((\"%15.10f \",data()[i]));\n            }\n            exprtk_debug((\"\\n\"));\n            #endif\n         }\n\n         static inline void match_sizes(type& vds0, type& vds1)\n         {\n            std::size_t size = min_size(vds0.control_block_,vds1.control_block_);\n            vds0.control_block_->size = size;\n            vds1.control_block_->size = size;\n         }\n\n      private:\n\n         static inline std::size_t min_size(control_block* cb0, control_block* cb1)\n         {\n            std::size_t size0 = cb0->size;\n            std::size_t size1 = cb1->size;\n\n            if (size0 && size1)\n               return std::min(size0,size1);\n            else\n               return (size0) ? size0 : size1;\n         }\n\n         control_block* control_block_;\n      };\n\n      namespace numeric\n      {\n         namespace details\n         {\n            template <typename T>\n            inline T process_impl(const operator_type operation, const T arg)\n            {\n               switch (operation)\n               {\n                  case e_abs   : return numeric::abs  (arg);\n                  case e_acos  : return numeric::acos (arg);\n                  case e_acosh : return numeric::acosh(arg);\n                  case e_asin  : return numeric::asin (arg);\n                  case e_asinh : return numeric::asinh(arg);\n                  case e_atan  : return numeric::atan (arg);\n                  case e_atanh : return numeric::atanh(arg);\n                  case e_ceil  : return numeric::ceil (arg);\n                  case e_cos   : return numeric::cos  (arg);\n                  case e_cosh  : return numeric::cosh (arg);\n                  case e_exp   : return numeric::exp  (arg);\n                  case e_expm1 : return numeric::expm1(arg);\n                  case e_floor : return numeric::floor(arg);\n                  case e_log   : return numeric::log  (arg);\n                  case e_log10 : return numeric::log10(arg);\n                  case e_log2  : return numeric::log2 (arg);\n                  case e_log1p : return numeric::log1p(arg);\n                  case e_neg   : return numeric::neg  (arg);\n                  case e_pos   : return numeric::pos  (arg);\n                  case e_round : return numeric::round(arg);\n                  case e_sin   : return numeric::sin  (arg);\n                  case e_sinc  : return numeric::sinc (arg);\n                  case e_sinh  : return numeric::sinh (arg);\n                  case e_sqrt  : return numeric::sqrt (arg);\n                  case e_tan   : return numeric::tan  (arg);\n                  case e_tanh  : return numeric::tanh (arg);\n                  case e_cot   : return numeric::cot  (arg);\n                  case e_sec   : return numeric::sec  (arg);\n                  case e_csc   : return numeric::csc  (arg);\n                  case e_r2d   : return numeric::r2d  (arg);\n                  case e_d2r   : return numeric::d2r  (arg);\n                  case e_d2g   : return numeric::d2g  (arg);\n                  case e_g2d   : return numeric::g2d  (arg);\n                  case e_notl  : return numeric::notl (arg);\n                  case e_sgn   : return numeric::sgn  (arg);\n                  case e_erf   : return numeric::erf  (arg);\n                  case e_erfc  : return numeric::erfc (arg);\n                  case e_ncdf  : return numeric::ncdf (arg);\n                  case e_frac  : return numeric::frac (arg);\n                  case e_trunc : return numeric::trunc(arg);\n\n                  default      : exprtk_debug((\"numeric::details::process_impl<T> - Invalid unary operation.\\n\"));\n                                 return std::numeric_limits<T>::quiet_NaN();\n               }\n            }\n\n            template <typename T>\n            inline T process_impl(const operator_type operation, const T arg0, const T arg1)\n            {\n               switch (operation)\n               {\n                  case e_add    : return (arg0 + arg1);\n                  case e_sub    : return (arg0 - arg1);\n                  case e_mul    : return (arg0 * arg1);\n                  case e_div    : return (arg0 / arg1);\n                  case e_mod    : return modulus<T>(arg0,arg1);\n                  case e_pow    : return pow<T>(arg0,arg1);\n                  case e_atan2  : return atan2<T>(arg0,arg1);\n                  case e_min    : return std::min<T>(arg0,arg1);\n                  case e_max    : return std::max<T>(arg0,arg1);\n                  case e_logn   : return logn<T>(arg0,arg1);\n                  case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);\n                  case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);\n                  case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);\n                  case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);\n                  case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);\n                  case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);\n                  case e_and    : return and_opr<T> (arg0,arg1);\n                  case e_nand   : return nand_opr<T>(arg0,arg1);\n                  case e_or     : return or_opr<T>  (arg0,arg1);\n                  case e_nor    : return nor_opr<T> (arg0,arg1);\n                  case e_xor    : return xor_opr<T> (arg0,arg1);\n                  case e_xnor   : return xnor_opr<T>(arg0,arg1);\n                  case e_root   : return root<T>    (arg0,arg1);\n                  case e_roundn : return roundn<T>  (arg0,arg1);\n                  case e_equal  : return equal      (arg0,arg1);\n                  case e_nequal : return nequal     (arg0,arg1);\n                  case e_hypot  : return hypot<T>   (arg0,arg1);\n                  case e_shr    : return shr<T>     (arg0,arg1);\n                  case e_shl    : return shl<T>     (arg0,arg1);\n\n                  default       : exprtk_debug((\"numeric::details::process_impl<T> - Invalid binary operation.\\n\"));\n                                  return std::numeric_limits<T>::quiet_NaN();\n               }\n            }\n\n            template <typename T>\n            inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)\n            {\n               switch (operation)\n               {\n                  case e_add    : return (arg0 + arg1);\n                  case e_sub    : return (arg0 - arg1);\n                  case e_mul    : return (arg0 * arg1);\n                  case e_div    : return (arg0 / arg1);\n                  case e_mod    : return arg0 % arg1;\n                  case e_pow    : return pow<T>(arg0,arg1);\n                  case e_min    : return std::min<T>(arg0,arg1);\n                  case e_max    : return std::max<T>(arg0,arg1);\n                  case e_logn   : return logn<T>(arg0,arg1);\n                  case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);\n                  case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);\n                  case e_eq     : return (arg0 == arg1) ? T(1) : T(0);\n                  case e_ne     : return (arg0 != arg1) ? T(1) : T(0);\n                  case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);\n                  case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);\n                  case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);\n                  case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);\n                  case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);\n                  case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);\n                  case e_xor    : return arg0 ^ arg1;\n                  case e_xnor   : return !(arg0 ^ arg1);\n                  case e_root   : return root<T>(arg0,arg1);\n                  case e_equal  : return arg0 == arg1;\n                  case e_nequal : return arg0 != arg1;\n                  case e_hypot  : return hypot<T>(arg0,arg1);\n                  case e_shr    : return arg0 >> arg1;\n                  case e_shl    : return arg0 << arg1;\n\n                  default       : exprtk_debug((\"numeric::details::process_impl<IntType> - Invalid binary operation.\\n\"));\n                                  return std::numeric_limits<T>::quiet_NaN();\n               }\n            }\n         }\n\n         template <typename T>\n         inline T process(const operator_type operation, const T arg)\n         {\n            return exprtk::details::numeric::details::process_impl(operation,arg);\n         }\n\n         template <typename T>\n         inline T process(const operator_type operation, const T arg0, const T arg1)\n         {\n            return exprtk::details::numeric::details::process_impl(operation,arg0,arg1);\n         }\n      }\n\n      template <typename T>\n      class expression_node\n      {\n      public:\n\n         enum node_type\n         {\n            e_none         , e_null         , e_constant     , e_unary        ,\n            e_binary       , e_binary_ext   , e_trinary      , e_quaternary   ,\n            e_vararg       , e_conditional  , e_while        , e_repeat       ,\n            e_for          , e_switch       , e_mswitch      , e_return       ,\n            e_retenv       , e_variable     , e_stringvar    , e_stringconst  ,\n            e_stringvarrng , e_cstringvarrng, e_strgenrange  , e_strconcat    ,\n            e_stringvarsize, e_strswap      , e_stringsize   , e_stringvararg ,\n            e_function     , e_vafunction   , e_genfunction  , e_strfunction  ,\n            e_strcondition , e_strccondition, e_add          , e_sub          ,\n            e_mul          , e_div          , e_mod          , e_pow          ,\n            e_lt           , e_lte          , e_gt           , e_gte          ,\n            e_eq           , e_ne           , e_and          , e_nand         ,\n            e_or           , e_nor          , e_xor          , e_xnor         ,\n            e_in           , e_like         , e_ilike        , e_inranges     ,\n            e_ipow         , e_ipowinv      , e_abs          , e_acos         ,\n            e_acosh        , e_asin         , e_asinh        , e_atan         ,\n            e_atanh        , e_ceil         , e_cos          , e_cosh         ,\n            e_exp          , e_expm1        , e_floor        , e_log          ,\n            e_log10        , e_log2         , e_log1p        , e_neg          ,\n            e_pos          , e_round        , e_sin          , e_sinc         ,\n            e_sinh         , e_sqrt         , e_tan          , e_tanh         ,\n            e_cot          , e_sec          , e_csc          , e_r2d          ,\n            e_d2r          , e_d2g          , e_g2d          , e_notl         ,\n            e_sgn          , e_erf          , e_erfc         , e_ncdf         ,\n            e_frac         , e_trunc        , e_uvouv        , e_vov          ,\n            e_cov          , e_voc          , e_vob          , e_bov          ,\n            e_cob          , e_boc          , e_vovov        , e_vovoc        ,\n            e_vocov        , e_covov        , e_covoc        , e_vovovov      ,\n            e_vovovoc      , e_vovocov      , e_vocovov      , e_covovov      ,\n            e_covocov      , e_vocovoc      , e_covovoc      , e_vococov      ,\n            e_sf3ext       , e_sf4ext       , e_nulleq       , e_strass       ,\n            e_vector       , e_vecelem      , e_rbvecelem    , e_rbveccelem   ,\n            e_vecdefass    , e_vecvalass    , e_vecvecass    , e_vecopvalass  ,\n            e_vecopvecass  , e_vecfunc      , e_vecvecswap   , e_vecvecineq   ,\n            e_vecvalineq   , e_valvecineq   , e_vecvecarith  , e_vecvalarith  ,\n            e_valvecarith  , e_vecunaryop   , e_break        , e_continue     ,\n            e_swap\n         };\n\n         typedef T value_type;\n         typedef expression_node<T>* expression_ptr;\n\n         virtual ~expression_node()\n         {}\n\n         inline virtual T value() const\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline virtual expression_node<T>* branch(const std::size_t& index = 0) const\n         {\n            return reinterpret_cast<expression_ptr>(index * 0);\n         }\n\n         inline virtual node_type type() const\n         {\n            return e_none;\n         }\n      };\n\n      template <typename T>\n      inline bool is_generally_string_node(const expression_node<T>* node);\n\n      inline bool is_true(const double v)\n      {\n         return std::not_equal_to<double>()(0.0,v);\n      }\n\n      inline bool is_true(const long double v)\n      {\n         return std::not_equal_to<long double>()(0.0L,v);\n      }\n\n      inline bool is_true(const float v)\n      {\n         return std::not_equal_to<float>()(0.0f,v);\n      }\n\n      template <typename T>\n      inline bool is_true(const std::complex<T>& v)\n      {\n         return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);\n      }\n\n      template <typename T>\n      inline bool is_true(const expression_node<T>* node)\n      {\n         return std::not_equal_to<T>()(T(0),node->value());\n      }\n\n      template <typename T>\n      inline bool is_false(const expression_node<T>* node)\n      {\n         return std::equal_to<T>()(T(0),node->value());\n      }\n\n      template <typename T>\n      inline bool is_unary_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_unary == node->type());\n      }\n\n      template <typename T>\n      inline bool is_neg_unary_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_neg == node->type());\n      }\n\n      template <typename T>\n      inline bool is_binary_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_binary == node->type());\n      }\n\n      template <typename T>\n      inline bool is_variable_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_variable == node->type());\n      }\n\n      template <typename T>\n      inline bool is_ivariable_node(const expression_node<T>* node)\n      {\n         return node &&\n                (\n                  details::expression_node<T>::e_variable   == node->type() ||\n                  details::expression_node<T>::e_vecelem    == node->type() ||\n                  details::expression_node<T>::e_rbvecelem  == node->type() ||\n                  details::expression_node<T>::e_rbveccelem == node->type()\n                );\n      }\n\n      template <typename T>\n      inline bool is_vector_elem_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_vecelem == node->type());\n      }\n\n      template <typename T>\n      inline bool is_rebasevector_elem_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_rbvecelem == node->type());\n      }\n\n      template <typename T>\n      inline bool is_rebasevector_celem_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_rbveccelem == node->type());\n      }\n\n      template <typename T>\n      inline bool is_vector_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_vector == node->type());\n      }\n\n      template <typename T>\n      inline bool is_ivector_node(const expression_node<T>* node)\n      {\n         if (node)\n         {\n            switch (node->type())\n            {\n               case details::expression_node<T>::e_vector      :\n               case details::expression_node<T>::e_vecvalass   :\n               case details::expression_node<T>::e_vecvecass   :\n               case details::expression_node<T>::e_vecopvalass :\n               case details::expression_node<T>::e_vecopvecass :\n               case details::expression_node<T>::e_vecvecswap  :\n               case details::expression_node<T>::e_vecvecarith :\n               case details::expression_node<T>::e_vecvalarith :\n               case details::expression_node<T>::e_valvecarith :\n               case details::expression_node<T>::e_vecunaryop  : return true;\n               default                                         : return false;\n            }\n         }\n         else\n            return false;\n      }\n\n      template <typename T>\n      inline bool is_constant_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_constant == node->type());\n      }\n\n      template <typename T>\n      inline bool is_null_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_null == node->type());\n      }\n\n      template <typename T>\n      inline bool is_break_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_break == node->type());\n      }\n\n      template <typename T>\n      inline bool is_continue_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_continue == node->type());\n      }\n\n      template <typename T>\n      inline bool is_swap_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_swap == node->type());\n      }\n\n      template <typename T>\n      inline bool is_function(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_function == node->type());\n      }\n\n      template <typename T>\n      inline bool is_return_node(const expression_node<T>* node)\n      {\n         return node && (details::expression_node<T>::e_return == node->type());\n      }\n\n      template <typename T> class unary_node;\n\n      template <typename T>\n      inline bool is_negate_node(const expression_node<T>* node)\n      {\n         if (node && is_unary_node(node))\n         {\n            return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());\n         }\n         else\n            return false;\n      }\n\n      template <typename T>\n      inline bool branch_deletable(expression_node<T>* node)\n      {\n         return !is_variable_node(node) &&\n                !is_string_node  (node) ;\n      }\n\n      template <std::size_t N, typename T>\n      inline bool all_nodes_valid(expression_node<T>* (&b)[N])\n      {\n         for (std::size_t i = 0; i < N; ++i)\n         {\n            if (0 == b[i]) return false;\n         }\n\n         return true;\n      }\n\n      template <typename T,\n                typename Allocator,\n                template <typename,typename> class Sequence>\n      inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)\n      {\n         for (std::size_t i = 0; i < b.size(); ++i)\n         {\n            if (0 == b[i]) return false;\n         }\n\n         return true;\n      }\n\n      template <std::size_t N, typename T>\n      inline bool all_nodes_variables(expression_node<T>* (&b)[N])\n      {\n         for (std::size_t i = 0; i < N; ++i)\n         {\n            if (0 == b[i])\n               return false;\n            else if (!is_variable_node(b[i]))\n               return false;\n         }\n\n         return true;\n      }\n\n      template <typename T,\n                typename Allocator,\n                template <typename,typename> class Sequence>\n      inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)\n      {\n         for (std::size_t i = 0; i < b.size(); ++i)\n         {\n            if (0 == b[i])\n               return false;\n            else if (!is_variable_node(b[i]))\n               return false;\n         }\n\n         return true;\n      }\n\n      template <typename NodeAllocator, typename T, std::size_t N>\n      inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])\n      {\n         for (std::size_t i = 0; i < N; ++i)\n         {\n            free_node(node_allocator,b[i]);\n         }\n      }\n\n      template <typename NodeAllocator,\n                typename T,\n                typename Allocator,\n                template <typename,typename> class Sequence>\n      inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)\n      {\n         for (std::size_t i = 0; i < b.size(); ++i)\n         {\n            free_node(node_allocator,b[i]);\n         }\n\n         b.clear();\n      }\n\n      template <typename NodeAllocator, typename T>\n      inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)\n      {\n         if (0 != node)\n         {\n            if (\n                 (is_variable_node(node) || is_string_node(node)) ||\n                 force_delete\n               )\n               return;\n\n            node_allocator.free(node);\n            node = reinterpret_cast<expression_node<T>*>(0);\n         }\n      }\n\n      template <typename T>\n      inline void destroy_node(expression_node<T>*& node)\n      {\n         delete node;\n         node = reinterpret_cast<expression_node<T>*>(0);\n      }\n\n      template <typename Type>\n      class vector_holder\n      {\n      private:\n\n         typedef Type value_type;\n         typedef value_type* value_ptr;\n         typedef const value_ptr const_value_ptr;\n\n         class vector_holder_base\n         {\n         public:\n\n            virtual ~vector_holder_base() {}\n\n            inline value_ptr operator[](const std::size_t& index) const\n            {\n               return value_at(index);\n            }\n\n            inline std::size_t size() const\n            {\n               return vector_size();\n            }\n\n            inline value_ptr data() const\n            {\n               return value_at(0);\n            }\n\n            virtual inline bool rebaseable() const\n            {\n               return false;\n            }\n\n            virtual void set_ref(value_ptr*) {}\n\n         protected:\n\n            virtual value_ptr value_at(const std::size_t&) const = 0;\n            virtual std::size_t vector_size()              const = 0;\n         };\n\n         class array_vector_impl : public vector_holder_base\n         {\n         public:\n\n            array_vector_impl(const Type* vec, const std::size_t& vec_size)\n            : vec_(vec),\n              size_(vec_size)\n            {}\n\n         protected:\n\n            value_ptr value_at(const std::size_t& index) const\n            {\n               if (index < size_)\n                  return const_cast<const_value_ptr>(vec_ + index);\n               else\n                  return const_value_ptr(0);\n            }\n\n            std::size_t vector_size() const\n            {\n               return size_;\n            }\n\n         private:\n\n            array_vector_impl operator=(const array_vector_impl&);\n\n            const Type* vec_;\n            const std::size_t size_;\n         };\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         class sequence_vector_impl : public vector_holder_base\n         {\n         public:\n\n            typedef Sequence<Type,Allocator> sequence_t;\n\n            sequence_vector_impl(sequence_t& seq)\n            : sequence_(seq)\n            {}\n\n         protected:\n\n            value_ptr value_at(const std::size_t& index) const\n            {\n               return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);\n            }\n\n            std::size_t vector_size() const\n            {\n               return sequence_.size();\n            }\n\n         private:\n\n            sequence_vector_impl operator=(const sequence_vector_impl&);\n\n            sequence_t& sequence_;\n         };\n\n         class vector_view_impl : public vector_holder_base\n         {\n         public:\n\n            typedef exprtk::vector_view<Type> vector_view_t;\n\n            vector_view_impl(vector_view_t& vec_view)\n            : vec_view_(vec_view)\n            {}\n\n            void set_ref(value_ptr* ref)\n            {\n               vec_view_.set_ref(ref);\n            }\n\n            virtual inline bool rebaseable() const\n            {\n               return true;\n            }\n\n         protected:\n\n            value_ptr value_at(const std::size_t& index) const\n            {\n               return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);\n            }\n\n            std::size_t vector_size() const\n            {\n               return vec_view_.size();\n            }\n\n         private:\n\n            vector_view_impl operator=(const vector_view_impl&);\n\n            vector_view_t& vec_view_;\n         };\n\n      public:\n\n         typedef typename details::vec_data_store<Type> vds_t;\n\n         vector_holder(Type* vec, const std::size_t& vec_size)\n         : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))\n         {}\n\n         vector_holder(const vds_t& vds)\n         : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))\n         {}\n\n         template <typename Allocator>\n         vector_holder(std::vector<Type,Allocator>& vec)\n         : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))\n         {}\n\n         vector_holder(exprtk::vector_view<Type>& vec)\n         : vector_holder_base_(new(buffer)vector_view_impl(vec))\n         {}\n\n         inline value_ptr operator[](const std::size_t& index) const\n         {\n            return (*vector_holder_base_)[index];\n         }\n\n         inline std::size_t size() const\n         {\n            return vector_holder_base_->size();\n         }\n\n         inline value_ptr data() const\n         {\n            return vector_holder_base_->data();\n         }\n\n         void set_ref(value_ptr* ref)\n         {\n            vector_holder_base_->set_ref(ref);\n         }\n\n         bool rebaseable() const\n         {\n            return vector_holder_base_->rebaseable();\n         }\n\n      private:\n\n         mutable vector_holder_base* vector_holder_base_;\n         uchar_t buffer[64];\n      };\n\n      template <typename T>\n      class null_node : public expression_node<T>\n      {\n      public:\n\n         inline T value() const\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_null;\n         }\n      };\n\n      template <typename T>\n      class null_eq_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         null_eq_node(expression_ptr brnch, const bool equality = true)\n         : branch_(brnch),\n           branch_deletable_(branch_deletable(branch_)),\n           equality_(equality)\n         {}\n\n        ~null_eq_node()\n         {\n            if (branch_ && branch_deletable_)\n            {\n               destroy_node(branch_);\n            }\n         }\n\n         inline T value() const\n         {\n            const T v = branch_->value();\n            const bool result = details::numeric::is_nan(v);\n\n            if (result)\n               return (equality_) ? T(1) : T(0);\n            else\n               return (equality_) ? T(0) : T(1);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_nulleq;\n         }\n\n         inline operator_type operation() const\n         {\n            return details::e_eq;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_;\n         }\n\n      private:\n\n         expression_ptr branch_;\n         const bool branch_deletable_;\n         bool equality_;\n      };\n\n      template <typename T>\n      class literal_node : public expression_node<T>\n      {\n      public:\n\n         explicit literal_node(const T& v)\n         : value_(v)\n         {}\n\n         inline T value() const\n         {\n            return value_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_constant;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return reinterpret_cast<expression_node<T>*>(0);\n         }\n\n      private:\n\n         literal_node(literal_node<T>&) {}\n         literal_node<T>& operator=(literal_node<T>&) { return (*this); }\n\n         const T value_;\n      };\n\n      template <typename T>\n      struct range_pack;\n\n      template <typename T>\n      struct range_data_type;\n\n      template <typename T>\n      class range_interface\n      {\n      public:\n\n         typedef range_pack<T> range_t;\n\n         virtual ~range_interface()\n         {}\n\n         virtual range_t& range_ref() = 0;\n\n         virtual const range_t& range_ref() const = 0;\n      };\n\n      #ifndef exprtk_disable_string_capabilities\n      template <typename T>\n      class string_base_node\n      {\n      public:\n\n         typedef range_data_type<T> range_data_type_t;\n\n         virtual ~string_base_node()\n         {}\n\n         virtual std::string str () const = 0;\n\n         virtual const char_t* base() const = 0;\n\n         virtual std::size_t size() const = 0;\n      };\n\n      template <typename T>\n      class string_literal_node : public expression_node <T>,\n                                  public string_base_node<T>,\n                                  public range_interface <T>\n      {\n      public:\n\n         typedef range_pack<T> range_t;\n\n         explicit string_literal_node(const std::string& v)\n         : value_(v)\n         {\n            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);\n            rp_.cache.first  = rp_.n0_c.second;\n            rp_.cache.second = rp_.n1_c.second;\n         }\n\n         inline T value() const\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_stringconst;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return reinterpret_cast<expression_node<T>*>(0);\n         }\n\n         std::string str() const\n         {\n            return value_;\n         }\n\n         const char_t* base() const\n         {\n            return value_.data();\n         }\n\n         std::size_t size() const\n         {\n            return value_.size();\n         }\n\n         range_t& range_ref()\n         {\n            return rp_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return rp_;\n         }\n\n      private:\n\n         string_literal_node(const string_literal_node<T>&);\n         string_literal_node<T>& operator=(const string_literal_node<T>&);\n\n         const std::string value_;\n         range_t rp_;\n      };\n      #endif\n\n      template <typename T>\n      class unary_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         unary_node(const operator_type& opr,\n                    expression_ptr brnch)\n         : operation_(opr),\n           branch_(brnch),\n           branch_deletable_(branch_deletable(branch_))\n         {}\n\n        ~unary_node()\n         {\n            if (branch_ && branch_deletable_)\n            {\n               destroy_node(branch_);\n            }\n         }\n\n         inline T value() const\n         {\n            const T arg = branch_->value();\n\n            return numeric::process<T>(operation_,arg);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_unary;\n         }\n\n         inline operator_type operation() const\n         {\n            return operation_;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_;\n         }\n\n         inline void release()\n         {\n            branch_deletable_ = false;\n         }\n\n      protected:\n\n         operator_type operation_;\n         expression_ptr branch_;\n         bool branch_deletable_;\n      };\n\n      template <typename T, std::size_t D, bool B>\n      struct construct_branch_pair\n      {\n         template <std::size_t N>\n         static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)\n         {}\n      };\n\n      template <typename T, std::size_t D>\n      struct construct_branch_pair<T,D,true>\n      {\n         template <std::size_t N>\n         static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)\n         {\n            if (b)\n            {\n               branch[D] = std::make_pair(b,branch_deletable(b));\n            }\n         }\n      };\n\n      template <std::size_t N, typename T>\n      inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],\n                                expression_node<T>* b0,\n                                expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),\n                                expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))\n      {\n         construct_branch_pair<T,0,(N > 0)>::process(branch,b0);\n         construct_branch_pair<T,1,(N > 1)>::process(branch,b1);\n         construct_branch_pair<T,2,(N > 2)>::process(branch,b2);\n         construct_branch_pair<T,3,(N > 3)>::process(branch,b3);\n         construct_branch_pair<T,4,(N > 4)>::process(branch,b4);\n         construct_branch_pair<T,5,(N > 5)>::process(branch,b5);\n         construct_branch_pair<T,6,(N > 6)>::process(branch,b6);\n         construct_branch_pair<T,7,(N > 7)>::process(branch,b7);\n         construct_branch_pair<T,8,(N > 8)>::process(branch,b8);\n         construct_branch_pair<T,9,(N > 9)>::process(branch,b9);\n      }\n\n      struct cleanup_branches\n      {\n         template <typename T, std::size_t N>\n         static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])\n         {\n            for (std::size_t i = 0; i < N; ++i)\n            {\n               if (branch[i].first && branch[i].second)\n               {\n                  destroy_node(branch[i].first);\n               }\n            }\n         }\n\n         template <typename T,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)\n         {\n            for (std::size_t i = 0; i < branch.size(); ++i)\n            {\n               if (branch[i].first && branch[i].second)\n               {\n                  destroy_node(branch[i].first);\n               }\n            }\n         }\n      };\n\n      template <typename T>\n      class binary_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n\n         binary_node(const operator_type& opr,\n                     expression_ptr branch0,\n                     expression_ptr branch1)\n         : operation_(opr)\n         {\n            init_branches<2>(branch_, branch0, branch1);\n         }\n\n        ~binary_node()\n         {\n            cleanup_branches::execute<T,2>(branch_);\n         }\n\n         inline T value() const\n         {\n            const T arg0 = branch_[0].first->value();\n            const T arg1 = branch_[1].first->value();\n\n            return numeric::process<T>(operation_,arg0,arg1);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_binary;\n         }\n\n         inline operator_type operation()\n         {\n            return operation_;\n         }\n\n         inline expression_node<T>* branch(const std::size_t& index = 0) const\n         {\n            if (0 == index)\n               return branch_[0].first;\n            else if (1 == index)\n               return branch_[1].first;\n            else\n               return reinterpret_cast<expression_ptr>(0);\n         }\n\n      protected:\n\n         operator_type operation_;\n         branch_t branch_[2];\n      };\n\n      template <typename T, typename Operation>\n      class binary_ext_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n\n         binary_ext_node(expression_ptr branch0, expression_ptr branch1)\n         {\n            init_branches<2>(branch_, branch0, branch1);\n         }\n\n        ~binary_ext_node()\n         {\n            cleanup_branches::execute<T,2>(branch_);\n         }\n\n         inline T value() const\n         {\n            const T arg0 = branch_[0].first->value();\n            const T arg1 = branch_[1].first->value();\n\n            return Operation::process(arg0,arg1);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_binary_ext;\n         }\n\n         inline operator_type operation()\n         {\n            return Operation::operation();\n         }\n\n         inline expression_node<T>* branch(const std::size_t& index = 0) const\n         {\n            if (0 == index)\n               return branch_[0].first;\n            else if (1 == index)\n               return branch_[1].first;\n            else\n               return reinterpret_cast<expression_ptr>(0);\n         }\n\n      protected:\n\n         branch_t branch_[2];\n      };\n\n      template <typename T>\n      class trinary_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n\n         trinary_node(const operator_type& opr,\n                      expression_ptr branch0,\n                      expression_ptr branch1,\n                      expression_ptr branch2)\n         : operation_(opr)\n         {\n            init_branches<3>(branch_, branch0, branch1, branch2);\n         }\n\n        ~trinary_node()\n         {\n            cleanup_branches::execute<T,3>(branch_);\n         }\n\n         inline T value() const\n         {\n            const T arg0 = branch_[0].first->value();\n            const T arg1 = branch_[1].first->value();\n            const T arg2 = branch_[2].first->value();\n\n            switch (operation_)\n            {\n               case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));\n\n               case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);\n\n               case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))\n                                   return arg1;\n                                else\n                                   return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);\n\n               default        : {\n                                   exprtk_debug((\"trinary_node::value() - Error: Invalid operation\\n\"));\n                                   return std::numeric_limits<T>::quiet_NaN();\n                                }\n            }\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_trinary;\n         }\n\n      protected:\n\n         operator_type operation_;\n         branch_t branch_[3];\n      };\n\n      template <typename T>\n      class quaternary_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n\n         quaternary_node(const operator_type& opr,\n                         expression_ptr branch0,\n                         expression_ptr branch1,\n                         expression_ptr branch2,\n                         expression_ptr branch3)\n         : operation_(opr)\n         {\n            init_branches<4>(branch_, branch0, branch1, branch2, branch3);\n         }\n\n        ~quaternary_node()\n         {\n            cleanup_branches::execute<T,4>(branch_);\n         }\n\n         inline T value() const\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_quaternary;\n         }\n\n      protected:\n\n         operator_type operation_;\n         branch_t branch_[4];\n      };\n\n      template <typename T>\n      class conditional_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         conditional_node(expression_ptr test,\n                          expression_ptr consequent,\n                          expression_ptr alternative)\n         : test_(test),\n           consequent_(consequent),\n           alternative_(alternative),\n           test_deletable_(branch_deletable(test_)),\n           consequent_deletable_(branch_deletable(consequent_)),\n           alternative_deletable_(branch_deletable(alternative_))\n         {}\n\n        ~conditional_node()\n         {\n            if (test_ && test_deletable_)\n            {\n               destroy_node(test_);\n            }\n\n            if (consequent_ && consequent_deletable_ )\n            {\n               destroy_node(consequent_);\n            }\n\n            if (alternative_ && alternative_deletable_)\n            {\n               destroy_node(alternative_);\n            }\n         }\n\n         inline T value() const\n         {\n            if (is_true(test_))\n               return consequent_->value();\n            else\n               return alternative_->value();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_conditional;\n         }\n\n      private:\n\n         expression_ptr test_;\n         expression_ptr consequent_;\n         expression_ptr alternative_;\n         const bool test_deletable_;\n         const bool consequent_deletable_;\n         const bool alternative_deletable_;\n      };\n\n      template <typename T>\n      class cons_conditional_node : public expression_node<T>\n      {\n      public:\n\n         // Consequent only conditional statement node\n         typedef expression_node<T>* expression_ptr;\n\n         cons_conditional_node(expression_ptr test,\n                               expression_ptr consequent)\n         : test_(test),\n           consequent_(consequent),\n           test_deletable_(branch_deletable(test_)),\n           consequent_deletable_(branch_deletable(consequent_))\n         {}\n\n        ~cons_conditional_node()\n         {\n            if (test_ && test_deletable_)\n            {\n               destroy_node(test_);\n            }\n\n            if (consequent_ && consequent_deletable_)\n            {\n               destroy_node(consequent_);\n            }\n         }\n\n         inline T value() const\n         {\n            if (is_true(test_))\n               return consequent_->value();\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_conditional;\n         }\n\n      private:\n\n         expression_ptr test_;\n         expression_ptr consequent_;\n         const bool test_deletable_;\n         const bool consequent_deletable_;\n      };\n\n      #ifndef exprtk_disable_break_continue\n      template <typename T>\n      class break_exception\n      {\n      public:\n\n         break_exception(const T& v)\n         : value(v)\n         {}\n\n         T value;\n      };\n\n      class continue_exception\n      {};\n\n      template <typename T>\n      class break_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         break_node(expression_ptr ret = expression_ptr(0))\n         : return_(ret),\n           return_deletable_(branch_deletable(return_))\n         {}\n\n        ~break_node()\n         {\n            if (return_deletable_)\n            {\n               destroy_node(return_);\n            }\n         }\n\n         inline T value() const\n         {\n            throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());\n            #ifndef _MSC_VER\n            return std::numeric_limits<T>::quiet_NaN();\n            #endif\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_break;\n         }\n\n      private:\n\n         expression_ptr return_;\n         const bool return_deletable_;\n      };\n\n      template <typename T>\n      class continue_node : public expression_node<T>\n      {\n      public:\n\n         inline T value() const\n         {\n            throw continue_exception();\n            #ifndef _MSC_VER\n            return std::numeric_limits<T>::quiet_NaN();\n            #endif\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_break;\n         }\n      };\n      #endif\n\n      template <typename T>\n      class while_loop_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         while_loop_node(expression_ptr condition, expression_ptr loop_body)\n         : condition_(condition),\n           loop_body_(loop_body),\n           condition_deletable_(branch_deletable(condition_)),\n           loop_body_deletable_(branch_deletable(loop_body_))\n         {}\n\n        ~while_loop_node()\n         {\n            if (condition_ && condition_deletable_)\n            {\n               destroy_node(condition_);\n            }\n\n            if (loop_body_ && loop_body_deletable_)\n            {\n               destroy_node(loop_body_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            while (is_true(condition_))\n            {\n               result = loop_body_->value();\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_while;\n         }\n\n      private:\n\n         expression_ptr condition_;\n         expression_ptr loop_body_;\n         const bool condition_deletable_;\n         const bool loop_body_deletable_;\n      };\n\n      template <typename T>\n      class repeat_until_loop_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)\n         : condition_(condition),\n           loop_body_(loop_body),\n           condition_deletable_(branch_deletable(condition_)),\n           loop_body_deletable_(branch_deletable(loop_body_))\n         {}\n\n        ~repeat_until_loop_node()\n         {\n            if (condition_ && condition_deletable_)\n            {\n               destroy_node(condition_);\n            }\n\n            if (loop_body_ && loop_body_deletable_)\n            {\n               destroy_node(loop_body_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            do\n            {\n               result = loop_body_->value();\n            }\n            while (is_false(condition_));\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_repeat;\n         }\n\n      private:\n\n         expression_ptr condition_;\n         expression_ptr loop_body_;\n         const bool condition_deletable_;\n         const bool loop_body_deletable_;\n      };\n\n      template <typename T>\n      class for_loop_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         for_loop_node(expression_ptr initialiser,\n                       expression_ptr condition,\n                       expression_ptr incrementor,\n                       expression_ptr loop_body)\n         : initialiser_(initialiser),\n           condition_  (condition  ),\n           incrementor_(incrementor),\n           loop_body_  (loop_body  ),\n           initialiser_deletable_(branch_deletable(initialiser_)),\n           condition_deletable_  (branch_deletable(condition_  )),\n           incrementor_deletable_(branch_deletable(incrementor_)),\n           loop_body_deletable_  (branch_deletable(loop_body_  ))\n         {}\n\n        ~for_loop_node()\n         {\n            if (initialiser_ && initialiser_deletable_)\n            {\n               destroy_node(initialiser_);\n            }\n\n            if (condition_ && condition_deletable_)\n            {\n               destroy_node(condition_);\n            }\n\n            if (incrementor_ && incrementor_deletable_)\n            {\n               destroy_node(incrementor_);\n            }\n\n            if (loop_body_ && loop_body_deletable_)\n            {\n               destroy_node(loop_body_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            if (initialiser_)\n               initialiser_->value();\n\n            if (incrementor_)\n            {\n               while (is_true(condition_))\n               {\n                  result = loop_body_->value();\n                  incrementor_->value();\n               }\n            }\n            else\n            {\n               while (is_true(condition_))\n               {\n                  result = loop_body_->value();\n               }\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_for;\n         }\n\n      private:\n\n         expression_ptr initialiser_      ;\n         expression_ptr condition_        ;\n         expression_ptr incrementor_      ;\n         expression_ptr loop_body_        ;\n         const bool initialiser_deletable_;\n         const bool condition_deletable_  ;\n         const bool incrementor_deletable_;\n         const bool loop_body_deletable_  ;\n      };\n\n      #ifndef exprtk_disable_break_continue\n      template <typename T>\n      class while_loop_bc_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)\n         : condition_(condition),\n           loop_body_(loop_body),\n           condition_deletable_(branch_deletable(condition_)),\n           loop_body_deletable_(branch_deletable(loop_body_))\n         {}\n\n        ~while_loop_bc_node()\n         {\n            if (condition_ && condition_deletable_)\n            {\n               destroy_node(condition_);\n            }\n\n            if (loop_body_ && loop_body_deletable_)\n            {\n               destroy_node(loop_body_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            while (is_true(condition_))\n            {\n               try\n               {\n                  result = loop_body_->value();\n               }\n               catch(const break_exception<T>& e)\n               {\n                  return e.value;\n               }\n               catch(const continue_exception&)\n               {}\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_while;\n         }\n\n      private:\n\n         expression_ptr condition_;\n         expression_ptr loop_body_;\n         const bool condition_deletable_;\n         const bool loop_body_deletable_;\n      };\n\n      template <typename T>\n      class repeat_until_loop_bc_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)\n         : condition_(condition),\n           loop_body_(loop_body),\n           condition_deletable_(branch_deletable(condition_)),\n           loop_body_deletable_(branch_deletable(loop_body_))\n         {}\n\n        ~repeat_until_loop_bc_node()\n         {\n            if (condition_ && condition_deletable_)\n            {\n               destroy_node(condition_);\n            }\n\n            if (loop_body_ && loop_body_deletable_)\n            {\n               destroy_node(loop_body_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            do\n            {\n               try\n               {\n                  result = loop_body_->value();\n               }\n               catch(const break_exception<T>& e)\n               {\n                  return e.value;\n               }\n               catch(const continue_exception&)\n               {}\n            }\n            while (is_false(condition_));\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_repeat;\n         }\n\n      private:\n\n         expression_ptr condition_;\n         expression_ptr loop_body_;\n         const bool condition_deletable_;\n         const bool loop_body_deletable_;\n      };\n\n      template <typename T>\n      class for_loop_bc_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         for_loop_bc_node(expression_ptr initialiser,\n                       expression_ptr condition,\n                       expression_ptr incrementor,\n                       expression_ptr loop_body)\n         : initialiser_(initialiser),\n           condition_  (condition  ),\n           incrementor_(incrementor),\n           loop_body_  (loop_body  ),\n           initialiser_deletable_(branch_deletable(initialiser_)),\n           condition_deletable_  (branch_deletable(condition_  )),\n           incrementor_deletable_(branch_deletable(incrementor_)),\n           loop_body_deletable_  (branch_deletable(loop_body_  ))\n         {}\n\n        ~for_loop_bc_node()\n         {\n            if (initialiser_ && initialiser_deletable_)\n            {\n               destroy_node(initialiser_);\n            }\n\n            if (condition_ && condition_deletable_)\n            {\n               destroy_node(condition_);\n            }\n\n            if (incrementor_ && incrementor_deletable_)\n            {\n               destroy_node(incrementor_);\n            }\n\n            if (loop_body_ && loop_body_deletable_)\n            {\n               destroy_node(loop_body_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            if (initialiser_)\n               initialiser_->value();\n\n            if (incrementor_)\n            {\n               while (is_true(condition_))\n               {\n                  try\n                  {\n                     result = loop_body_->value();\n                  }\n                  catch(const break_exception<T>& e)\n                  {\n                     return e.value;\n                  }\n                  catch(const continue_exception&)\n                  {}\n\n                  incrementor_->value();\n               }\n            }\n            else\n            {\n               while (is_true(condition_))\n               {\n                  try\n                  {\n                     result = loop_body_->value();\n                  }\n                  catch(const break_exception<T>& e)\n                  {\n                     return e.value;\n                  }\n                  catch(const continue_exception&)\n                  {}\n               }\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_for;\n         }\n\n      private:\n\n         expression_ptr initialiser_;\n         expression_ptr condition_  ;\n         expression_ptr incrementor_;\n         expression_ptr loop_body_  ;\n         const bool initialiser_deletable_;\n         const bool condition_deletable_  ;\n         const bool incrementor_deletable_;\n         const bool loop_body_deletable_  ;\n      };\n      #endif\n\n      template <typename T>\n      class switch_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         switch_node(const Sequence<expression_ptr,Allocator>& arg_list)\n         {\n            if (1 != (arg_list.size() & 1))\n               return;\n\n            arg_list_.resize(arg_list.size());\n            delete_branch_.resize(arg_list.size());\n\n            for (std::size_t i = 0; i < arg_list.size(); ++i)\n            {\n               if (arg_list[i])\n               {\n                       arg_list_[i] = arg_list[i];\n                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);\n               }\n               else\n               {\n                  arg_list_.clear();\n                  delete_branch_.clear();\n                  return;\n               }\n            }\n         }\n\n        ~switch_node()\n         {\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               if (arg_list_[i] && delete_branch_[i])\n               {\n                  destroy_node(arg_list_[i]);\n               }\n            }\n         }\n\n         inline T value() const\n         {\n            if (!arg_list_.empty())\n            {\n               const std::size_t upper_bound = (arg_list_.size() - 1);\n\n               for (std::size_t i = 0; i < upper_bound; i += 2)\n               {\n                  expression_ptr condition  = arg_list_[i    ];\n                  expression_ptr consequent = arg_list_[i + 1];\n\n                  if (is_true(condition))\n                  {\n                     return consequent->value();\n                  }\n               }\n\n               return arg_list_[upper_bound]->value();\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_switch;\n         }\n\n      protected:\n\n         std::vector<expression_ptr> arg_list_;\n         std::vector<unsigned char> delete_branch_;\n      };\n\n      template <typename T, typename Switch_N>\n      class switch_n_node : public switch_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)\n         : switch_node<T>(arg_list)\n         {}\n\n         inline T value() const\n         {\n            return Switch_N::process(switch_node<T>::arg_list_);\n         }\n      };\n\n      template <typename T>\n      class multi_switch_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)\n         {\n            if (0 != (arg_list.size() & 1))\n               return;\n\n            arg_list_.resize(arg_list.size());\n            delete_branch_.resize(arg_list.size());\n\n            for (std::size_t i = 0; i < arg_list.size(); ++i)\n            {\n               if (arg_list[i])\n               {\n                       arg_list_[i] = arg_list[i];\n                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);\n               }\n               else\n               {\n                  arg_list_.clear();\n                  delete_branch_.clear();\n                  return;\n               }\n            }\n         }\n\n        ~multi_switch_node()\n         {\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               if (arg_list_[i] && delete_branch_[i])\n               {\n                  destroy_node(arg_list_[i]);\n               }\n            }\n         }\n\n         inline T value() const\n         {\n            T result = T(0);\n\n            if (arg_list_.empty())\n            {\n               return std::numeric_limits<T>::quiet_NaN();\n            }\n\n            const std::size_t upper_bound = (arg_list_.size() - 1);\n\n            for (std::size_t i = 0; i < upper_bound; i += 2)\n            {\n               expression_ptr condition  = arg_list_[i    ];\n               expression_ptr consequent = arg_list_[i + 1];\n\n               if (is_true(condition))\n               {\n                  result = consequent->value();\n               }\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_mswitch;\n         }\n\n      private:\n\n         std::vector<expression_ptr> arg_list_;\n         std::vector<unsigned char> delete_branch_;\n      };\n\n      template <typename T>\n      class ivariable\n      {\n      public:\n\n         virtual ~ivariable()\n         {}\n\n         virtual T& ref() = 0;\n         virtual const T& ref() const = 0;\n      };\n\n      template <typename T>\n      class variable_node : public expression_node<T>,\n                            public ivariable      <T>\n      {\n      public:\n\n         static T null_value;\n\n         explicit variable_node()\n         : value_(&null_value)\n         {}\n\n         variable_node(T& v)\n         : value_(&v)\n         {}\n\n         inline bool operator <(const variable_node<T>& v) const\n         {\n            return this < (&v);\n         }\n\n         inline T value() const\n         {\n            return (*value_);\n         }\n\n         inline T& ref()\n         {\n            return (*value_);\n         }\n\n         inline const T& ref() const\n         {\n            return (*value_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_variable;\n         }\n\n      private:\n\n         T* value_;\n      };\n\n      template <typename T>\n      T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());\n\n      template <typename T>\n      struct range_pack\n      {\n         typedef expression_node<T>*           expression_node_ptr;\n         typedef std::pair<std::size_t,std::size_t> cached_range_t;\n\n         range_pack()\n         : n0_e (std::make_pair(false,expression_node_ptr(0))),\n           n1_e (std::make_pair(false,expression_node_ptr(0))),\n           n0_c (std::make_pair(false,0)),\n           n1_c (std::make_pair(false,0)),\n           cache(std::make_pair(0,0))\n         {}\n\n         void clear()\n         {\n            n0_e  = std::make_pair(false,expression_node_ptr(0));\n            n1_e  = std::make_pair(false,expression_node_ptr(0));\n            n0_c  = std::make_pair(false,0);\n            n1_c  = std::make_pair(false,0);\n            cache = std::make_pair(0,0);\n         }\n\n         void free()\n         {\n            if (n0_e.first && n0_e.second)\n            {\n               n0_e.first = false;\n\n               if (\n                    !is_variable_node(n0_e.second) &&\n                    !is_string_node  (n0_e.second)\n                  )\n               {\n                  destroy_node(n0_e.second);\n               }\n            }\n\n            if (n1_e.first && n1_e.second)\n            {\n               n1_e.first = false;\n\n               if (\n                    !is_variable_node(n1_e.second) &&\n                    !is_string_node  (n1_e.second)\n                  )\n               {\n                  destroy_node(n1_e.second);\n               }\n            }\n         }\n\n         bool const_range()\n         {\n           return ( n0_c.first &&  n1_c.first) &&\n                  (!n0_e.first && !n1_e.first);\n         }\n\n         bool var_range()\n         {\n           return ( n0_e.first &&  n1_e.first) &&\n                  (!n0_c.first && !n1_c.first);\n         }\n\n         bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const\n         {\n            if (n0_c.first)\n               r0 = n0_c.second;\n            else if (n0_e.first)\n            {\n               T r0_value = n0_e.second->value();\n\n               if (r0_value < 0)\n                  return false;\n               else\n                  r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));\n            }\n            else\n               return false;\n\n            if (n1_c.first)\n               r1 = n1_c.second;\n            else if (n1_e.first)\n            {\n               T r1_value = n1_e.second->value();\n\n               if (r1_value < 0)\n                  return false;\n               else\n                  r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));\n            }\n            else\n               return false;\n\n            if (\n                 (std::numeric_limits<std::size_t>::max() != size) &&\n                 (std::numeric_limits<std::size_t>::max() == r1  )\n               )\n            {\n               r1 = size - 1;\n            }\n\n            cache.first  = r0;\n            cache.second = r1;\n\n            return (r0 <= r1);\n         }\n\n         inline std::size_t const_size() const\n         {\n            return (n1_c.second - n0_c.second + 1);\n         }\n\n         inline std::size_t cache_size() const\n         {\n            return (cache.second - cache.first + 1);\n         }\n\n         std::pair<bool,expression_node_ptr> n0_e;\n         std::pair<bool,expression_node_ptr> n1_e;\n         std::pair<bool,std::size_t        > n0_c;\n         std::pair<bool,std::size_t        > n1_c;\n         mutable cached_range_t             cache;\n      };\n\n      template <typename T>\n      class string_base_node;\n\n      template <typename T>\n      struct range_data_type\n      {\n         typedef range_pack<T> range_t;\n         typedef string_base_node<T>* strbase_ptr_t;\n\n         range_data_type()\n         : range(0),\n           data (0),\n           size (0),\n           type_size(0),\n           str_node (0)\n         {}\n\n         range_t*      range;\n         void*         data;\n         std::size_t   size;\n         std::size_t   type_size;\n         strbase_ptr_t str_node;\n      };\n\n      template <typename T> class vector_node;\n\n      template <typename T>\n      class vector_interface\n      {\n      public:\n\n         typedef vector_node<T>*   vector_node_ptr;\n         typedef vec_data_store<T>           vds_t;\n\n         virtual ~vector_interface()\n         {}\n\n         virtual std::size_t size   () const = 0;\n\n         virtual vector_node_ptr vec() const = 0;\n\n         virtual vector_node_ptr vec()       = 0;\n\n         virtual       vds_t& vds   ()       = 0;\n\n         virtual const vds_t& vds   () const = 0;\n\n         virtual bool side_effect   () const { return false; }\n      };\n\n      template <typename T>\n      class vector_node : public expression_node <T>,\n                          public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*  expression_ptr;\n         typedef vector_holder<T>    vector_holder_t;\n         typedef vector_node<T>*     vector_node_ptr;\n         typedef vec_data_store<T>             vds_t;\n\n         vector_node(vector_holder_t* vh)\n         : vector_holder_(vh),\n           vds_((*vector_holder_).size(),(*vector_holder_)[0])\n         {\n            vector_holder_->set_ref(&vds_.ref());\n         }\n\n         vector_node(const vds_t& vds, vector_holder_t* vh)\n         : vector_holder_(vh),\n           vds_(vds)\n         {}\n\n         inline T value() const\n         {\n            return vds().data()[0];\n         }\n\n         vector_node_ptr vec() const\n         {\n            return const_cast<vector_node_ptr>(this);\n         }\n\n         vector_node_ptr vec()\n         {\n            return this;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vector;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n         inline vector_holder_t& vec_holder()\n         {\n            return (*vector_holder_);\n         }\n\n      private:\n\n         vector_holder_t* vector_holder_;\n         vds_t                      vds_;\n      };\n\n      template <typename T>\n      class vector_elem_node : public expression_node<T>,\n                               public ivariable      <T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef vector_holder<T>    vector_holder_t;\n         typedef vector_holder_t*    vector_holder_ptr;\n\n         vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)\n         : index_(index),\n           vec_holder_(vec_holder),\n           vector_base_((*vec_holder)[0]),\n           index_deletable_(branch_deletable(index_))\n         {}\n\n        ~vector_elem_node()\n         {\n            if (index_ && index_deletable_)\n            {\n               destroy_node(index_);\n            }\n         }\n\n         inline T value() const\n         {\n            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));\n         }\n\n         inline T& ref()\n         {\n            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));\n         }\n\n         inline const T& ref() const\n         {\n            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecelem;\n         }\n\n         inline vector_holder_t& vec_holder()\n         {\n            return (*vec_holder_);\n         }\n\n      private:\n\n         expression_ptr index_;\n         vector_holder_ptr vec_holder_;\n         T* vector_base_;\n         const bool index_deletable_;\n      };\n\n      template <typename T>\n      class rebasevector_elem_node : public expression_node<T>,\n                                     public ivariable      <T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef vector_holder<T>    vector_holder_t;\n         typedef vector_holder_t*    vector_holder_ptr;\n         typedef vec_data_store<T>   vds_t;\n\n         rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)\n         : index_(index),\n           index_deletable_(branch_deletable(index_)),\n           vector_holder_(vec_holder),\n           vds_((*vector_holder_).size(),(*vector_holder_)[0])\n         {\n            vector_holder_->set_ref(&vds_.ref());\n         }\n\n        ~rebasevector_elem_node()\n         {\n            if (index_ && index_deletable_)\n            {\n               destroy_node(index_);\n            }\n         }\n\n         inline T value() const\n         {\n            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));\n         }\n\n         inline T& ref()\n         {\n            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));\n         }\n\n         inline const T& ref() const\n         {\n            return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_rbvecelem;\n         }\n\n         inline vector_holder_t& vec_holder()\n         {\n            return (*vector_holder_);\n         }\n\n      private:\n\n         expression_ptr index_;\n         const bool index_deletable_;\n         vector_holder_ptr vector_holder_;\n         vds_t             vds_;\n      };\n\n      template <typename T>\n      class rebasevector_celem_node : public expression_node<T>,\n                                      public ivariable      <T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef vector_holder<T>    vector_holder_t;\n         typedef vector_holder_t*    vector_holder_ptr;\n         typedef vec_data_store<T>   vds_t;\n\n         rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder)\n         : index_(index),\n           vector_holder_(vec_holder),\n           vds_((*vector_holder_).size(),(*vector_holder_)[0])\n         {\n            vector_holder_->set_ref(&vds_.ref());\n         }\n\n         inline T value() const\n         {\n            return *(vds_.data() + index_);\n         }\n\n         inline T& ref()\n         {\n            return *(vds_.data() + index_);\n         }\n\n         inline const T& ref() const\n         {\n            return *(vds_.data() + index_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_rbveccelem;\n         }\n\n         inline vector_holder_t& vec_holder()\n         {\n            return (*vector_holder_);\n         }\n\n      private:\n\n         const std::size_t index_;\n         vector_holder_ptr vector_holder_;\n         vds_t vds_;\n      };\n\n      template <typename T>\n      class vector_assignment_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         vector_assignment_node(T* vector_base,\n                                const std::size_t& size,\n                                const std::vector<expression_ptr>& initialiser_list,\n                                const bool single_value_initialse)\n         : vector_base_(vector_base),\n           initialiser_list_(initialiser_list),\n           size_(size),\n           single_value_initialse_(single_value_initialse)\n         {}\n\n        ~vector_assignment_node()\n         {\n            for (std::size_t i = 0; i < initialiser_list_.size(); ++i)\n            {\n               if (branch_deletable(initialiser_list_[i]))\n               {\n                  destroy_node(initialiser_list_[i]);\n               }\n            }\n         }\n\n         inline T value() const\n         {\n            if (single_value_initialse_)\n            {\n               for (std::size_t i = 0; i < size_; ++i)\n               {\n                  *(vector_base_ + i) = initialiser_list_[0]->value();\n               }\n            }\n            else\n            {\n               std::size_t il_size = initialiser_list_.size();\n\n               for (std::size_t i = 0; i < il_size; ++i)\n               {\n                  *(vector_base_ + i) = initialiser_list_[i]->value();\n               }\n\n               if (il_size < size_)\n               {\n                  for (std::size_t i = il_size; i < size_; ++i)\n                  {\n                     *(vector_base_ + i) = T(0);\n                  }\n               }\n            }\n\n            return *(vector_base_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecdefass;\n         }\n\n      private:\n\n         vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);\n\n         mutable T* vector_base_;\n         std::vector<expression_ptr> initialiser_list_;\n         const std::size_t size_;\n         const bool single_value_initialse_;\n      };\n\n      template <typename T>\n      class swap_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef variable_node<T>*   variable_node_ptr;\n\n         swap_node(variable_node_ptr var0, variable_node_ptr var1)\n         : var0_(var0),\n           var1_(var1)\n         {}\n\n         inline T value() const\n         {\n            std::swap(var0_->ref(),var1_->ref());\n            return var1_->ref();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_swap;\n         }\n\n      private:\n\n         variable_node_ptr var0_;\n         variable_node_ptr var1_;\n      };\n\n      template <typename T>\n      class swap_generic_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef ivariable<T>* ivariable_ptr;\n\n         swap_generic_node(expression_ptr var0, expression_ptr var1)\n         : binary_node<T>(details::e_swap, var0, var1),\n           var0_(dynamic_cast<ivariable_ptr>(var0)),\n           var1_(dynamic_cast<ivariable_ptr>(var1))\n         {}\n\n         inline T value() const\n         {\n            std::swap(var0_->ref(),var1_->ref());\n            return var1_->ref();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_swap;\n         }\n\n      private:\n\n         ivariable_ptr var0_;\n         ivariable_ptr var1_;\n      };\n\n      template <typename T>\n      class swap_vecvec_node : public binary_node     <T>,\n                               public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*  expression_ptr;\n         typedef vector_node<T>*     vector_node_ptr;\n         typedef vec_data_store<T>             vds_t;\n\n         swap_vecvec_node(expression_ptr branch0,\n                          expression_ptr branch1)\n         : binary_node<T>(details::e_swap, branch0, branch1),\n           vec0_node_ptr_(0),\n           vec1_node_ptr_(0),\n           vec_size_     (0),\n           initialised_  (false)\n         {\n            if (is_ivector_node(binary_node<T>::branch_[0].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))\n               {\n                  vec0_node_ptr_ = vi->vec();\n                  vds()          = vi->vds();\n               }\n            }\n\n            if (is_ivector_node(binary_node<T>::branch_[1].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))\n               {\n                  vec1_node_ptr_ = vi->vec();\n               }\n            }\n\n            if (vec0_node_ptr_ && vec1_node_ptr_)\n            {\n               vec_size_ = std::min(vec0_node_ptr_->vds().size(),\n                                    vec1_node_ptr_->vds().size());\n\n               initialised_ = true;\n            }\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               T* vec0 = vec0_node_ptr_->vds().data();\n               T* vec1 = vec1_node_ptr_->vds().data();\n\n               for (std::size_t i = 0; i < vec_size_; ++i)\n               {\n                  std::swap(vec0[i],vec1[i]);\n               }\n\n               return vec1_node_ptr_->value();\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return vec0_node_ptr_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return vec0_node_ptr_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecvecswap;\n         }\n\n         std::size_t size() const\n         {\n            return vec_size_;\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node<T>* vec0_node_ptr_;\n         vector_node<T>* vec1_node_ptr_;\n         std::size_t     vec_size_;\n         bool            initialised_;\n         vds_t           vds_;\n      };\n\n      #ifndef exprtk_disable_string_capabilities\n      template <typename T>\n      class stringvar_node : public expression_node <T>,\n                             public string_base_node<T>,\n                             public range_interface <T>\n      {\n      public:\n\n         typedef range_pack<T> range_t;\n\n         static std::string null_value;\n\n         explicit stringvar_node()\n         : value_(&null_value)\n         {}\n\n         explicit stringvar_node(std::string& v)\n         : value_(&v)\n         {\n            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);\n            rp_.cache.first  = rp_.n0_c.second;\n            rp_.cache.second = rp_.n1_c.second;\n         }\n\n         inline bool operator <(const stringvar_node<T>& v) const\n         {\n            return this < (&v);\n         }\n\n         inline T value() const\n         {\n            rp_.n1_c.second  = (*value_).size() - 1;\n            rp_.cache.second = rp_.n1_c.second;\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return ref();\n         }\n\n         const char_t* base() const\n         {\n            return &(*value_)[0];\n         }\n\n         std::size_t size() const\n         {\n            return ref().size();\n         }\n\n         std::string& ref()\n         {\n            return (*value_);\n         }\n\n         const std::string& ref() const\n         {\n            return (*value_);\n         }\n\n         range_t& range_ref()\n         {\n            return rp_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return rp_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_stringvar;\n         }\n\n      private:\n\n         std::string* value_;\n         mutable range_t rp_;\n      };\n\n      template <typename T>\n      std::string stringvar_node<T>::null_value = std::string(\"\");\n\n      template <typename T>\n      class string_range_node : public expression_node <T>,\n                                public string_base_node<T>,\n                                public range_interface <T>\n      {\n      public:\n\n         typedef range_pack<T> range_t;\n\n         static std::string null_value;\n\n         explicit string_range_node(std::string& v, const range_t& rp)\n         : value_(&v),\n           rp_(rp)\n         {}\n\n         virtual ~string_range_node()\n         {\n            rp_.free();\n         }\n\n         inline bool operator <(const string_range_node<T>& v) const\n         {\n            return this < (&v);\n         }\n\n         inline T value() const\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline std::string str() const\n         {\n            return (*value_);\n         }\n\n         const char_t* base() const\n         {\n            return &(*value_)[0];\n         }\n\n         std::size_t size() const\n         {\n            return ref().size();\n         }\n\n         inline range_t range() const\n         {\n            return rp_;\n         }\n\n         inline virtual std::string& ref()\n         {\n            return (*value_);\n         }\n\n         inline virtual const std::string& ref() const\n         {\n            return (*value_);\n         }\n\n         inline range_t& range_ref()\n         {\n            return rp_;\n         }\n\n         inline const range_t& range_ref() const\n         {\n            return rp_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_stringvarrng;\n         }\n\n      private:\n\n         std::string* value_;\n         range_t      rp_;\n      };\n\n      template <typename T>\n      std::string string_range_node<T>::null_value = std::string(\"\");\n\n      template <typename T>\n      class const_string_range_node : public expression_node <T>,\n                                      public string_base_node<T>,\n                                      public range_interface <T>\n      {\n      public:\n\n         typedef range_pack<T> range_t;\n\n         explicit const_string_range_node(const std::string& v, const range_t& rp)\n         : value_(v),\n           rp_(rp)\n         {}\n\n        ~const_string_range_node()\n         {\n            rp_.free();\n         }\n\n         inline T value() const\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return value_;\n         }\n\n         const char_t* base() const\n         {\n            return value_.data();\n         }\n\n         std::size_t size() const\n         {\n            return value_.size();\n         }\n\n         range_t range() const\n         {\n            return rp_;\n         }\n\n         range_t& range_ref()\n         {\n            return rp_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return rp_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_cstringvarrng;\n         }\n\n      private:\n\n         const_string_range_node<T>& operator=(const const_string_range_node<T>&);\n\n         const std::string value_;\n         range_t rp_;\n      };\n\n      template <typename T>\n      class generic_string_range_node : public expression_node <T>,\n                                        public string_base_node<T>,\n                                        public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>*  expression_ptr;\n         typedef stringvar_node  <T>* strvar_node_ptr;\n         typedef string_base_node<T>*    str_base_ptr;\n         typedef range_pack      <T>          range_t;\n         typedef range_t*                   range_ptr;\n         typedef range_interface<T>          irange_t;\n         typedef irange_t*                 irange_ptr;\n\n         generic_string_range_node(expression_ptr str_branch, const range_t& brange)\n         : initialised_(false),\n           branch_(str_branch),\n           branch_deletable_(branch_deletable(branch_)),\n           str_base_ptr_ (0),\n           str_range_ptr_(0),\n           base_range_(brange)\n         {\n            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.cache.first  = range_.n0_c.second;\n            range_.cache.second = range_.n1_c.second;\n\n            if (is_generally_string_node(branch_))\n            {\n               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);\n\n               if (0 == str_base_ptr_)\n                  return;\n\n               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);\n\n               if (0 == str_range_ptr_)\n                  return;\n            }\n\n            initialised_ = (str_base_ptr_ && str_range_ptr_);\n         }\n\n        ~generic_string_range_node()\n         {\n            base_range_.free();\n\n            if (branch_ && branch_deletable_)\n            {\n               destroy_node(branch_);\n            }\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               branch_->value();\n\n               std::size_t str_r0 = 0;\n               std::size_t str_r1 = 0;\n\n               std::size_t r0 = 0;\n               std::size_t r1 = 0;\n\n               range_t& range = str_range_ptr_->range_ref();\n\n               const std::size_t base_str_size = str_base_ptr_->size();\n\n               if (\n                    range      (str_r0,str_r1,base_str_size) &&\n                    base_range_(    r0,    r1,base_str_size)\n                  )\n               {\n                  const std::size_t size = (r1 - r0) + 1;\n\n                  range_.n1_c.second  = size - 1;\n                  range_.cache.second = range_.n1_c.second;\n\n                  value_.assign(str_base_ptr_->base() + str_r0 + r0, size);\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return value_;\n         }\n\n         const char_t* base() const\n         {\n            return &value_[0];\n         }\n\n         std::size_t size() const\n         {\n            return value_.size();\n         }\n\n         range_t& range_ref()\n         {\n            return range_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return range_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strgenrange;\n         }\n\n      private:\n\n         bool                initialised_;\n         expression_ptr           branch_;\n         const bool     branch_deletable_;\n         str_base_ptr       str_base_ptr_;\n         irange_ptr        str_range_ptr_;\n         mutable range_t      base_range_;\n         mutable range_t           range_;\n         mutable std::string       value_;\n      };\n\n      template <typename T>\n      class string_concat_node : public binary_node     <T>,\n                                 public string_base_node<T>,\n                                 public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>*  expression_ptr;\n         typedef string_base_node<T>*    str_base_ptr;\n         typedef range_pack      <T>          range_t;\n         typedef range_t*                   range_ptr;\n         typedef range_interface<T>          irange_t;\n         typedef irange_t*                 irange_ptr;\n\n         string_concat_node(const operator_type& opr,\n                            expression_ptr branch0,\n                            expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           initialised_(false),\n           str0_base_ptr_ (0),\n           str1_base_ptr_ (0),\n           str0_range_ptr_(0),\n           str1_range_ptr_(0)\n         {\n            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);\n\n            range_.cache.first  = range_.n0_c.second;\n            range_.cache.second = range_.n1_c.second;\n\n            if (is_generally_string_node(binary_node<T>::branch_[0].first))\n            {\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == str0_base_ptr_)\n                  return;\n\n               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == str0_range_ptr_)\n                  return;\n            }\n\n            if (is_generally_string_node(binary_node<T>::branch_[1].first))\n            {\n               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == str1_base_ptr_)\n                  return;\n\n               str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == str1_range_ptr_)\n                  return;\n            }\n\n            initialised_ = str0_base_ptr_  &&\n                           str1_base_ptr_  &&\n                           str0_range_ptr_ &&\n                           str1_range_ptr_ ;\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               std::size_t str0_r0 = 0;\n               std::size_t str0_r1 = 0;\n\n               std::size_t str1_r0 = 0;\n               std::size_t str1_r1 = 0;\n\n               range_t& range0 = str0_range_ptr_->range_ref();\n               range_t& range1 = str1_range_ptr_->range_ref();\n\n               if (\n                    range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&\n                    range1(str1_r0,str1_r1,str1_base_ptr_->size())\n                  )\n               {\n                  const std::size_t size0 = (str0_r1 - str0_r0) + 1;\n                  const std::size_t size1 = (str1_r1 - str1_r0) + 1;\n\n                  value_.assign(str0_base_ptr_->base() + str0_r0, size0);\n                  value_.append(str1_base_ptr_->base() + str1_r0, size1);\n\n                  range_.n1_c.second  = value_.size() - 1;\n                  range_.cache.second = range_.n1_c.second;\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return value_;\n         }\n\n         const char_t* base() const\n         {\n            return &value_[0];\n         }\n\n         std::size_t size() const\n         {\n            return value_.size();\n         }\n\n         range_t& range_ref()\n         {\n            return range_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return range_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strconcat;\n         }\n\n      private:\n\n         bool initialised_;\n         str_base_ptr str0_base_ptr_;\n         str_base_ptr str1_base_ptr_;\n         irange_ptr   str0_range_ptr_;\n         irange_ptr   str1_range_ptr_;\n         mutable range_t     range_;\n         mutable std::string value_;\n      };\n\n      template <typename T>\n      class swap_string_node : public binary_node     <T>,\n                               public string_base_node<T>,\n                               public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>*  expression_ptr;\n         typedef stringvar_node  <T>* strvar_node_ptr;\n         typedef string_base_node<T>*    str_base_ptr;\n         typedef range_pack      <T>          range_t;\n         typedef range_t*                   range_ptr;\n         typedef range_interface<T>          irange_t;\n         typedef irange_t*                 irange_ptr;\n\n         swap_string_node(expression_ptr branch0, expression_ptr branch1)\n         : binary_node<T>(details::e_swap, branch0, branch1),\n           initialised_(false),\n           str0_node_ptr_(0),\n           str1_node_ptr_(0)\n         {\n            if (is_string_node(binary_node<T>::branch_[0].first))\n            {\n               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);\n            }\n\n            if (is_string_node(binary_node<T>::branch_[1].first))\n            {\n               str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);\n            }\n\n            initialised_ = (str0_node_ptr_ && str1_node_ptr_);\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref());\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return str0_node_ptr_->str();\n         }\n\n         const char_t* base() const\n         {\n           return str0_node_ptr_->base();\n         }\n\n         std::size_t size() const\n         {\n            return str0_node_ptr_->size();\n         }\n\n         range_t& range_ref()\n         {\n            return str0_node_ptr_->range_ref();\n         }\n\n         const range_t& range_ref() const\n         {\n            return str0_node_ptr_->range_ref();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strswap;\n         }\n\n      private:\n\n         bool initialised_;\n         strvar_node_ptr str0_node_ptr_;\n         strvar_node_ptr str1_node_ptr_;\n      };\n\n      template <typename T>\n      class swap_genstrings_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node <T>* expression_ptr;\n         typedef string_base_node<T>*   str_base_ptr;\n         typedef range_pack      <T>         range_t;\n         typedef range_t*                  range_ptr;\n         typedef range_interface<T>         irange_t;\n         typedef irange_t*                irange_ptr;\n\n         swap_genstrings_node(expression_ptr branch0,\n                              expression_ptr branch1)\n         : binary_node<T>(details::e_default, branch0, branch1),\n           str0_base_ptr_ (0),\n           str1_base_ptr_ (0),\n           str0_range_ptr_(0),\n           str1_range_ptr_(0),\n           initialised_(false)\n         {\n            if (is_generally_string_node(binary_node<T>::branch_[0].first))\n            {\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == str0_base_ptr_)\n                  return;\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str0_range_ptr_ = &(range_ptr->range_ref());\n            }\n\n            if (is_generally_string_node(binary_node<T>::branch_[1].first))\n            {\n               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == str1_base_ptr_)\n                  return;\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str1_range_ptr_ = &(range_ptr->range_ref());\n            }\n\n            initialised_ = str0_base_ptr_  &&\n                           str1_base_ptr_  &&\n                           str0_range_ptr_ &&\n                           str1_range_ptr_ ;\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               std::size_t str0_r0 = 0;\n               std::size_t str0_r1 = 0;\n\n               std::size_t str1_r0 = 0;\n               std::size_t str1_r1 = 0;\n\n               range_t& range0 = (*str0_range_ptr_);\n               range_t& range1 = (*str1_range_ptr_);\n\n               if (\n                    range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&\n                    range1(str1_r0,str1_r1,str1_base_ptr_->size())\n                  )\n               {\n                  const std::size_t size0    = range0.cache_size();\n                  const std::size_t size1    = range1.cache_size();\n                  const std::size_t max_size = std::min(size0,size1);\n\n                  char_t* s0 = const_cast<char_t*>(str0_base_ptr_->base() + str0_r0);\n                  char_t* s1 = const_cast<char_t*>(str1_base_ptr_->base() + str1_r0);\n\n                  loop_unroll::details lud(max_size);\n                  const char_t* upper_bound = s0 + lud.upper_bound;\n\n                  while (s0 < upper_bound)\n                  {\n                     #define exprtk_loop(N)   \\\n                     std::swap(s0[N], s1[N]); \\\n\n                     exprtk_loop( 0) exprtk_loop( 1)\n                     exprtk_loop( 2) exprtk_loop( 3)\n                     #ifndef exprtk_disable_superscalar_unroll\n                     exprtk_loop( 4) exprtk_loop( 5)\n                     exprtk_loop( 6) exprtk_loop( 7)\n                     exprtk_loop( 8) exprtk_loop( 9)\n                     exprtk_loop(10) exprtk_loop(11)\n                     exprtk_loop(12) exprtk_loop(13)\n                     exprtk_loop(14) exprtk_loop(15)\n                     #endif\n\n                     s0 += lud.batch_size;\n                     s1 += lud.batch_size;\n                  }\n\n                  int i = 0;\n\n                  exprtk_disable_fallthrough_begin\n                  switch (lud.remainder)\n                  {\n                     #define case_stmt(N)                      \\\n                     case N : { std::swap(s0[i],s1[i]); ++i; } \\\n\n                     #ifndef exprtk_disable_superscalar_unroll\n                     case_stmt(15) case_stmt(14)\n                     case_stmt(13) case_stmt(12)\n                     case_stmt(11) case_stmt(10)\n                     case_stmt( 9) case_stmt( 8)\n                     case_stmt( 7) case_stmt( 6)\n                     case_stmt( 5) case_stmt( 4)\n                     #endif\n                     case_stmt( 3) case_stmt( 2)\n                     case_stmt( 1)\n                  }\n                  exprtk_disable_fallthrough_end\n\n                  #undef exprtk_loop\n                  #undef case_stmt\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strswap;\n         }\n\n      private:\n\n         swap_genstrings_node(swap_genstrings_node<T>&);\n         swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&);\n\n         str_base_ptr str0_base_ptr_;\n         str_base_ptr str1_base_ptr_;\n         range_ptr    str0_range_ptr_;\n         range_ptr    str1_range_ptr_;\n         bool         initialised_;\n      };\n\n      template <typename T>\n      class stringvar_size_node : public expression_node<T>\n      {\n      public:\n\n         static std::string null_value;\n\n         explicit stringvar_size_node()\n         : value_(&null_value)\n         {}\n\n         explicit stringvar_size_node(std::string& v)\n         : value_(&v)\n         {}\n\n         inline T value() const\n         {\n            return T((*value_).size());\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_stringvarsize;\n         }\n\n      private:\n\n         std::string* value_;\n      };\n\n      template <typename T>\n      std::string stringvar_size_node<T>::null_value = std::string(\"\");\n\n      template <typename T>\n      class string_size_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node <T>* expression_ptr;\n         typedef string_base_node<T>*   str_base_ptr;\n\n         string_size_node(expression_ptr brnch)\n         : branch_(brnch),\n           branch_deletable_(branch_deletable(branch_)),\n           str_base_ptr_(0)\n         {\n            if (is_generally_string_node(branch_))\n            {\n               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);\n\n               if (0 == str_base_ptr_)\n                  return;\n            }\n         }\n\n        ~string_size_node()\n         {\n            if (branch_ && branch_deletable_)\n            {\n               destroy_node(branch_);\n            }\n         }\n\n         inline T value() const\n         {\n            T result = std::numeric_limits<T>::quiet_NaN();\n\n            if (str_base_ptr_)\n            {\n               branch_->value();\n               result = T(str_base_ptr_->size());\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_stringsize;\n         }\n\n      private:\n\n         expression_ptr           branch_;\n         const bool     branch_deletable_;\n         str_base_ptr       str_base_ptr_;\n      };\n\n      struct asn_assignment\n      {\n         static inline void execute(std::string& s, const char_t* data, const std::size_t size)\n         { s.assign(data,size); }\n      };\n\n      struct asn_addassignment\n      {\n         static inline void execute(std::string& s, const char_t* data, const std::size_t size)\n         { s.append(data,size); }\n      };\n\n      template <typename T, typename AssignmentProcess = asn_assignment>\n      class assignment_string_node : public binary_node     <T>,\n                                     public string_base_node<T>,\n                                     public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>*  expression_ptr;\n         typedef stringvar_node  <T>* strvar_node_ptr;\n         typedef string_base_node<T>*    str_base_ptr;\n         typedef range_pack      <T>          range_t;\n         typedef range_t*                   range_ptr;\n         typedef range_interface<T>          irange_t;\n         typedef irange_t*                 irange_ptr;\n\n         assignment_string_node(const operator_type& opr,\n                                expression_ptr branch0,\n                                expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           initialised_(false),\n           str0_base_ptr_ (0),\n           str1_base_ptr_ (0),\n           str0_node_ptr_ (0),\n           str1_range_ptr_(0)\n         {\n            if (is_string_node(binary_node<T>::branch_[0].first))\n            {\n               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);\n\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);\n            }\n\n            if (is_generally_string_node(binary_node<T>::branch_[1].first))\n            {\n               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == str1_base_ptr_)\n                  return;\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str1_range_ptr_ = &(range_ptr->range_ref());\n            }\n\n            initialised_ = str0_base_ptr_  &&\n                           str1_base_ptr_  &&\n                           str0_node_ptr_  &&\n                           str1_range_ptr_ ;\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[1].first->value();\n\n               std::size_t r0 = 0;\n               std::size_t r1 = 0;\n\n               range_t& range = (*str1_range_ptr_);\n\n               if (range(r0, r1, str1_base_ptr_->size()))\n               {\n                  AssignmentProcess::execute(str0_node_ptr_->ref(),\n                                             str1_base_ptr_->base() + r0,\n                                             (r1 - r0) + 1);\n\n                  binary_node<T>::branch_[0].first->value();\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return str0_node_ptr_->str();\n         }\n\n         const char_t* base() const\n         {\n           return str0_node_ptr_->base();\n         }\n\n         std::size_t size() const\n         {\n            return str0_node_ptr_->size();\n         }\n\n         range_t& range_ref()\n         {\n            return str0_node_ptr_->range_ref();\n         }\n\n         const range_t& range_ref() const\n         {\n            return str0_node_ptr_->range_ref();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strass;\n         }\n\n      private:\n\n         bool            initialised_;\n         str_base_ptr    str0_base_ptr_;\n         str_base_ptr    str1_base_ptr_;\n         strvar_node_ptr str0_node_ptr_;\n         range_ptr       str1_range_ptr_;\n      };\n\n      template <typename T, typename AssignmentProcess = asn_assignment>\n      class assignment_string_range_node : public binary_node     <T>,\n                                           public string_base_node<T>,\n                                           public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>*  expression_ptr;\n         typedef stringvar_node  <T>* strvar_node_ptr;\n         typedef string_base_node<T>*    str_base_ptr;\n         typedef range_pack      <T>          range_t;\n         typedef range_t*                   range_ptr;\n         typedef range_interface<T>          irange_t;\n         typedef irange_t*                 irange_ptr;\n\n         assignment_string_range_node(const operator_type& opr,\n                                      expression_ptr branch0,\n                                      expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           initialised_(false),\n           str0_base_ptr_ (0),\n           str1_base_ptr_ (0),\n           str0_node_ptr_ (0),\n           str0_range_ptr_(0),\n           str1_range_ptr_(0)\n         {\n            if (is_string_range_node(binary_node<T>::branch_[0].first))\n            {\n               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);\n\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str0_range_ptr_ = &(range_ptr->range_ref());\n            }\n\n            if (is_generally_string_node(binary_node<T>::branch_[1].first))\n            {\n               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == str1_base_ptr_)\n                  return;\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str1_range_ptr_ = &(range_ptr->range_ref());\n            }\n\n            initialised_ = str0_base_ptr_  &&\n                           str1_base_ptr_  &&\n                           str0_node_ptr_  &&\n                           str0_range_ptr_ &&\n                           str1_range_ptr_ ;\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               std::size_t s0_r0 = 0;\n               std::size_t s0_r1 = 0;\n\n               std::size_t s1_r0 = 0;\n               std::size_t s1_r1 = 0;\n\n               range_t& range0 = (*str0_range_ptr_);\n               range_t& range1 = (*str1_range_ptr_);\n\n               if (\n                    range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&\n                    range1(s1_r0, s1_r1, str1_base_ptr_->size())\n                  )\n               {\n                  std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1;\n\n                  std::copy(str1_base_ptr_->base() + s1_r0,\n                            str1_base_ptr_->base() + s1_r0 + size,\n                            const_cast<char_t*>(base() + s0_r0));\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return str0_node_ptr_->str();\n         }\n\n         const char_t* base() const\n         {\n           return str0_node_ptr_->base();\n         }\n\n         std::size_t size() const\n         {\n            return str0_node_ptr_->size();\n         }\n\n         range_t& range_ref()\n         {\n            return str0_node_ptr_->range_ref();\n         }\n\n         const range_t& range_ref() const\n         {\n            return str0_node_ptr_->range_ref();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strass;\n         }\n\n      private:\n\n         bool            initialised_;\n         str_base_ptr    str0_base_ptr_;\n         str_base_ptr    str1_base_ptr_;\n         strvar_node_ptr str0_node_ptr_;\n         range_ptr       str0_range_ptr_;\n         range_ptr       str1_range_ptr_;\n      };\n\n      template <typename T>\n      class conditional_string_node : public trinary_node    <T>,\n                                      public string_base_node<T>,\n                                      public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>* expression_ptr;\n         typedef string_base_node<T>*   str_base_ptr;\n         typedef range_pack      <T>         range_t;\n         typedef range_t*                  range_ptr;\n         typedef range_interface<T>         irange_t;\n         typedef irange_t*                irange_ptr;\n\n         conditional_string_node(expression_ptr test,\n                                 expression_ptr consequent,\n                                 expression_ptr alternative)\n         : trinary_node<T>(details::e_default,consequent,alternative,test),\n           initialised_(false),\n           str0_base_ptr_ (0),\n           str1_base_ptr_ (0),\n           str0_range_ptr_(0),\n           str1_range_ptr_(0),\n           test_              (test),\n           consequent_  (consequent),\n           alternative_(alternative)\n         {\n            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);\n\n            range_.cache.first  = range_.n0_c.second;\n            range_.cache.second = range_.n1_c.second;\n\n            if (is_generally_string_node(trinary_node<T>::branch_[0].first))\n            {\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);\n\n               if (0 == str0_base_ptr_)\n                  return;\n\n               str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);\n\n               if (0 == str0_range_ptr_)\n                  return;\n            }\n\n            if (is_generally_string_node(trinary_node<T>::branch_[1].first))\n            {\n               str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);\n\n               if (0 == str1_base_ptr_)\n                  return;\n\n               str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);\n\n               if (0 == str1_range_ptr_)\n                  return;\n            }\n\n            initialised_ = str0_base_ptr_  &&\n                           str1_base_ptr_  &&\n                           str0_range_ptr_ &&\n                           str1_range_ptr_ ;\n\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               std::size_t r0 = 0;\n               std::size_t r1 = 0;\n\n               if (is_true(test_))\n               {\n                  consequent_->value();\n\n                  range_t& range = str0_range_ptr_->range_ref();\n\n                  if (range(r0,r1,str0_base_ptr_->size()))\n                  {\n                     const std::size_t size = (r1 - r0) + 1;\n\n                     value_.assign(str0_base_ptr_->base() + r0, size);\n\n                     range_.n1_c.second  = value_.size() - 1;\n                     range_.cache.second = range_.n1_c.second;\n\n                     return T(1);\n                  }\n               }\n               else\n               {\n                  alternative_->value();\n\n                  range_t& range = str1_range_ptr_->range_ref();\n\n                  if (range(r0,r1,str1_base_ptr_->size()))\n                  {\n                     const std::size_t size = (r1 - r0) + 1;\n\n                     value_.assign(str1_base_ptr_->base() + r0, size);\n\n                     range_.n1_c.second  = value_.size() - 1;\n                     range_.cache.second = range_.n1_c.second;\n\n                     return T(0);\n                  }\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return value_;\n         }\n\n         const char_t* base() const\n         {\n            return &value_[0];\n         }\n\n         std::size_t size() const\n         {\n            return value_.size();\n         }\n\n         range_t& range_ref()\n         {\n            return range_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return range_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strcondition;\n         }\n\n      private:\n\n         bool initialised_;\n         str_base_ptr str0_base_ptr_;\n         str_base_ptr str1_base_ptr_;\n         irange_ptr   str0_range_ptr_;\n         irange_ptr   str1_range_ptr_;\n         mutable range_t     range_;\n         mutable std::string value_;\n\n         expression_ptr test_;\n         expression_ptr consequent_;\n         expression_ptr alternative_;\n      };\n\n      template <typename T>\n      class cons_conditional_str_node : public binary_node     <T>,\n                                        public string_base_node<T>,\n                                        public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>* expression_ptr;\n         typedef string_base_node<T>*   str_base_ptr;\n         typedef range_pack      <T>         range_t;\n         typedef range_t*                  range_ptr;\n         typedef range_interface<T>         irange_t;\n         typedef irange_t*                irange_ptr;\n\n         cons_conditional_str_node(expression_ptr test,\n                                   expression_ptr consequent)\n         : binary_node<T>(details::e_default, consequent, test),\n           initialised_(false),\n           str0_base_ptr_ (0),\n           str0_range_ptr_(0),\n           test_      (test),\n           consequent_(consequent)\n         {\n            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);\n\n            range_.cache.first  = range_.n0_c.second;\n            range_.cache.second = range_.n1_c.second;\n\n            if (is_generally_string_node(binary_node<T>::branch_[0].first))\n            {\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == str0_base_ptr_)\n                  return;\n\n               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == str0_range_ptr_)\n                  return;\n            }\n\n            initialised_ = str0_base_ptr_ && str0_range_ptr_ ;\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               if (is_true(test_))\n               {\n                  consequent_->value();\n\n                  range_t& range = str0_range_ptr_->range_ref();\n\n                  std::size_t r0 = 0;\n                  std::size_t r1 = 0;\n\n                  if (range(r0,r1,str0_base_ptr_->size()))\n                  {\n                     const std::size_t size = (r1 - r0) + 1;\n\n                     value_.assign(str0_base_ptr_->base() + r0, size);\n\n                     range_.n1_c.second  = value_.size() - 1;\n                     range_.cache.second = range_.n1_c.second;\n\n                     return T(1);\n                  }\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return value_;\n         }\n\n         const char_t* base() const\n         {\n            return &value_[0];\n         }\n\n         std::size_t size() const\n         {\n            return value_.size();\n         }\n\n         range_t& range_ref()\n         {\n            return range_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return range_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strccondition;\n         }\n\n      private:\n\n         bool initialised_;\n         str_base_ptr str0_base_ptr_;\n         irange_ptr   str0_range_ptr_;\n         mutable range_t     range_;\n         mutable std::string value_;\n\n         expression_ptr test_;\n         expression_ptr consequent_;\n      };\n\n      template <typename T, typename VarArgFunction>\n      class str_vararg_node  : public expression_node <T>,\n                               public string_base_node<T>,\n                               public range_interface <T>\n      {\n      public:\n\n         typedef expression_node <T>*  expression_ptr;\n         typedef string_base_node<T>*    str_base_ptr;\n         typedef range_pack      <T>          range_t;\n         typedef range_t*                   range_ptr;\n         typedef range_interface<T>          irange_t;\n         typedef irange_t*                 irange_ptr;\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)\n         : final_node_(arg_list.back()),\n           final_deletable_(branch_deletable(final_node_)),\n           initialised_(false),\n           str_base_ptr_ (0),\n           str_range_ptr_(0)\n         {\n            if (0 == final_node_)\n               return;\n            else if (!is_generally_string_node(final_node_))\n               return;\n\n            str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);\n\n            if (0 == str_base_ptr_)\n               return;\n\n            str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);\n\n            if (0 == str_range_ptr_)\n               return;\n\n            initialised_ = str_base_ptr_  && str_range_ptr_;\n\n            if (arg_list.size() > 1)\n            {\n               const std::size_t arg_list_size = arg_list.size() - 1;\n\n               arg_list_.resize(arg_list_size);\n               delete_branch_.resize(arg_list_size);\n\n               for (std::size_t i = 0; i < arg_list_size; ++i)\n               {\n                  if (arg_list[i])\n                  {\n                          arg_list_[i] = arg_list[i];\n                     delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);\n                  }\n                  else\n                  {\n                     arg_list_.clear();\n                     delete_branch_.clear();\n                     return;\n                  }\n               }\n            }\n         }\n\n        ~str_vararg_node()\n         {\n            if (final_node_ && final_deletable_)\n            {\n               destroy_node(final_node_);\n            }\n\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               if (arg_list_[i] && delete_branch_[i])\n               {\n                  destroy_node(arg_list_[i]);\n               }\n            }\n         }\n\n         inline T value() const\n         {\n            if (!arg_list_.empty())\n            {\n               VarArgFunction::process(arg_list_);\n            }\n\n            final_node_->value();\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         std::string str() const\n         {\n            return str_base_ptr_->str();\n         }\n\n         const char_t* base() const\n         {\n            return str_base_ptr_->base();\n         }\n\n         std::size_t size() const\n         {\n            return str_base_ptr_->size();\n         }\n\n         range_t& range_ref()\n         {\n            return str_range_ptr_->range_ref();\n         }\n\n         const range_t& range_ref() const\n         {\n            return str_range_ptr_->range_ref();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_stringvararg;\n         }\n\n      private:\n\n         expression_ptr final_node_;\n         bool           final_deletable_;\n         bool           initialised_;\n         str_base_ptr   str_base_ptr_;\n         irange_ptr     str_range_ptr_;\n         std::vector<expression_ptr> arg_list_;\n         std::vector<unsigned char> delete_branch_;\n      };\n      #endif\n\n      template <typename T, std::size_t N>\n      inline T axn(T a, T x)\n      {\n         // a*x^n\n         return a * exprtk::details::numeric::fast_exp<T,N>::result(x);\n      }\n\n      template <typename T, std::size_t N>\n      inline T axnb(T a, T x, T b)\n      {\n         // a*x^n+b\n         return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;\n      }\n\n      template <typename T>\n      struct sf_base\n      {\n         typedef typename details::functor_t<T>::Type Type;\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::qfunc_t quaternary_functor_t;\n         typedef typename functor_t::tfunc_t    trinary_functor_t;\n         typedef typename functor_t::bfunc_t     binary_functor_t;\n         typedef typename functor_t::ufunc_t      unary_functor_t;\n      };\n\n      #define define_sfop3(NN,OP0,OP1)                   \\\n      template <typename T>                              \\\n      struct sf##NN##_op : public sf_base<T>             \\\n      {                                                  \\\n         typedef typename sf_base<T>::Type Type;         \\\n         static inline T process(Type x, Type y, Type z) \\\n         {                                               \\\n            return (OP0);                                \\\n         }                                               \\\n         static inline std::string id()                  \\\n         {                                               \\\n            return OP1;                                  \\\n         }                                               \\\n      };                                                 \\\n\n      define_sfop3(00,(x + y) / z       ,\"(t+t)/t\")\n      define_sfop3(01,(x + y) * z       ,\"(t+t)*t\")\n      define_sfop3(02,(x + y) - z       ,\"(t+t)-t\")\n      define_sfop3(03,(x + y) + z       ,\"(t+t)+t\")\n      define_sfop3(04,(x - y) + z       ,\"(t-t)+t\")\n      define_sfop3(05,(x - y) / z       ,\"(t-t)/t\")\n      define_sfop3(06,(x - y) * z       ,\"(t-t)*t\")\n      define_sfop3(07,(x * y) + z       ,\"(t*t)+t\")\n      define_sfop3(08,(x * y) - z       ,\"(t*t)-t\")\n      define_sfop3(09,(x * y) / z       ,\"(t*t)/t\")\n      define_sfop3(10,(x * y) * z       ,\"(t*t)*t\")\n      define_sfop3(11,(x / y) + z       ,\"(t/t)+t\")\n      define_sfop3(12,(x / y) - z       ,\"(t/t)-t\")\n      define_sfop3(13,(x / y) / z       ,\"(t/t)/t\")\n      define_sfop3(14,(x / y) * z       ,\"(t/t)*t\")\n      define_sfop3(15,x / (y + z)       ,\"t/(t+t)\")\n      define_sfop3(16,x / (y - z)       ,\"t/(t-t)\")\n      define_sfop3(17,x / (y * z)       ,\"t/(t*t)\")\n      define_sfop3(18,x / (y / z)       ,\"t/(t/t)\")\n      define_sfop3(19,x * (y + z)       ,\"t*(t+t)\")\n      define_sfop3(20,x * (y - z)       ,\"t*(t-t)\")\n      define_sfop3(21,x * (y * z)       ,\"t*(t*t)\")\n      define_sfop3(22,x * (y / z)       ,\"t*(t/t)\")\n      define_sfop3(23,x - (y + z)       ,\"t-(t+t)\")\n      define_sfop3(24,x - (y - z)       ,\"t-(t-t)\")\n      define_sfop3(25,x - (y / z)       ,\"t-(t/t)\")\n      define_sfop3(26,x - (y * z)       ,\"t-(t*t)\")\n      define_sfop3(27,x + (y * z)       ,\"t+(t*t)\")\n      define_sfop3(28,x + (y / z)       ,\"t+(t/t)\")\n      define_sfop3(29,x + (y + z)       ,\"t+(t+t)\")\n      define_sfop3(30,x + (y - z)       ,\"t+(t-t)\")\n      define_sfop3(31,(axnb<T,2>(x,y,z)),\"       \")\n      define_sfop3(32,(axnb<T,3>(x,y,z)),\"       \")\n      define_sfop3(33,(axnb<T,4>(x,y,z)),\"       \")\n      define_sfop3(34,(axnb<T,5>(x,y,z)),\"       \")\n      define_sfop3(35,(axnb<T,6>(x,y,z)),\"       \")\n      define_sfop3(36,(axnb<T,7>(x,y,z)),\"       \")\n      define_sfop3(37,(axnb<T,8>(x,y,z)),\"       \")\n      define_sfop3(38,(axnb<T,9>(x,y,z)),\"       \")\n      define_sfop3(39,x * numeric::log(y)   + z,\"\")\n      define_sfop3(40,x * numeric::log(y)   - z,\"\")\n      define_sfop3(41,x * numeric::log10(y) + z,\"\")\n      define_sfop3(42,x * numeric::log10(y) - z,\"\")\n      define_sfop3(43,x * numeric::sin(y) + z  ,\"\")\n      define_sfop3(44,x * numeric::sin(y) - z  ,\"\")\n      define_sfop3(45,x * numeric::cos(y) + z  ,\"\")\n      define_sfop3(46,x * numeric::cos(y) - z  ,\"\")\n      define_sfop3(47,details::is_true(x) ? y : z,\"\")\n\n      #define define_sfop4(NN,OP0,OP1)                           \\\n      template <typename T>                                      \\\n      struct sf##NN##_op : public sf_base<T>                     \\\n      {                                                          \\\n         typedef typename sf_base<T>::Type Type;                 \\\n         static inline T process(Type x, Type y, Type z, Type w) \\\n         {                                                       \\\n            return (OP0);                                        \\\n         }                                                       \\\n         static inline std::string id() { return OP1; }          \\\n      };                                                         \\\n\n      define_sfop4(48,(x + ((y + z) / w)),\"t+((t+t)/t)\")\n      define_sfop4(49,(x + ((y + z) * w)),\"t+((t+t)*t)\")\n      define_sfop4(50,(x + ((y - z) / w)),\"t+((t-t)/t)\")\n      define_sfop4(51,(x + ((y - z) * w)),\"t+((t-t)*t)\")\n      define_sfop4(52,(x + ((y * z) / w)),\"t+((t*t)/t)\")\n      define_sfop4(53,(x + ((y * z) * w)),\"t+((t*t)*t)\")\n      define_sfop4(54,(x + ((y / z) + w)),\"t+((t/t)+t)\")\n      define_sfop4(55,(x + ((y / z) / w)),\"t+((t/t)/t)\")\n      define_sfop4(56,(x + ((y / z) * w)),\"t+((t/t)*t)\")\n      define_sfop4(57,(x - ((y + z) / w)),\"t-((t+t)/t)\")\n      define_sfop4(58,(x - ((y + z) * w)),\"t-((t+t)*t)\")\n      define_sfop4(59,(x - ((y - z) / w)),\"t-((t-t)/t)\")\n      define_sfop4(60,(x - ((y - z) * w)),\"t-((t-t)*t)\")\n      define_sfop4(61,(x - ((y * z) / w)),\"t-((t*t)/t)\")\n      define_sfop4(62,(x - ((y * z) * w)),\"t-((t*t)*t)\")\n      define_sfop4(63,(x - ((y / z) / w)),\"t-((t/t)/t)\")\n      define_sfop4(64,(x - ((y / z) * w)),\"t-((t/t)*t)\")\n      define_sfop4(65,(((x + y) * z) - w),\"((t+t)*t)-t\")\n      define_sfop4(66,(((x - y) * z) - w),\"((t-t)*t)-t\")\n      define_sfop4(67,(((x * y) * z) - w),\"((t*t)*t)-t\")\n      define_sfop4(68,(((x / y) * z) - w),\"((t/t)*t)-t\")\n      define_sfop4(69,(((x + y) / z) - w),\"((t+t)/t)-t\")\n      define_sfop4(70,(((x - y) / z) - w),\"((t-t)/t)-t\")\n      define_sfop4(71,(((x * y) / z) - w),\"((t*t)/t)-t\")\n      define_sfop4(72,(((x / y) / z) - w),\"((t/t)/t)-t\")\n      define_sfop4(73,((x * y) + (z * w)),\"(t*t)+(t*t)\")\n      define_sfop4(74,((x * y) - (z * w)),\"(t*t)-(t*t)\")\n      define_sfop4(75,((x * y) + (z / w)),\"(t*t)+(t/t)\")\n      define_sfop4(76,((x * y) - (z / w)),\"(t*t)-(t/t)\")\n      define_sfop4(77,((x / y) + (z / w)),\"(t/t)+(t/t)\")\n      define_sfop4(78,((x / y) - (z / w)),\"(t/t)-(t/t)\")\n      define_sfop4(79,((x / y) - (z * w)),\"(t/t)-(t*t)\")\n      define_sfop4(80,(x / (y + (z * w))),\"t/(t+(t*t))\")\n      define_sfop4(81,(x / (y - (z * w))),\"t/(t-(t*t))\")\n      define_sfop4(82,(x * (y + (z * w))),\"t*(t+(t*t))\")\n      define_sfop4(83,(x * (y - (z * w))),\"t*(t-(t*t))\")\n\n      define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),\"\")\n      define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),\"\")\n      define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),\"\")\n      define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),\"\")\n      define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),\"\")\n      define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),\"\")\n      define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),\"\")\n      define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),\"\")\n      define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),\"\")\n      define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),\"\")\n      define_sfop4(94,((x <  y) ? z : w),\"\")\n      define_sfop4(95,((x <= y) ? z : w),\"\")\n      define_sfop4(96,((x >  y) ? z : w),\"\")\n      define_sfop4(97,((x >= y) ? z : w),\"\")\n      define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),\"\")\n      define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),\"\")\n\n      define_sfop4(ext00,((x + y) - (z * w)),\"(t+t)-(t*t)\")\n      define_sfop4(ext01,((x + y) - (z / w)),\"(t+t)-(t/t)\")\n      define_sfop4(ext02,((x + y) + (z * w)),\"(t+t)+(t*t)\")\n      define_sfop4(ext03,((x + y) + (z / w)),\"(t+t)+(t/t)\")\n      define_sfop4(ext04,((x - y) + (z * w)),\"(t-t)+(t*t)\")\n      define_sfop4(ext05,((x - y) + (z / w)),\"(t-t)+(t/t)\")\n      define_sfop4(ext06,((x - y) - (z * w)),\"(t-t)-(t*t)\")\n      define_sfop4(ext07,((x - y) - (z / w)),\"(t-t)-(t/t)\")\n      define_sfop4(ext08,((x + y) - (z - w)),\"(t+t)-(t-t)\")\n      define_sfop4(ext09,((x + y) + (z - w)),\"(t+t)+(t-t)\")\n      define_sfop4(ext10,((x + y) + (z + w)),\"(t+t)+(t+t)\")\n      define_sfop4(ext11,((x + y) * (z - w)),\"(t+t)*(t-t)\")\n      define_sfop4(ext12,((x + y) / (z - w)),\"(t+t)/(t-t)\")\n      define_sfop4(ext13,((x - y) - (z + w)),\"(t-t)-(t+t)\")\n      define_sfop4(ext14,((x - y) + (z + w)),\"(t-t)+(t+t)\")\n      define_sfop4(ext15,((x - y) * (z + w)),\"(t-t)*(t+t)\")\n      define_sfop4(ext16,((x - y) / (z + w)),\"(t-t)/(t+t)\")\n      define_sfop4(ext17,((x * y) - (z + w)),\"(t*t)-(t+t)\")\n      define_sfop4(ext18,((x / y) - (z + w)),\"(t/t)-(t+t)\")\n      define_sfop4(ext19,((x * y) + (z + w)),\"(t*t)+(t+t)\")\n      define_sfop4(ext20,((x / y) + (z + w)),\"(t/t)+(t+t)\")\n      define_sfop4(ext21,((x * y) + (z - w)),\"(t*t)+(t-t)\")\n      define_sfop4(ext22,((x / y) + (z - w)),\"(t/t)+(t-t)\")\n      define_sfop4(ext23,((x * y) - (z - w)),\"(t*t)-(t-t)\")\n      define_sfop4(ext24,((x / y) - (z - w)),\"(t/t)-(t-t)\")\n      define_sfop4(ext25,((x + y) * (z * w)),\"(t+t)*(t*t)\")\n      define_sfop4(ext26,((x + y) * (z / w)),\"(t+t)*(t/t)\")\n      define_sfop4(ext27,((x + y) / (z * w)),\"(t+t)/(t*t)\")\n      define_sfop4(ext28,((x + y) / (z / w)),\"(t+t)/(t/t)\")\n      define_sfop4(ext29,((x - y) / (z * w)),\"(t-t)/(t*t)\")\n      define_sfop4(ext30,((x - y) / (z / w)),\"(t-t)/(t/t)\")\n      define_sfop4(ext31,((x - y) * (z * w)),\"(t-t)*(t*t)\")\n      define_sfop4(ext32,((x - y) * (z / w)),\"(t-t)*(t/t)\")\n      define_sfop4(ext33,((x * y) * (z + w)),\"(t*t)*(t+t)\")\n      define_sfop4(ext34,((x / y) * (z + w)),\"(t/t)*(t+t)\")\n      define_sfop4(ext35,((x * y) / (z + w)),\"(t*t)/(t+t)\")\n      define_sfop4(ext36,((x / y) / (z + w)),\"(t/t)/(t+t)\")\n      define_sfop4(ext37,((x * y) / (z - w)),\"(t*t)/(t-t)\")\n      define_sfop4(ext38,((x / y) / (z - w)),\"(t/t)/(t-t)\")\n      define_sfop4(ext39,((x * y) * (z - w)),\"(t*t)*(t-t)\")\n      define_sfop4(ext40,((x * y) / (z * w)),\"(t*t)/(t*t)\")\n      define_sfop4(ext41,((x / y) * (z / w)),\"(t/t)*(t/t)\")\n      define_sfop4(ext42,((x / y) * (z - w)),\"(t/t)*(t-t)\")\n      define_sfop4(ext43,((x * y) * (z * w)),\"(t*t)*(t*t)\")\n      define_sfop4(ext44,(x + (y * (z / w))),\"t+(t*(t/t))\")\n      define_sfop4(ext45,(x - (y * (z / w))),\"t-(t*(t/t))\")\n      define_sfop4(ext46,(x + (y / (z * w))),\"t+(t/(t*t))\")\n      define_sfop4(ext47,(x - (y / (z * w))),\"t-(t/(t*t))\")\n      define_sfop4(ext48,(((x - y) - z) * w),\"((t-t)-t)*t\")\n      define_sfop4(ext49,(((x - y) - z) / w),\"((t-t)-t)/t\")\n      define_sfop4(ext50,(((x - y) + z) * w),\"((t-t)+t)*t\")\n      define_sfop4(ext51,(((x - y) + z) / w),\"((t-t)+t)/t\")\n      define_sfop4(ext52,((x + (y - z)) * w),\"(t+(t-t))*t\")\n      define_sfop4(ext53,((x + (y - z)) / w),\"(t+(t-t))/t\")\n      define_sfop4(ext54,((x + y) / (z + w)),\"(t+t)/(t+t)\")\n      define_sfop4(ext55,((x - y) / (z - w)),\"(t-t)/(t-t)\")\n      define_sfop4(ext56,((x + y) * (z + w)),\"(t+t)*(t+t)\")\n      define_sfop4(ext57,((x - y) * (z - w)),\"(t-t)*(t-t)\")\n      define_sfop4(ext58,((x - y) + (z - w)),\"(t-t)+(t-t)\")\n      define_sfop4(ext59,((x - y) - (z - w)),\"(t-t)-(t-t)\")\n      define_sfop4(ext60,((x / y) + (z * w)),\"(t/t)+(t*t)\")\n      define_sfop4(ext61,(((x * y) * z) / w),\"((t*t)*t)/t\")\n\n      #undef define_sfop3\n      #undef define_sfop4\n\n      template <typename T, typename SpecialFunction>\n      class sf3_node : public trinary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         sf3_node(const operator_type& opr,\n                  expression_ptr branch0,\n                  expression_ptr branch1,\n                  expression_ptr branch2)\n         : trinary_node<T>(opr, branch0, branch1, branch2)\n         {}\n\n         inline T value() const\n         {\n            const T x = trinary_node<T>::branch_[0].first->value();\n            const T y = trinary_node<T>::branch_[1].first->value();\n            const T z = trinary_node<T>::branch_[2].first->value();\n\n            return SpecialFunction::process(x, y, z);\n         }\n      };\n\n      template <typename T, typename SpecialFunction>\n      class sf4_node : public quaternary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         sf4_node(const operator_type& opr,\n                  expression_ptr branch0,\n                  expression_ptr branch1,\n                  expression_ptr branch2,\n                  expression_ptr branch3)\n         : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)\n         {}\n\n         inline T value() const\n         {\n            const T x = quaternary_node<T>::branch_[0].first->value();\n            const T y = quaternary_node<T>::branch_[1].first->value();\n            const T z = quaternary_node<T>::branch_[2].first->value();\n            const T w = quaternary_node<T>::branch_[3].first->value();\n\n            return SpecialFunction::process(x, y, z, w);\n         }\n      };\n\n      template <typename T, typename SpecialFunction>\n      class sf3_var_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         sf3_var_node(const T& v0, const T& v1, const T& v2)\n         : v0_(v0),\n           v1_(v1),\n           v2_(v2)\n         {}\n\n         inline T value() const\n         {\n            return SpecialFunction::process(v0_, v1_, v2_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_trinary;\n         }\n\n      private:\n\n         sf3_var_node(sf3_var_node<T,SpecialFunction>&);\n         sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);\n\n         const T& v0_;\n         const T& v1_;\n         const T& v2_;\n      };\n\n      template <typename T, typename SpecialFunction>\n      class sf4_var_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)\n         : v0_(v0),\n           v1_(v1),\n           v2_(v2),\n           v3_(v3)\n         {}\n\n         inline T value() const\n         {\n            return SpecialFunction::process(v0_, v1_, v2_, v3_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_trinary;\n         }\n\n      private:\n\n         sf4_var_node(sf4_var_node<T,SpecialFunction>&);\n         sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);\n\n         const T& v0_;\n         const T& v1_;\n         const T& v2_;\n         const T& v3_;\n      };\n\n      template <typename T, typename VarArgFunction>\n      class vararg_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)\n         {\n            arg_list_     .resize(arg_list.size());\n            delete_branch_.resize(arg_list.size());\n\n            for (std::size_t i = 0; i < arg_list.size(); ++i)\n            {\n               if (arg_list[i])\n               {\n                       arg_list_[i] = arg_list[i];\n                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);\n               }\n               else\n               {\n                  arg_list_.clear();\n                  delete_branch_.clear();\n                  return;\n               }\n            }\n         }\n\n        ~vararg_node()\n         {\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               if (arg_list_[i] && delete_branch_[i])\n               {\n                  destroy_node(arg_list_[i]);\n               }\n            }\n         }\n\n         inline T value() const\n         {\n            if (!arg_list_.empty())\n               return VarArgFunction::process(arg_list_);\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vararg;\n         }\n\n      private:\n\n         std::vector<expression_ptr> arg_list_;\n         std::vector<unsigned char> delete_branch_;\n      };\n\n      template <typename T, typename VarArgFunction>\n      class vararg_varnode : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)\n         {\n            arg_list_.resize(arg_list.size());\n\n            for (std::size_t i = 0; i < arg_list.size(); ++i)\n            {\n               if (arg_list[i] && is_variable_node(arg_list[i]))\n               {\n                  variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);\n                  arg_list_[i] = (&var_node_ptr->ref());\n               }\n               else\n               {\n                  arg_list_.clear();\n                  return;\n               }\n            }\n         }\n\n         inline T value() const\n         {\n            if (!arg_list_.empty())\n               return VarArgFunction::process(arg_list_);\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vararg;\n         }\n\n      private:\n\n         std::vector<const T*> arg_list_;\n      };\n\n      template <typename T, typename VecFunction>\n      class vectorize_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         vectorize_node(const expression_ptr v)\n         : ivec_ptr_(0),\n           v_(v),\n           v_deletable_(branch_deletable(v_))\n         {\n            if (is_ivector_node(v))\n            {\n               ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);\n            }\n            else\n               ivec_ptr_ = 0;\n         }\n\n        ~vectorize_node()\n         {\n            if (v_ && v_deletable_)\n            {\n               destroy_node(v_);\n            }\n         }\n\n         inline T value() const\n         {\n            if (ivec_ptr_)\n            {\n               v_->value();\n               return VecFunction::process(ivec_ptr_);\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecfunc;\n         }\n\n      private:\n\n         vector_interface<T>* ivec_ptr_;\n         expression_ptr              v_;\n         const bool        v_deletable_;\n      };\n\n      template <typename T>\n      class assignment_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_node(const operator_type& opr,\n                         expression_ptr branch0,\n                         expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           var_node_ptr_(0)\n         {\n            if (is_variable_node(binary_node<T>::branch_[0].first))\n            {\n               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (var_node_ptr_)\n            {\n               T& result = var_node_ptr_->ref();\n\n               result = binary_node<T>::branch_[1].first->value();\n\n               return result;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         variable_node<T>* var_node_ptr_;\n      };\n\n      template <typename T>\n      class assignment_vec_elem_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_vec_elem_node(const operator_type& opr,\n                                  expression_ptr branch0,\n                                  expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec_node_ptr_(0)\n         {\n            if (is_vector_elem_node(binary_node<T>::branch_[0].first))\n            {\n               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (vec_node_ptr_)\n            {\n               T& result = vec_node_ptr_->ref();\n\n               result = binary_node<T>::branch_[1].first->value();\n\n               return result;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         vector_elem_node<T>* vec_node_ptr_;\n      };\n\n      template <typename T>\n      class assignment_rebasevec_elem_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_rebasevec_elem_node(const operator_type& opr,\n                                        expression_ptr branch0,\n                                        expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           rbvec_node_ptr_(0)\n         {\n            if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))\n            {\n               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (rbvec_node_ptr_)\n            {\n               T& result = rbvec_node_ptr_->ref();\n\n               result = binary_node<T>::branch_[1].first->value();\n\n               return result;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         rebasevector_elem_node<T>* rbvec_node_ptr_;\n      };\n\n      template <typename T>\n      class assignment_rebasevec_celem_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_rebasevec_celem_node(const operator_type& opr,\n                                         expression_ptr branch0,\n                                         expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           rbvec_node_ptr_(0)\n         {\n            if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))\n            {\n               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (rbvec_node_ptr_)\n            {\n               T& result = rbvec_node_ptr_->ref();\n\n               result = binary_node<T>::branch_[1].first->value();\n\n               return result;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         rebasevector_celem_node<T>* rbvec_node_ptr_;\n      };\n\n      template <typename T>\n      class assignment_vec_node : public binary_node     <T>,\n                                  public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef vector_node<T>*    vector_node_ptr;\n         typedef vec_data_store<T>            vds_t;\n\n         assignment_vec_node(const operator_type& opr,\n                             expression_ptr branch0,\n                             expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec_node_ptr_(0)\n         {\n            if (is_vector_node(binary_node<T>::branch_[0].first))\n            {\n               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);\n               vds()         = vec_node_ptr_->vds();\n            }\n         }\n\n         inline T value() const\n         {\n            if (vec_node_ptr_)\n            {\n               const T v = binary_node<T>::branch_[1].first->value();\n\n               T* vec = vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec + lud.upper_bound;\n\n               while (vec < upper_bound)\n               {\n                 #define exprtk_loop(N) \\\n                  vec[N] = v;           \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec += lud.batch_size;\n               }\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N) \\\n                  case N : *vec++ = v; \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return vec_node_ptr_->value();\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return vec_node_ptr_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return vec_node_ptr_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecvalass;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node<T>* vec_node_ptr_;\n         vds_t           vds_;\n      };\n\n      template <typename T>\n      class assignment_vecvec_node : public binary_node     <T>,\n                                     public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*  expression_ptr;\n         typedef vector_node<T>*     vector_node_ptr;\n         typedef vec_data_store<T>             vds_t;\n\n         assignment_vecvec_node(const operator_type& opr,\n                                expression_ptr branch0,\n                                expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec0_node_ptr_(0),\n           vec1_node_ptr_(0),\n           initialised_(false),\n           src_is_ivec_(false)\n         {\n            if (is_vector_node(binary_node<T>::branch_[0].first))\n            {\n               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);\n               vds()          = vec0_node_ptr_->vds();\n            }\n\n            if (is_vector_node(binary_node<T>::branch_[1].first))\n            {\n               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);\n               vds_t::match_sizes(vds(),vec1_node_ptr_->vds());\n            }\n            else if (is_ivector_node(binary_node<T>::branch_[1].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))\n               {\n                  vec1_node_ptr_ = vi->vec();\n\n                  if (!vi->side_effect())\n                  {\n                     vi->vds()    = vds();\n                     src_is_ivec_ = true;\n                  }\n                  else\n                     vds_t::match_sizes(vds(),vi->vds());\n               }\n            }\n\n            initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[1].first->value();\n\n               if (src_is_ivec_)\n                  return vec0_node_ptr_->value();\n\n               T* vec0 = vec0_node_ptr_->vds().data();\n               T* vec1 = vec1_node_ptr_->vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec0 + lud.upper_bound;\n\n               while (vec0 < upper_bound)\n               {\n                  #define exprtk_loop(N) \\\n                  vec0[N] = vec1[N];     \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec0 += lud.batch_size;\n                  vec1 += lud.batch_size;\n               }\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)        \\\n                  case N : *vec0++ = *vec1++; \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return vec0_node_ptr_->value();\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return vec0_node_ptr_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return vec0_node_ptr_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecvecass;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node<T>* vec0_node_ptr_;\n         vector_node<T>* vec1_node_ptr_;\n         bool            initialised_;\n         bool            src_is_ivec_;\n         vds_t           vds_;\n      };\n\n      template <typename T, typename Operation>\n      class assignment_op_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_op_node(const operator_type& opr,\n                            expression_ptr branch0,\n                            expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           var_node_ptr_(0)\n         {\n            if (is_variable_node(binary_node<T>::branch_[0].first))\n            {\n               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (var_node_ptr_)\n            {\n               T& v = var_node_ptr_->ref();\n               v = Operation::process(v,binary_node<T>::branch_[1].first->value());\n\n               return v;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         variable_node<T>* var_node_ptr_;\n      };\n\n      template <typename T, typename Operation>\n      class assignment_vec_elem_op_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_vec_elem_op_node(const operator_type& opr,\n                                     expression_ptr branch0,\n                                     expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec_node_ptr_(0)\n         {\n            if (is_vector_elem_node(binary_node<T>::branch_[0].first))\n            {\n               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (vec_node_ptr_)\n            {\n               T& v = vec_node_ptr_->ref();\n                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());\n\n               return v;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         vector_elem_node<T>* vec_node_ptr_;\n      };\n\n      template <typename T, typename Operation>\n      class assignment_rebasevec_elem_op_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_rebasevec_elem_op_node(const operator_type& opr,\n                                           expression_ptr branch0,\n                                           expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           rbvec_node_ptr_(0)\n         {\n            if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first))\n            {\n               rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (rbvec_node_ptr_)\n            {\n               T& v = rbvec_node_ptr_->ref();\n                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());\n\n               return v;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         rebasevector_elem_node<T>* rbvec_node_ptr_;\n      };\n\n      template <typename T, typename Operation>\n      class assignment_rebasevec_celem_op_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         assignment_rebasevec_celem_op_node(const operator_type& opr,\n                                            expression_ptr branch0,\n                                            expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           rbvec_node_ptr_(0)\n         {\n            if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first))\n            {\n               rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first);\n            }\n         }\n\n         inline T value() const\n         {\n            if (rbvec_node_ptr_)\n            {\n               T& v = rbvec_node_ptr_->ref();\n                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());\n\n               return v;\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n      private:\n\n         rebasevector_celem_node<T>* rbvec_node_ptr_;\n      };\n\n      template <typename T, typename Operation>\n      class assignment_vec_op_node : public binary_node     <T>,\n                                     public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*  expression_ptr;\n         typedef vector_node<T>*     vector_node_ptr;\n         typedef vec_data_store<T>             vds_t;\n\n         assignment_vec_op_node(const operator_type& opr,\n                                expression_ptr branch0,\n                                expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec_node_ptr_(0)\n         {\n            if (is_vector_node(binary_node<T>::branch_[0].first))\n            {\n               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);\n               vds()         = vec_node_ptr_->vds();\n            }\n         }\n\n         inline T value() const\n         {\n            if (vec_node_ptr_)\n            {\n               const T v = binary_node<T>::branch_[1].first->value();\n\n               T* vec = vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec + lud.upper_bound;\n\n               while (vec < upper_bound)\n               {\n                  #define exprtk_loop(N)       \\\n                  Operation::assign(vec[N],v); \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec += lud.batch_size;\n               }\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)                  \\\n                  case N : Operation::assign(*vec++,v); \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return vec_node_ptr_->value();\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return vec_node_ptr_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return vec_node_ptr_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecopvalass;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n         bool side_effect() const\n         {\n            return true;\n         }\n\n      private:\n\n         vector_node<T>* vec_node_ptr_;\n         vds_t           vds_;\n      };\n\n      template <typename T, typename Operation>\n      class assignment_vecvec_op_node : public binary_node     <T>,\n                                        public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*  expression_ptr;\n         typedef vector_node<T>*     vector_node_ptr;\n         typedef vec_data_store<T>             vds_t;\n\n         assignment_vecvec_op_node(const operator_type& opr,\n                                   expression_ptr branch0,\n                                   expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec0_node_ptr_(0),\n           vec1_node_ptr_(0),\n           initialised_(false)\n         {\n            if (is_vector_node(binary_node<T>::branch_[0].first))\n            {\n               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);\n               vds()          = vec0_node_ptr_->vds();\n            }\n\n            if (is_vector_node(binary_node<T>::branch_[1].first))\n            {\n               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);\n               vec1_node_ptr_->vds() = vds();\n            }\n            else if (is_ivector_node(binary_node<T>::branch_[1].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))\n               {\n                  vec1_node_ptr_ = vi->vec();\n                  vec1_node_ptr_->vds() = vds();\n               }\n               else\n                  vds_t::match_sizes(vds(),vec1_node_ptr_->vds());\n            }\n\n            initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               T* vec0 = vec0_node_ptr_->vds().data();\n               T* vec1 = vec1_node_ptr_->vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec0 + lud.upper_bound;\n\n               while (vec0 < upper_bound)\n               {\n                  #define exprtk_loop(N)                         \\\n                  vec0[N] = Operation::process(vec0[N],vec1[N]); \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec0 += lud.batch_size;\n                  vec1 += lud.batch_size;\n               }\n\n               int i = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)                                             \\\n                  case N : { vec0[i] = Operation::process(vec0[i],vec1[i]); ++i; } \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return vec0_node_ptr_->value();\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return vec0_node_ptr_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return vec0_node_ptr_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecopvecass;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n         bool side_effect() const\n         {\n            return true;\n         }\n\n      private:\n\n         vector_node<T>* vec0_node_ptr_;\n         vector_node<T>* vec1_node_ptr_;\n         bool            initialised_;\n         vds_t           vds_;\n      };\n\n      template <typename T, typename Operation>\n      class vec_binop_vecvec_node : public binary_node     <T>,\n                                    public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*    expression_ptr;\n         typedef vector_node<T>*       vector_node_ptr;\n         typedef vector_holder<T>*   vector_holder_ptr;\n         typedef vec_data_store<T>               vds_t;\n\n         vec_binop_vecvec_node(const operator_type& opr,\n                               expression_ptr branch0,\n                               expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec0_node_ptr_(0),\n           vec1_node_ptr_(0),\n           temp_         (0),\n           temp_vec_node_(0),\n           initialised_(false)\n         {\n            bool v0_is_ivec = false;\n            bool v1_is_ivec = false;\n\n            if (is_vector_node(binary_node<T>::branch_[0].first))\n            {\n               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);\n            }\n            else if (is_ivector_node(binary_node<T>::branch_[0].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))\n               {\n                  vec0_node_ptr_ = vi->vec();\n                  v0_is_ivec     = true;\n               }\n            }\n\n            if (is_vector_node(binary_node<T>::branch_[1].first))\n            {\n               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);\n            }\n            else if (is_ivector_node(binary_node<T>::branch_[1].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))\n               {\n                  vec1_node_ptr_ = vi->vec();\n                  v1_is_ivec     = true;\n               }\n            }\n\n            if (vec0_node_ptr_ && vec1_node_ptr_)\n            {\n               vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder();\n               vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder();\n\n               if (v0_is_ivec && (vec0.size() <= vec1.size()))\n                  vds_ = vds_t(vec0_node_ptr_->vds());\n               else if (v1_is_ivec && (vec1.size() <= vec0.size()))\n                  vds_ = vds_t(vec1_node_ptr_->vds());\n               else\n                  vds_ = vds_t(std::min(vec0.size(),vec1.size()));\n\n               temp_          = new vector_holder<T>(vds().data(),vds().size());\n               temp_vec_node_ = new vector_node<T>  (vds(),temp_);\n\n               initialised_ = true;\n            }\n         }\n\n        ~vec_binop_vecvec_node()\n         {\n            delete temp_;\n            delete temp_vec_node_;\n         }\n\n         inline T value() const\n         {\n            if (initialised_)\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               T* vec0 = vec0_node_ptr_->vds().data();\n               T* vec1 = vec1_node_ptr_->vds().data();\n               T* vec2 = vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec2 + lud.upper_bound;\n\n               while (vec2 < upper_bound)\n               {\n                  #define exprtk_loop(N)                         \\\n                  vec2[N] = Operation::process(vec0[N],vec1[N]); \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec0 += lud.batch_size;\n                  vec1 += lud.batch_size;\n                  vec2 += lud.batch_size;\n               }\n\n               int i = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)                                             \\\n                  case N : { vec2[i] = Operation::process(vec0[i],vec1[i]); ++i; } \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return (vds().data())[0];\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return temp_vec_node_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return temp_vec_node_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecvecarith;\n         }\n\n         std::size_t size() const\n         {\n            return vds_.size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node_ptr   vec0_node_ptr_;\n         vector_node_ptr   vec1_node_ptr_;\n         vector_holder_ptr temp_;\n         vector_node_ptr   temp_vec_node_;\n         bool              initialised_;\n         vds_t             vds_;\n      };\n\n      template <typename T, typename Operation>\n      class vec_binop_vecval_node : public binary_node     <T>,\n                                    public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*    expression_ptr;\n         typedef vector_node<T>*       vector_node_ptr;\n         typedef vector_holder<T>*   vector_holder_ptr;\n         typedef vec_data_store<T>               vds_t;\n\n         vec_binop_vecval_node(const operator_type& opr,\n                               expression_ptr branch0,\n                               expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec0_node_ptr_(0),\n           temp_         (0),\n           temp_vec_node_(0)\n         {\n            bool v0_is_ivec = false;\n\n            if (is_vector_node(binary_node<T>::branch_[0].first))\n            {\n               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);\n            }\n            else if (is_ivector_node(binary_node<T>::branch_[0].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))\n               {\n                  vec0_node_ptr_ = vi->vec();\n                  v0_is_ivec     = true;\n               }\n            }\n\n            if (vec0_node_ptr_)\n            {\n               if (v0_is_ivec)\n                  vds() = vec0_node_ptr_->vds();\n               else\n                  vds() = vds_t(vec0_node_ptr_->size());\n\n               temp_          = new vector_holder<T>(vds());\n               temp_vec_node_ = new vector_node<T>  (vds(),temp_);\n            }\n         }\n\n        ~vec_binop_vecval_node()\n         {\n            delete temp_;\n            delete temp_vec_node_;\n         }\n\n         inline T value() const\n         {\n            if (vec0_node_ptr_)\n            {\n                           binary_node<T>::branch_[0].first->value();\n               const T v = binary_node<T>::branch_[1].first->value();\n\n               T* vec0 = vec0_node_ptr_->vds().data();\n               T* vec1 = vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec0 + lud.upper_bound;\n\n               while (vec0 < upper_bound)\n               {\n                  #define exprtk_loop(N)                   \\\n                  vec1[N] = Operation::process(vec0[N],v); \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec0 += lud.batch_size;\n                  vec1 += lud.batch_size;\n               }\n\n               int i = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)                                       \\\n                  case N : { vec1[i] = Operation::process(vec0[i],v); ++i; } \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return (vds().data())[0];\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return temp_vec_node_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return temp_vec_node_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecvalarith;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node_ptr   vec0_node_ptr_;\n         vector_holder_ptr temp_;\n         vector_node_ptr   temp_vec_node_;\n         vds_t             vds_;\n      };\n\n      template <typename T, typename Operation>\n      class vec_binop_valvec_node : public binary_node     <T>,\n                                    public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*    expression_ptr;\n         typedef vector_node<T>*       vector_node_ptr;\n         typedef vector_holder<T>*   vector_holder_ptr;\n         typedef vec_data_store<T>               vds_t;\n\n         vec_binop_valvec_node(const operator_type& opr,\n                               expression_ptr branch0,\n                               expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           vec1_node_ptr_(0),\n           temp_         (0),\n           temp_vec_node_(0)\n         {\n            bool v1_is_ivec = false;\n\n            if (is_vector_node(binary_node<T>::branch_[1].first))\n            {\n               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);\n            }\n            else if (is_ivector_node(binary_node<T>::branch_[1].first))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))\n               {\n                  vec1_node_ptr_ = vi->vec();\n                  v1_is_ivec     = true;\n               }\n            }\n\n            if (vec1_node_ptr_)\n            {\n               if (v1_is_ivec)\n                  vds() = vec1_node_ptr_->vds();\n               else\n                  vds() = vds_t(vec1_node_ptr_->size());\n\n               temp_          = new vector_holder<T>(vds());\n               temp_vec_node_ = new vector_node<T>  (vds(),temp_);\n            }\n         }\n\n        ~vec_binop_valvec_node()\n         {\n            delete temp_;\n            delete temp_vec_node_;\n         }\n\n         inline T value() const\n         {\n            if (vec1_node_ptr_)\n            {\n               const T v = binary_node<T>::branch_[0].first->value();\n                           binary_node<T>::branch_[1].first->value();\n\n               T* vec0 = vds().data();\n               T* vec1 = vec1_node_ptr_->vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec0 + lud.upper_bound;\n\n               while (vec0 < upper_bound)\n               {\n                  #define exprtk_loop(N)                   \\\n                  vec0[N] = Operation::process(v,vec1[N]); \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec0 += lud.batch_size;\n                  vec1 += lud.batch_size;\n               }\n\n               int i = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)                                       \\\n                  case N : { vec0[i] = Operation::process(v,vec1[i]); ++i; } \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return (vds().data())[0];\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return temp_vec_node_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return temp_vec_node_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecvalarith;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node_ptr   vec1_node_ptr_;\n         vector_holder_ptr temp_;\n         vector_node_ptr   temp_vec_node_;\n         vds_t             vds_;\n      };\n\n      template <typename T, typename Operation>\n      class unary_vector_node : public unary_node      <T>,\n                                public vector_interface<T>\n      {\n      public:\n\n         typedef expression_node<T>*    expression_ptr;\n         typedef vector_node<T>*       vector_node_ptr;\n         typedef vector_holder<T>*   vector_holder_ptr;\n         typedef vec_data_store<T>               vds_t;\n\n         unary_vector_node(const operator_type& opr, expression_ptr branch0)\n         : unary_node<T>(opr, branch0),\n           vec0_node_ptr_(0),\n           temp_         (0),\n           temp_vec_node_(0)\n         {\n            bool vec0_is_ivec = false;\n\n            if (is_vector_node(unary_node<T>::branch_))\n            {\n               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);\n            }\n            else if (is_ivector_node(unary_node<T>::branch_))\n            {\n               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n               if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))\n               {\n                  vec0_node_ptr_ = vi->vec();\n                  vec0_is_ivec   = true;\n               }\n            }\n\n            if (vec0_node_ptr_)\n            {\n               if (vec0_is_ivec)\n                  vds_ = vec0_node_ptr_->vds();\n               else\n                  vds_ = vds_t(vec0_node_ptr_->size());\n\n               temp_          = new vector_holder<T>(vds());\n               temp_vec_node_ = new vector_node<T>  (vds(),temp_);\n            }\n         }\n\n        ~unary_vector_node()\n         {\n            delete temp_;\n            delete temp_vec_node_;\n         }\n\n         inline T value() const\n         {\n            unary_node<T>::branch_->value();\n\n            if (vec0_node_ptr_)\n            {\n               T* vec0 = vec0_node_ptr_->vds().data();\n               T* vec1 = vds().data();\n\n               loop_unroll::details lud(size());\n               const T* upper_bound = vec0 + lud.upper_bound;\n\n               while (vec0 < upper_bound)\n               {\n                  #define exprtk_loop(N)                 \\\n                  vec1[N] = Operation::process(vec0[N]); \\\n\n                  exprtk_loop( 0) exprtk_loop( 1)\n                  exprtk_loop( 2) exprtk_loop( 3)\n                  #ifndef exprtk_disable_superscalar_unroll\n                  exprtk_loop( 4) exprtk_loop( 5)\n                  exprtk_loop( 6) exprtk_loop( 7)\n                  exprtk_loop( 8) exprtk_loop( 9)\n                  exprtk_loop(10) exprtk_loop(11)\n                  exprtk_loop(12) exprtk_loop(13)\n                  exprtk_loop(14) exprtk_loop(15)\n                  #endif\n\n                  vec0 += lud.batch_size;\n                  vec1 += lud.batch_size;\n               }\n\n               int i = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (lud.remainder)\n               {\n                  #define case_stmt(N)                                     \\\n                  case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(15) case_stmt(14)\n                  case_stmt(13) case_stmt(12)\n                  case_stmt(11) case_stmt(10)\n                  case_stmt( 9) case_stmt( 8)\n                  case_stmt( 7) case_stmt( 6)\n                  case_stmt( 5) case_stmt( 4)\n                  #endif\n                  case_stmt( 3) case_stmt( 2)\n                  case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef exprtk_loop\n               #undef case_stmt\n\n               return (vds().data())[0];\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         vector_node_ptr vec() const\n         {\n            return temp_vec_node_;\n         }\n\n         vector_node_ptr vec()\n         {\n            return temp_vec_node_;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vecunaryop;\n         }\n\n         std::size_t size() const\n         {\n            return vds().size();\n         }\n\n         vds_t& vds()\n         {\n            return vds_;\n         }\n\n         const vds_t& vds() const\n         {\n            return vds_;\n         }\n\n      private:\n\n         vector_node_ptr   vec0_node_ptr_;\n         vector_holder_ptr temp_;\n         vector_node_ptr   temp_vec_node_;\n         vds_t             vds_;\n      };\n\n      template <typename T>\n      class scand_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         scand_node(const operator_type& opr,\n                    expression_ptr branch0,\n                    expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1)\n         {}\n\n         inline T value() const\n         {\n            return (\n                     std::not_equal_to<T>()\n                        (T(0),binary_node<T>::branch_[0].first->value()) &&\n                     std::not_equal_to<T>()\n                        (T(0),binary_node<T>::branch_[1].first->value())\n                   ) ? T(1) : T(0);\n         }\n      };\n\n      template <typename T>\n      class scor_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         scor_node(const operator_type& opr,\n                   expression_ptr branch0,\n                   expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1)\n         {}\n\n         inline T value() const\n         {\n            return (\n                     std::not_equal_to<T>()\n                        (T(0),binary_node<T>::branch_[0].first->value()) ||\n                     std::not_equal_to<T>()\n                        (T(0),binary_node<T>::branch_[1].first->value())\n                   ) ? T(1) : T(0);\n         }\n      };\n\n      template <typename T, typename IFunction, std::size_t N>\n      class function_N_node : public expression_node<T>\n      {\n      public:\n\n         // Function of N paramters.\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n         typedef IFunction ifunction;\n\n         function_N_node(ifunction* func)\n         : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),\n           parameter_count_(func->param_count)\n         {}\n\n        ~function_N_node()\n         {\n            cleanup_branches::execute<T,N>(branch_);\n         }\n\n         template <std::size_t NumBranches>\n         bool init_branches(expression_ptr (&b)[NumBranches])\n         {\n            // Needed for incompetent and broken msvc compiler versions\n            #ifdef _MSC_VER\n             #pragma warning(push)\n             #pragma warning(disable: 4127)\n            #endif\n            if (N != NumBranches)\n               return false;\n            else\n            {\n               for (std::size_t i = 0; i < NumBranches; ++i)\n               {\n                  if (b[i])\n                     branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));\n                  else\n                     return false;\n               }\n               return true;\n            }\n            #ifdef _MSC_VER\n             #pragma warning(pop)\n            #endif\n         }\n\n         inline bool operator <(const function_N_node<T,IFunction,N>& fn) const\n         {\n            return this < (&fn);\n         }\n\n         inline T value() const\n         {\n            // Needed for incompetent and broken msvc compiler versions\n            #ifdef _MSC_VER\n             #pragma warning(push)\n             #pragma warning(disable: 4127)\n            #endif\n            if ((0 == function_) || (0 == N))\n               return std::numeric_limits<T>::quiet_NaN();\n            else\n            {\n               T v[N];\n               evaluate_branches<T,N>::execute(v,branch_);\n               return invoke<T,N>::execute(*function_,v);\n            }\n            #ifdef _MSC_VER\n             #pragma warning(pop)\n            #endif\n         }\n\n         template <typename T_, std::size_t BranchCount>\n         struct evaluate_branches\n         {\n            static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])\n            {\n               for (std::size_t i = 0; i < BranchCount; ++i)\n               {\n                  v[i] = b[i].first->value();\n               }\n            }\n         };\n\n         template <typename T_>\n         struct evaluate_branches <T_,5>\n         {\n            static inline void execute(T_ (&v)[5], const branch_t (&b)[5])\n            {\n               v[0] = b[0].first->value();\n               v[1] = b[1].first->value();\n               v[2] = b[2].first->value();\n               v[3] = b[3].first->value();\n               v[4] = b[4].first->value();\n            }\n         };\n\n         template <typename T_>\n         struct evaluate_branches <T_,4>\n         {\n            static inline void execute(T_ (&v)[4], const branch_t (&b)[4])\n            {\n               v[0] = b[0].first->value();\n               v[1] = b[1].first->value();\n               v[2] = b[2].first->value();\n               v[3] = b[3].first->value();\n            }\n         };\n\n         template <typename T_>\n         struct evaluate_branches <T_,3>\n         {\n            static inline void execute(T_ (&v)[3], const branch_t (&b)[3])\n            {\n               v[0] = b[0].first->value();\n               v[1] = b[1].first->value();\n               v[2] = b[2].first->value();\n            }\n         };\n\n         template <typename T_>\n         struct evaluate_branches <T_,2>\n         {\n            static inline void execute(T_ (&v)[2], const branch_t (&b)[2])\n            {\n               v[0] = b[0].first->value();\n               v[1] = b[1].first->value();\n            }\n         };\n\n         template <typename T_>\n         struct evaluate_branches <T_,1>\n         {\n            static inline void execute(T_ (&v)[1], const branch_t (&b)[1])\n            {\n               v[0] = b[0].first->value();\n            }\n         };\n\n         template <typename T_, std::size_t ParamCount>\n         struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };\n\n         template <typename T_>\n         struct invoke<T_,20>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[20])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,19>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[19])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,18>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[18])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,17>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[17])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,16>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[16])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,15>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[15])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,14>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[14])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,13>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[13])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,12>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[12])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,11>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[11])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,10>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[10])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,9>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[9])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,8>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[8])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,7>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[7])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,6>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[6])\n            { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,5>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[5])\n            { return f(v[0],v[1],v[2],v[3],v[4]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,4>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[4])\n            { return f(v[0],v[1],v[2],v[3]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,3>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[3])\n            { return f(v[0],v[1],v[2]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,2>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[2])\n            { return f(v[0],v[1]); }\n         };\n\n         template <typename T_>\n         struct invoke<T_,1>\n         {\n            static inline T_ execute(ifunction& f, T_ (&v)[1])\n            { return f(v[0]); }\n         };\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_function;\n         }\n\n      private:\n\n         ifunction*  function_;\n         std::size_t parameter_count_;\n         branch_t    branch_[N];\n      };\n\n      template <typename T, typename IFunction>\n      class function_N_node<T,IFunction,0> : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef IFunction ifunction;\n\n         function_N_node(ifunction* func)\n         : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))\n         {}\n\n         inline bool operator <(const function_N_node<T,IFunction,0>& fn) const\n         {\n            return this < (&fn);\n         }\n\n         inline T value() const\n         {\n            if (function_)\n               return (*function_)();\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_function;\n         }\n\n      private:\n\n         ifunction* function_;\n      };\n\n      template <typename T, typename VarArgFunction>\n      class vararg_function_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n\n         vararg_function_node(VarArgFunction*  func,\n                              const std::vector<expression_ptr>& arg_list)\n         : function_(func),\n           arg_list_(arg_list)\n         {\n            value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());\n         }\n\n        ~vararg_function_node()\n         {\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))\n               {\n                  destroy_node(arg_list_[i]);\n               }\n            }\n         }\n\n         inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const\n         {\n            return this < (&fn);\n         }\n\n         inline T value() const\n         {\n            if (function_)\n            {\n               populate_value_list();\n               return (*function_)(value_list_);\n            }\n            else\n               return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_vafunction;\n         }\n\n      private:\n\n         inline void populate_value_list() const\n         {\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               value_list_[i] = arg_list_[i]->value();\n            }\n         }\n\n         VarArgFunction* function_;\n         std::vector<expression_ptr> arg_list_;\n         mutable std::vector<T> value_list_;\n      };\n\n      template <typename T, typename GenericFunction>\n      class generic_function_node : public expression_node<T>\n      {\n      public:\n\n         typedef type_store<T>                         type_store_t;\n         typedef expression_node<T>*                 expression_ptr;\n         typedef variable_node<T>                   variable_node_t;\n         typedef vector_node<T>                       vector_node_t;\n         typedef variable_node_t*               variable_node_ptr_t;\n         typedef vector_node_t*                   vector_node_ptr_t;\n         typedef range_interface<T>               range_interface_t;\n         typedef range_data_type<T>               range_data_type_t;\n         typedef range_pack<T>                              range_t;\n         typedef std::pair<expression_ptr,bool>            branch_t;\n         typedef std::pair<void*,std::size_t>                void_t;\n         typedef std::vector<T>                            tmp_vs_t;\n         typedef std::vector<type_store_t>         typestore_list_t;\n         typedef std::vector<range_data_type_t>        range_list_t;\n\n         generic_function_node(const std::vector<expression_ptr>& arg_list,\n                               GenericFunction* func = (GenericFunction*)(0))\n         : function_(func),\n           arg_list_(arg_list)\n         {}\n\n         virtual ~generic_function_node()\n         {\n            cleanup_branches::execute(branch_);\n         }\n\n         virtual bool init_branches()\n         {\n            expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );\n            typestore_list_    .resize(arg_list_.size(),type_store_t()     );\n            range_list_        .resize(arg_list_.size(),range_data_type_t());\n            branch_            .resize(arg_list_.size(),branch_t((expression_ptr)0,false));\n\n            for (std::size_t i = 0; i < arg_list_.size(); ++i)\n            {\n               type_store_t& ts = typestore_list_[i];\n\n               if (0 == arg_list_[i])\n                  return false;\n               else if (is_ivector_node(arg_list_[i]))\n               {\n                  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);\n\n                  if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))\n                     return false;\n\n                  ts.size = vi->size();\n                  ts.data = vi->vds().data();\n                  ts.type = type_store_t::e_vector;\n               }\n               #ifndef exprtk_disable_string_capabilities\n               else if (is_generally_string_node(arg_list_[i]))\n               {\n                  string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);\n\n                  if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))\n                     return false;\n\n                  ts.size = sbn->size();\n                  ts.data = reinterpret_cast<void*>(const_cast<char_t*>(sbn->base()));\n                  ts.type = type_store_t::e_string;\n\n                  range_list_[i].data      = ts.data;\n                  range_list_[i].size      = ts.size;\n                  range_list_[i].type_size = sizeof(char);\n                  range_list_[i].str_node  = sbn;\n\n                  range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);\n\n                  if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))\n                     return false;\n\n                  range_t& rp = ri->range_ref();\n\n                  if (\n                       rp.const_range() &&\n                       is_const_string_range_node(arg_list_[i])\n                     )\n                  {\n                     ts.size = rp.const_size();\n                     ts.data = static_cast<char_t*>(ts.data) + rp.n0_c.second;\n                     range_list_[i].range = reinterpret_cast<range_t*>(0);\n                  }\n                  else\n                     range_list_[i].range = &(ri->range_ref());\n               }\n               #endif\n               else if (is_variable_node(arg_list_[i]))\n               {\n                  variable_node_ptr_t var = variable_node_ptr_t(0);\n\n                  if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))\n                     return false;\n\n                  ts.size = 1;\n                  ts.data = &var->ref();\n                  ts.type = type_store_t::e_scalar;\n               }\n               else\n               {\n                  ts.size = 1;\n                  ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);\n                  ts.type = type_store_t::e_scalar;\n               }\n\n               branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));\n            }\n\n            return true;\n         }\n\n         inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const\n         {\n            return this < (&fn);\n         }\n\n         inline T value() const\n         {\n            if (function_)\n            {\n               if (populate_value_list())\n               {\n                  typedef typename GenericFunction::parameter_list_t parameter_list_t;\n\n                  return (*function_)(parameter_list_t(typestore_list_));\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_genfunction;\n         }\n\n      protected:\n\n         inline virtual bool populate_value_list() const\n         {\n            for (std::size_t i = 0; i < branch_.size(); ++i)\n            {\n               expr_as_vec1_store_[i] = branch_[i].first->value();\n            }\n\n            for (std::size_t i = 0; i < branch_.size(); ++i)\n            {\n               range_data_type_t& rdt = range_list_[i];\n\n               if (rdt.range)\n               {\n                  range_t&    rp = (*rdt.range);\n                  std::size_t r0 = 0;\n                  std::size_t r1 = 0;\n\n                  if (rp(r0,r1,rdt.size))\n                  {\n                     type_store_t& ts = typestore_list_[i];\n\n                     ts.size = rp.cache_size();\n                     #ifndef exprtk_disable_string_capabilities\n                     if (ts.type == type_store_t::e_string)\n                        ts.data = const_cast<char_t*>(rdt.str_node->base()) + rp.cache.first;\n                     else\n                     #endif\n                        ts.data = static_cast<char_t*>(rdt.data) + (rp.cache.first * rdt.type_size);\n                  }\n                  else\n                     return false;\n               }\n            }\n\n            return true;\n         }\n\n         GenericFunction* function_;\n         mutable typestore_list_t typestore_list_;\n\n      private:\n\n         std::vector<expression_ptr> arg_list_;\n         std::vector<branch_t>         branch_;\n         mutable tmp_vs_t  expr_as_vec1_store_;\n         mutable range_list_t      range_list_;\n      };\n\n      #ifndef exprtk_disable_string_capabilities\n      template <typename T, typename StringFunction>\n      class string_function_node : public generic_function_node<T,StringFunction>,\n                                   public string_base_node<T>,\n                                   public range_interface <T>\n      {\n      public:\n\n         typedef generic_function_node<T,StringFunction> gen_function_t;\n         typedef range_pack<T> range_t;\n\n         string_function_node(StringFunction* func,\n                              const std::vector<typename gen_function_t::expression_ptr>& arg_list)\n         : gen_function_t(arg_list,func)\n         {\n            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);\n            range_.cache.first  = range_.n0_c.second;\n            range_.cache.second = range_.n1_c.second;\n         }\n\n         inline bool operator <(const string_function_node<T,StringFunction>& fn) const\n         {\n            return this < (&fn);\n         }\n\n         inline T value() const\n         {\n            T result = std::numeric_limits<T>::quiet_NaN();\n\n            if (gen_function_t::function_)\n            {\n               if (gen_function_t::populate_value_list())\n               {\n                  typedef typename StringFunction::parameter_list_t parameter_list_t;\n\n                  result = (*gen_function_t::function_)(ret_string_,\n                                                        parameter_list_t(gen_function_t::typestore_list_));\n\n                  range_.n1_c.second  = ret_string_.size() - 1;\n                  range_.cache.second = range_.n1_c.second;\n\n                  return result;\n               }\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strfunction;\n         }\n\n         std::string str() const\n         {\n            return ret_string_;\n         }\n\n         const char_t* base() const\n         {\n           return &ret_string_[0];\n         }\n\n         std::size_t size() const\n         {\n            return ret_string_.size();\n         }\n\n         range_t& range_ref()\n         {\n            return range_;\n         }\n\n         const range_t& range_ref() const\n         {\n            return range_;\n         }\n\n      protected:\n\n         mutable range_t     range_;\n         mutable std::string ret_string_;\n      };\n      #endif\n\n      template <typename T, typename GenericFunction>\n      class multimode_genfunction_node : public generic_function_node<T,GenericFunction>\n      {\n      public:\n\n         typedef generic_function_node<T,GenericFunction> gen_function_t;\n         typedef range_pack<T> range_t;\n\n         multimode_genfunction_node(GenericFunction* func,\n                                    const std::size_t& param_seq_index,\n                                    const std::vector<typename gen_function_t::expression_ptr>& arg_list)\n         : gen_function_t(arg_list,func),\n           param_seq_index_(param_seq_index)\n         {}\n\n         inline T value() const\n         {\n            T result = std::numeric_limits<T>::quiet_NaN();\n\n            if (gen_function_t::function_)\n            {\n               if (gen_function_t::populate_value_list())\n               {\n                  typedef typename GenericFunction::parameter_list_t parameter_list_t;\n\n                  return (*gen_function_t::function_)(param_seq_index_,\n                                                      parameter_list_t(gen_function_t::typestore_list_));\n               }\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_genfunction;\n         }\n\n      private:\n\n         std::size_t param_seq_index_;\n      };\n\n      #ifndef exprtk_disable_string_capabilities\n      template <typename T, typename StringFunction>\n      class multimode_strfunction_node : public string_function_node<T,StringFunction>\n      {\n      public:\n\n         typedef string_function_node<T,StringFunction> str_function_t;\n         typedef range_pack<T> range_t;\n\n         multimode_strfunction_node(StringFunction* func,\n                                    const std::size_t& param_seq_index,\n                                    const std::vector<typename str_function_t::expression_ptr>& arg_list)\n         : str_function_t(func,arg_list),\n           param_seq_index_(param_seq_index)\n         {}\n\n         inline T value() const\n         {\n            T result = std::numeric_limits<T>::quiet_NaN();\n\n            if (str_function_t::function_)\n            {\n               if (str_function_t::populate_value_list())\n               {\n                  typedef typename StringFunction::parameter_list_t parameter_list_t;\n\n                  result = (*str_function_t::function_)(param_seq_index_,\n                                                        str_function_t::ret_string_,\n                                                        parameter_list_t(str_function_t::typestore_list_));\n\n                  str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size() - 1;\n                  str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;\n\n                  return result;\n               }\n            }\n\n            return result;\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_strfunction;\n         }\n\n      private:\n\n         const std::size_t param_seq_index_;\n      };\n      #endif\n\n      class return_exception\n      {};\n\n      template <typename T>\n      class null_igenfunc\n      {\n      public:\n\n         virtual ~null_igenfunc()\n         {}\n\n         typedef type_store<T> generic_type;\n         typedef typename generic_type::parameter_list parameter_list_t;\n\n         inline virtual T operator() (parameter_list_t)\n         {\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n      };\n\n      #ifndef exprtk_disable_return_statement\n      template <typename T>\n      class return_node : public generic_function_node<T,null_igenfunc<T> >\n      {\n      public:\n\n         typedef null_igenfunc<T> igeneric_function_t;\n         typedef igeneric_function_t* igeneric_function_ptr;\n         typedef generic_function_node<T,igeneric_function_t> gen_function_t;\n         typedef results_context<T> results_context_t;\n\n         return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,\n                     results_context_t& rc)\n         : gen_function_t  (arg_list),\n           results_context_(&rc)\n         {}\n\n         inline T value() const\n         {\n            if (\n                 (0 != results_context_) &&\n                 gen_function_t::populate_value_list()\n               )\n            {\n               typedef typename type_store<T>::parameter_list parameter_list_t;\n\n               results_context_->\n                  assign(parameter_list_t(gen_function_t::typestore_list_));\n\n               throw return_exception();\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_return;\n         }\n\n      private:\n\n         results_context_t* results_context_;\n      };\n\n      template <typename T>\n      class return_envelope_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef results_context<T>  results_context_t;\n\n         return_envelope_node(expression_ptr body, results_context_t& rc)\n         : results_context_(&rc  ),\n           return_invoked_ (false),\n           body_           (body ),\n           body_deletable_ (branch_deletable(body_))\n         {}\n\n        ~return_envelope_node()\n         {\n            if (body_ && body_deletable_)\n            {\n               destroy_node(body_);\n            }\n         }\n\n         inline T value() const\n         {\n            try\n            {\n               return_invoked_ = false;\n               results_context_->clear();\n\n               return body_->value();\n            }\n            catch(const return_exception&)\n            {\n               return_invoked_ = true;\n               return std::numeric_limits<T>::quiet_NaN();\n            }\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_retenv;\n         }\n\n         inline bool* retinvk_ptr()\n         {\n            return &return_invoked_;\n         }\n\n      private:\n\n         results_context_t* results_context_;\n         mutable bool       return_invoked_;\n         expression_ptr     body_;\n         const bool         body_deletable_;\n      };\n      #endif\n\n      #define exprtk_define_unary_op(OpName)                    \\\n      template <typename T>                                     \\\n      struct OpName##_op                                        \\\n      {                                                         \\\n         typedef typename functor_t<T>::Type Type;              \\\n         typedef typename expression_node<T>::node_type node_t; \\\n                                                                \\\n         static inline T process(Type v)                        \\\n         {                                                      \\\n            return numeric:: OpName (v);                        \\\n         }                                                      \\\n                                                                \\\n         static inline node_t type()                            \\\n         {                                                      \\\n            return expression_node<T>::e_##OpName;              \\\n         }                                                      \\\n                                                                \\\n         static inline details::operator_type operation()       \\\n         {                                                      \\\n            return details::e_##OpName;                         \\\n         }                                                      \\\n      };                                                        \\\n\n      exprtk_define_unary_op(abs  )\n      exprtk_define_unary_op(acos )\n      exprtk_define_unary_op(acosh)\n      exprtk_define_unary_op(asin )\n      exprtk_define_unary_op(asinh)\n      exprtk_define_unary_op(atan )\n      exprtk_define_unary_op(atanh)\n      exprtk_define_unary_op(ceil )\n      exprtk_define_unary_op(cos  )\n      exprtk_define_unary_op(cosh )\n      exprtk_define_unary_op(cot  )\n      exprtk_define_unary_op(csc  )\n      exprtk_define_unary_op(d2g  )\n      exprtk_define_unary_op(d2r  )\n      exprtk_define_unary_op(erf  )\n      exprtk_define_unary_op(erfc )\n      exprtk_define_unary_op(exp  )\n      exprtk_define_unary_op(expm1)\n      exprtk_define_unary_op(floor)\n      exprtk_define_unary_op(frac )\n      exprtk_define_unary_op(g2d  )\n      exprtk_define_unary_op(log  )\n      exprtk_define_unary_op(log10)\n      exprtk_define_unary_op(log2 )\n      exprtk_define_unary_op(log1p)\n      exprtk_define_unary_op(ncdf )\n      exprtk_define_unary_op(neg  )\n      exprtk_define_unary_op(notl )\n      exprtk_define_unary_op(pos  )\n      exprtk_define_unary_op(r2d  )\n      exprtk_define_unary_op(round)\n      exprtk_define_unary_op(sec  )\n      exprtk_define_unary_op(sgn  )\n      exprtk_define_unary_op(sin  )\n      exprtk_define_unary_op(sinc )\n      exprtk_define_unary_op(sinh )\n      exprtk_define_unary_op(sqrt )\n      exprtk_define_unary_op(tan  )\n      exprtk_define_unary_op(tanh )\n      exprtk_define_unary_op(trunc)\n      #undef exprtk_define_unary_op\n\n      template <typename T>\n      struct opr_base\n      {\n         typedef typename details::functor_t<T>::Type Type;\n         typedef typename details::functor_t<T>::RefType RefType;\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::qfunc_t quaternary_functor_t;\n         typedef typename functor_t::tfunc_t    trinary_functor_t;\n         typedef typename functor_t::bfunc_t     binary_functor_t;\n         typedef typename functor_t::ufunc_t      unary_functor_t;\n      };\n\n      template <typename T>\n      struct add_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         typedef typename opr_base<T>::RefType RefType;\n         static inline T process(Type t1, Type t2) { return t1 + t2; }\n         static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }\n         static inline void assign(RefType t1, Type t2) { t1 += t2; }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }\n         static inline details::operator_type operation() { return details::e_add; }\n      };\n\n      template <typename T>\n      struct mul_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         typedef typename opr_base<T>::RefType RefType;\n         static inline T process(Type t1, Type t2) { return t1 * t2; }\n         static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }\n         static inline void assign(RefType t1, Type t2) { t1 *= t2; }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }\n         static inline details::operator_type operation() { return details::e_mul; }\n      };\n\n      template <typename T>\n      struct sub_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         typedef typename opr_base<T>::RefType RefType;\n         static inline T process(Type t1, Type t2) { return t1 - t2; }\n         static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }\n         static inline void assign(RefType t1, Type t2) { t1 -= t2; }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }\n         static inline details::operator_type operation() { return details::e_sub; }\n      };\n\n      template <typename T>\n      struct div_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         typedef typename opr_base<T>::RefType RefType;\n         static inline T process(Type t1, Type t2) { return t1 / t2; }\n         static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }\n         static inline void assign(RefType t1, Type t2) { t1 /= t2; }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }\n         static inline details::operator_type operation() { return details::e_div; }\n      };\n\n      template <typename T>\n      struct mod_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         typedef typename opr_base<T>::RefType RefType;\n         static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }\n         static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }\n         static inline details::operator_type operation() { return details::e_mod; }\n      };\n\n      template <typename T>\n      struct pow_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         typedef typename opr_base<T>::RefType RefType;\n         static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }\n         static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }\n         static inline details::operator_type operation() { return details::e_pow; }\n      };\n\n      template <typename T>\n      struct lt_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }\n         static inline details::operator_type operation() { return details::e_lt; }\n      };\n\n      template <typename T>\n      struct lte_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }\n         static inline details::operator_type operation() { return details::e_lte; }\n      };\n\n      template <typename T>\n      struct gt_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }\n         static inline details::operator_type operation() { return details::e_gt; }\n      };\n\n      template <typename T>\n      struct gte_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }\n         static inline details::operator_type operation() { return details::e_gte; }\n      };\n\n      template <typename T>\n      struct eq_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }\n         static inline details::operator_type operation() { return details::e_eq; }\n      };\n\n      template <typename T>\n      struct equal_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }\n         static inline details::operator_type operation() { return details::e_equal; }\n      };\n\n      template <typename T>\n      struct ne_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }\n         static inline details::operator_type operation() { return details::e_ne; }\n      };\n\n      template <typename T>\n      struct and_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }\n         static inline details::operator_type operation() { return details::e_and; }\n      };\n\n      template <typename T>\n      struct nand_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }\n         static inline details::operator_type operation() { return details::e_nand; }\n      };\n\n      template <typename T>\n      struct or_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }\n         static inline details::operator_type operation() { return details::e_or; }\n      };\n\n      template <typename T>\n      struct nor_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }\n         static inline details::operator_type operation() { return details::e_nor; }\n      };\n\n      template <typename T>\n      struct xor_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }\n         static inline details::operator_type operation() { return details::e_xor; }\n      };\n\n      template <typename T>\n      struct xnor_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }\n         static inline details::operator_type operation() { return details::e_xnor; }\n      };\n\n      template <typename T>\n      struct in_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }\n         static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }\n         static inline details::operator_type operation() { return details::e_in; }\n      };\n\n      template <typename T>\n      struct like_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }\n         static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }\n         static inline details::operator_type operation() { return details::e_like; }\n      };\n\n      template <typename T>\n      struct ilike_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }\n         static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }\n         static inline details::operator_type operation() { return details::e_ilike; }\n      };\n\n      template <typename T>\n      struct inrange_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n         static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }\n         static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)\n         {\n            return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);\n         }\n         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }\n         static inline details::operator_type operation() { return details::e_inrange; }\n      };\n\n      template <typename T>\n      inline T value(details::expression_node<T>* n)\n      {\n         return n->value();\n      }\n\n      template <typename T>\n      inline T value(T* t)\n      {\n         return (*t);\n      }\n\n      template <typename T>\n      struct vararg_add_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 0  : return T(0);\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default :\n                         {\n                            T result = T(0);\n\n                            for (std::size_t i = 0; i < arg_list.size(); ++i)\n                            {\n                              result += value(arg_list[i]);\n                            }\n\n                            return result;\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return value(arg_list[0]);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) + value(arg_list[1]);\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) + value(arg_list[1]) +\n                   value(arg_list[2]);\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) + value(arg_list[1]) +\n                   value(arg_list[2]) + value(arg_list[3]);\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) + value(arg_list[1]) +\n                   value(arg_list[2]) + value(arg_list[3]) +\n                   value(arg_list[4]);\n         }\n      };\n\n      template <typename T>\n      struct vararg_mul_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 0  : return T(0);\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default :\n                         {\n                            T result = T(value(arg_list[0]));\n\n                            for (std::size_t i = 1; i < arg_list.size(); ++i)\n                            {\n                               result *= value(arg_list[i]);\n                            }\n\n                            return result;\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return value(arg_list[0]);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) * value(arg_list[1]);\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) * value(arg_list[1]) *\n                   value(arg_list[2]);\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) * value(arg_list[1]) *\n                   value(arg_list[2]) * value(arg_list[3]);\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return value(arg_list[0]) * value(arg_list[1]) *\n                   value(arg_list[2]) * value(arg_list[3]) *\n                   value(arg_list[4]);\n         }\n      };\n\n      template <typename T>\n      struct vararg_avg_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 0  : return T(0);\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default : return vararg_add_op<T>::process(arg_list) / arg_list.size();\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return value(arg_list[0]);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return (value(arg_list[0]) + value(arg_list[1])) / T(2);\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return (value(arg_list[0]) + value(arg_list[1]) +\n                    value(arg_list[2]) + value(arg_list[3])) / T(4);\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return (value(arg_list[0]) + value(arg_list[1]) +\n                    value(arg_list[2]) + value(arg_list[3]) +\n                    value(arg_list[4])) / T(5);\n         }\n      };\n\n      template <typename T>\n      struct vararg_min_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 0  : return T(0);\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default :\n                         {\n                            T result = T(value(arg_list[0]));\n\n                            for (std::size_t i = 1; i < arg_list.size(); ++i)\n                            {\n                               const T v = value(arg_list[i]);\n\n                               if (v < result)\n                                  result = v;\n                            }\n\n                            return result;\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return value(arg_list[0]);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return std::min<T>(value(arg_list[0]),value(arg_list[1]));\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return std::min<T>(\n                        std::min<T>(value(arg_list[0]),value(arg_list[1])),\n                        std::min<T>(value(arg_list[2]),value(arg_list[3])));\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return std::min<T>(\n                   std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),\n                               std::min<T>(value(arg_list[2]),value(arg_list[3]))),\n                               value(arg_list[4]));\n         }\n      };\n\n      template <typename T>\n      struct vararg_max_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 0  : return T(0);\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default :\n                         {\n                            T result = T(value(arg_list[0]));\n\n                            for (std::size_t i = 1; i < arg_list.size(); ++i)\n                            {\n                               const T v = value(arg_list[i]);\n\n                               if (v > result)\n                                  result = v;\n                            }\n\n                            return result;\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return value(arg_list[0]);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return std::max<T>(value(arg_list[0]),value(arg_list[1]));\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return std::max<T>(\n                        std::max<T>(value(arg_list[0]),value(arg_list[1])),\n                        std::max<T>(value(arg_list[2]),value(arg_list[3])));\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return std::max<T>(\n                   std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),\n                               std::max<T>(value(arg_list[2]),value(arg_list[3]))),\n                               value(arg_list[4]));\n         }\n      };\n\n      template <typename T>\n      struct vararg_mand_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default :\n                         {\n                            for (std::size_t i = 0; i < arg_list.size(); ++i)\n                            {\n                               if (std::equal_to<T>()(T(0),value(arg_list[i])))\n                                  return T(0);\n                            }\n\n                            return T(1);\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return std::not_equal_to<T>()\n                      (T(0),value(arg_list[0])) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[1]))\n                   ) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[2]))\n                   ) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[2])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[3]))\n                   ) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[2])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[3])) &&\n                     std::not_equal_to<T>()(T(0),value(arg_list[4]))\n                   ) ? T(1) : T(0);\n         }\n      };\n\n      template <typename T>\n      struct vararg_mor_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               default :\n                         {\n                            for (std::size_t i = 0; i < arg_list.size(); ++i)\n                            {\n                               if (std::not_equal_to<T>()(T(0),value(arg_list[i])))\n                                  return T(1);\n                            }\n\n                            return T(0);\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return std::not_equal_to<T>()\n                      (T(0),value(arg_list[0])) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[1]))\n                   ) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[2]))\n                   ) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[2])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[3]))\n                   ) ? T(1) : T(0);\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n            return (\n                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[2])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[3])) ||\n                     std::not_equal_to<T>()(T(0),value(arg_list[4]))\n                   ) ? T(1) : T(0);\n         }\n      };\n\n      template <typename T>\n      struct vararg_multi_op : public opr_base<T>\n      {\n         typedef typename opr_base<T>::Type Type;\n\n         template <typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         static inline T process(const Sequence<Type,Allocator>& arg_list)\n         {\n            switch (arg_list.size())\n            {\n               case 0  : return std::numeric_limits<T>::quiet_NaN();\n               case 1  : return process_1(arg_list);\n               case 2  : return process_2(arg_list);\n               case 3  : return process_3(arg_list);\n               case 4  : return process_4(arg_list);\n               case 5  : return process_5(arg_list);\n               case 6  : return process_6(arg_list);\n               case 7  : return process_7(arg_list);\n               case 8  : return process_8(arg_list);\n               default :\n                         {\n                            for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)\n                            {\n                               value(arg_list[i]);\n                            }\n\n                            return value(arg_list.back());\n                         }\n            }\n         }\n\n         template <typename Sequence>\n         static inline T process_1(const Sequence& arg_list)\n         {\n            return value(arg_list[0]);\n         }\n\n         template <typename Sequence>\n         static inline T process_2(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n            return value(arg_list[1]);\n         }\n\n         template <typename Sequence>\n         static inline T process_3(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n                   value(arg_list[1]);\n            return value(arg_list[2]);\n         }\n\n         template <typename Sequence>\n         static inline T process_4(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n                   value(arg_list[1]);\n                   value(arg_list[2]);\n            return value(arg_list[3]);\n         }\n\n         template <typename Sequence>\n         static inline T process_5(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n                   value(arg_list[1]);\n                   value(arg_list[2]);\n                   value(arg_list[3]);\n            return value(arg_list[4]);\n         }\n\n         template <typename Sequence>\n         static inline T process_6(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n                   value(arg_list[1]);\n                   value(arg_list[2]);\n                   value(arg_list[3]);\n                   value(arg_list[4]);\n            return value(arg_list[5]);\n         }\n\n         template <typename Sequence>\n         static inline T process_7(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n                   value(arg_list[1]);\n                   value(arg_list[2]);\n                   value(arg_list[3]);\n                   value(arg_list[4]);\n                   value(arg_list[5]);\n            return value(arg_list[6]);\n         }\n\n         template <typename Sequence>\n         static inline T process_8(const Sequence& arg_list)\n         {\n                   value(arg_list[0]);\n                   value(arg_list[1]);\n                   value(arg_list[2]);\n                   value(arg_list[3]);\n                   value(arg_list[4]);\n                   value(arg_list[5]);\n                   value(arg_list[6]);\n            return value(arg_list[7]);\n         }\n      };\n\n      template <typename T>\n      struct vec_add_op\n      {\n         typedef vector_interface<T>* ivector_ptr;\n\n         static inline T process(const ivector_ptr v)\n         {\n            const T* vec = v->vec()->vds().data();\n            const std::size_t vec_size = v->vec()->vds().size();\n\n            loop_unroll::details lud(vec_size);\n\n            if (vec_size <= static_cast<std::size_t>(lud.batch_size))\n            {\n               T result = T(0);\n               int i    = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (vec_size)\n               {\n                  #define case_stmt(N)         \\\n                  case N : result += vec[i++]; \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(16) case_stmt(15)\n                  case_stmt(14) case_stmt(13)\n                  case_stmt(12) case_stmt(11)\n                  case_stmt(10) case_stmt( 9)\n                  case_stmt( 8) case_stmt( 7)\n                  case_stmt( 6) case_stmt( 5)\n                  #endif\n                  case_stmt( 4) case_stmt( 3)\n                  case_stmt( 2) case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef case_stmt\n\n               return result;\n            }\n\n            T r[] = {\n                      T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),\n                      T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)\n                    };\n\n            const T* upper_bound = vec + lud.upper_bound;\n\n            while (vec < upper_bound)\n            {\n               #define exprtk_loop(N) \\\n               r[N] += vec[N];        \\\n\n               exprtk_loop( 0) exprtk_loop( 1)\n               exprtk_loop( 2) exprtk_loop( 3)\n               #ifndef exprtk_disable_superscalar_unroll\n               exprtk_loop( 4) exprtk_loop( 5)\n               exprtk_loop( 6) exprtk_loop( 7)\n               exprtk_loop( 8) exprtk_loop( 9)\n               exprtk_loop(10) exprtk_loop(11)\n               exprtk_loop(12) exprtk_loop(13)\n               exprtk_loop(14) exprtk_loop(15)\n               #endif\n\n               vec += lud.batch_size;\n            }\n\n            int i = 0;\n\n            exprtk_disable_fallthrough_begin\n            switch (lud.remainder)\n            {\n               #define case_stmt(N)       \\\n               case N : r[0] += vec[i++]; \\\n\n               #ifndef exprtk_disable_superscalar_unroll\n               case_stmt(15) case_stmt(14)\n               case_stmt(13) case_stmt(12)\n               case_stmt(11) case_stmt(10)\n               case_stmt( 9) case_stmt( 8)\n               case_stmt( 7) case_stmt( 6)\n               case_stmt( 5) case_stmt( 4)\n               #endif\n               case_stmt( 3) case_stmt( 2)\n               case_stmt( 1)\n            }\n            exprtk_disable_fallthrough_end\n\n            #undef exprtk_loop\n            #undef case_stmt\n\n            return (r[ 0] + r[ 1] + r[ 2] + r[ 3])\n                   #ifndef exprtk_disable_superscalar_unroll\n                 + (r[ 4] + r[ 5] + r[ 6] + r[ 7])\n                 + (r[ 8] + r[ 9] + r[10] + r[11])\n                 + (r[12] + r[13] + r[14] + r[15])\n                   #endif\n                   ;\n         }\n      };\n\n      template <typename T>\n      struct vec_mul_op\n      {\n         typedef vector_interface<T>* ivector_ptr;\n\n         static inline T process(const ivector_ptr v)\n         {\n            const T* vec = v->vec()->vds().data();\n            const std::size_t vec_size = v->vec()->vds().size();\n\n            loop_unroll::details lud(vec_size);\n\n            if (vec_size <= static_cast<std::size_t>(lud.batch_size))\n            {\n               T result = T(1);\n               int i    = 0;\n\n               exprtk_disable_fallthrough_begin\n               switch (vec_size)\n               {\n                  #define case_stmt(N)         \\\n                  case N : result *= vec[i++]; \\\n\n                  #ifndef exprtk_disable_superscalar_unroll\n                  case_stmt(16) case_stmt(15)\n                  case_stmt(14) case_stmt(13)\n                  case_stmt(12) case_stmt(11)\n                  case_stmt(10) case_stmt( 9)\n                  case_stmt( 8) case_stmt( 7)\n                  case_stmt( 6) case_stmt( 5)\n                  #endif\n                  case_stmt( 4) case_stmt( 3)\n                  case_stmt( 2) case_stmt( 1)\n               }\n               exprtk_disable_fallthrough_end\n\n               #undef case_stmt\n\n               return result;\n            }\n\n            T r[] = {\n                      T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),\n                      T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)\n                    };\n\n            const T* upper_bound = vec + lud.upper_bound;\n\n            while (vec < upper_bound)\n            {\n               #define exprtk_loop(N) \\\n               r[N] *= vec[N];        \\\n\n               exprtk_loop( 0) exprtk_loop( 1)\n               exprtk_loop( 2) exprtk_loop( 3)\n               #ifndef exprtk_disable_superscalar_unroll\n               exprtk_loop( 4) exprtk_loop( 5)\n               exprtk_loop( 6) exprtk_loop( 7)\n               exprtk_loop( 8) exprtk_loop( 9)\n               exprtk_loop(10) exprtk_loop(11)\n               exprtk_loop(12) exprtk_loop(13)\n               exprtk_loop(14) exprtk_loop(15)\n               #endif\n\n               vec += lud.batch_size;\n            }\n\n            int i = 0;\n\n            exprtk_disable_fallthrough_begin\n            switch (lud.remainder)\n            {\n               #define case_stmt(N)       \\\n               case N : r[0] *= vec[i++]; \\\n\n               #ifndef exprtk_disable_superscalar_unroll\n               case_stmt(15) case_stmt(14)\n               case_stmt(13) case_stmt(12)\n               case_stmt(11) case_stmt(10)\n               case_stmt( 9) case_stmt( 8)\n               case_stmt( 7) case_stmt( 6)\n               case_stmt( 5) case_stmt( 4)\n               #endif\n               case_stmt( 3) case_stmt( 2)\n               case_stmt( 1)\n            }\n            exprtk_disable_fallthrough_end\n\n            #undef exprtk_loop\n            #undef case_stmt\n\n            return (r[ 0] * r[ 1] * r[ 2] * r[ 3])\n                   #ifndef exprtk_disable_superscalar_unroll\n                 + (r[ 4] * r[ 5] * r[ 6] * r[ 7])\n                 + (r[ 8] * r[ 9] * r[10] * r[11])\n                 + (r[12] * r[13] * r[14] * r[15])\n                   #endif\n                   ;\n         }\n      };\n\n      template <typename T>\n      struct vec_avg_op\n      {\n         typedef vector_interface<T>* ivector_ptr;\n\n         static inline T process(const ivector_ptr v)\n         {\n            const std::size_t vec_size = v->vec()->vds().size();\n\n            return vec_add_op<T>::process(v) / vec_size;\n         }\n      };\n\n      template <typename T>\n      struct vec_min_op\n      {\n         typedef vector_interface<T>* ivector_ptr;\n\n         static inline T process(const ivector_ptr v)\n         {\n            const T* vec = v->vec()->vds().data();\n            const std::size_t vec_size = v->vec()->vds().size();\n\n            T result = vec[0];\n\n            for (std::size_t i = 1; i < vec_size; ++i)\n            {\n               T v_i = vec[i];\n\n               if (v_i < result)\n                  result = v_i;\n            }\n\n            return result;\n         }\n      };\n\n      template <typename T>\n      struct vec_max_op\n      {\n         typedef vector_interface<T>* ivector_ptr;\n\n         static inline T process(const ivector_ptr v)\n         {\n            const T* vec = v->vec()->vds().data();\n            const std::size_t vec_size = v->vec()->vds().size();\n\n            T result = vec[0];\n\n            for (std::size_t i = 1; i < vec_size; ++i)\n            {\n               T v_i = vec[i];\n\n               if (v_i > result)\n                  result = v_i;\n            }\n\n            return result;\n         }\n      };\n\n      template <typename T>\n      class vov_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~vov_base_node()\n         {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         virtual const T& v0() const = 0;\n\n         virtual const T& v1() const = 0;\n      };\n\n      template <typename T>\n      class cov_base_node : public expression_node<T>\n      {\n      public:\n\n       virtual ~cov_base_node()\n          {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         virtual const T c() const = 0;\n\n         virtual const T& v() const = 0;\n      };\n\n      template <typename T>\n      class voc_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~voc_base_node()\n         {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         virtual const T c() const = 0;\n\n         virtual const T& v() const = 0;\n      };\n\n      template <typename T>\n      class vob_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~vob_base_node()\n         {}\n\n         virtual const T& v() const = 0;\n      };\n\n      template <typename T>\n      class bov_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~bov_base_node()\n         {}\n\n         virtual const T& v() const = 0;\n      };\n\n      template <typename T>\n      class cob_base_node : public expression_node<T>\n      {\n      public:\n\n       virtual ~cob_base_node()\n       {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         virtual const T c() const = 0;\n\n         virtual void set_c(const T) = 0;\n\n         virtual expression_node<T>* move_branch(const std::size_t& index) = 0;\n      };\n\n      template <typename T>\n      class boc_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~boc_base_node()\n         {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         virtual const T c() const = 0;\n\n         virtual void set_c(const T) = 0;\n\n         virtual expression_node<T>* move_branch(const std::size_t& index) = 0;\n      };\n\n      template <typename T>\n      class uv_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~uv_base_node()\n         {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         virtual const T& v() const = 0;\n      };\n\n      template <typename T>\n      class sos_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~sos_base_node()\n         {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n      };\n\n      template <typename T>\n      class sosos_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~sosos_base_node()\n         {}\n\n         inline virtual operator_type operation() const\n         {\n            return details::e_default;\n         }\n      };\n\n      template <typename T>\n      class T0oT1oT2_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~T0oT1oT2_base_node()\n         {}\n\n         virtual std::string type_id() const = 0;\n      };\n\n      template <typename T>\n      class T0oT1oT2oT3_base_node : public expression_node<T>\n      {\n      public:\n\n         virtual ~T0oT1oT2oT3_base_node()\n         {}\n\n         virtual std::string type_id() const = 0;\n      };\n\n      template <typename T, typename Operation>\n      class unary_variable_node : public uv_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         explicit unary_variable_node(const T& var)\n         : v_(var)\n         {}\n\n         inline T value() const\n         {\n            return Operation::process(v_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T& v() const\n         {\n            return v_;\n         }\n\n      private:\n\n         unary_variable_node(unary_variable_node<T,Operation>&);\n         unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);\n\n         const T& v_;\n      };\n\n      template <typename T>\n      class uvouv_node : public expression_node<T>\n      {\n      public:\n\n         // UOpr1(v0) Op UOpr2(v1)\n\n         typedef expression_node<T>* expression_ptr;\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::bfunc_t      bfunc_t;\n         typedef typename functor_t::ufunc_t      ufunc_t;\n\n         explicit uvouv_node(const T& var0,const T& var1,\n                             ufunc_t uf0, ufunc_t uf1, bfunc_t bf)\n         : v0_(var0),\n           v1_(var1),\n           u0_(uf0 ),\n           u1_(uf1 ),\n           f_ (bf  )\n         {}\n\n         inline T value() const\n         {\n            return f_(u0_(v0_),u1_(v1_));\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_uvouv;\n         }\n\n         inline operator_type operation() const\n         {\n            return details::e_default;\n         }\n\n         inline const T& v0()\n         {\n            return v0_;\n         }\n\n         inline const T& v1()\n         {\n            return v1_;\n         }\n\n         inline ufunc_t u0()\n         {\n            return u0_;\n         }\n\n         inline ufunc_t u1()\n         {\n            return u1_;\n         }\n\n         inline ufunc_t f()\n         {\n            return f_;\n         }\n\n      private:\n\n         uvouv_node(uvouv_node<T>&);\n         uvouv_node<T>& operator=(uvouv_node<T>&);\n\n         const T& v0_;\n         const T& v1_;\n         const ufunc_t u0_;\n         const ufunc_t u1_;\n         const bfunc_t f_;\n      };\n\n      template <typename T, typename Operation>\n      class unary_branch_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         explicit unary_branch_node(expression_ptr brnch)\n         : branch_(brnch),\n           branch_deletable_(branch_deletable(branch_))\n         {}\n\n        ~unary_branch_node()\n         {\n            if (branch_ && branch_deletable_)\n            {\n               destroy_node(branch_);\n            }\n         }\n\n         inline T value() const\n         {\n            return Operation::process(branch_->value());\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_;\n         }\n\n         inline void release()\n         {\n            branch_deletable_ = false;\n         }\n\n      private:\n\n         unary_branch_node(unary_branch_node<T,Operation>&);\n         unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);\n\n         expression_ptr branch_;\n         bool           branch_deletable_;\n      };\n\n      template <typename T> struct is_const                { enum {result = 0}; };\n      template <typename T> struct is_const <const T>      { enum {result = 1}; };\n      template <typename T> struct is_const_ref            { enum {result = 0}; };\n      template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };\n      template <typename T> struct is_ref                  { enum {result = 0}; };\n      template <typename T> struct is_ref<T&>              { enum {result = 1}; };\n      template <typename T> struct is_ref<const T&>        { enum {result = 0}; };\n\n      template <std::size_t State>\n      struct param_to_str { static std::string result() { static const std::string r(\"v\"); return r; } };\n\n      template <>\n      struct param_to_str<0> { static std::string result() { static const std::string r(\"c\"); return r; } };\n\n      #define exprtk_crtype(Type)                          \\\n      param_to_str<is_const_ref< Type >::result>::result() \\\n\n      template <typename T>\n      struct T0oT1oT2process\n      {\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::bfunc_t      bfunc_t;\n\n         struct mode0\n         {\n            static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)\n            {\n               // (T0 o0 T1) o1 T2\n               return bf1(bf0(t0,t1),t2);\n            }\n\n            template <typename T0, typename T1, typename T2>\n            static inline std::string id()\n            {\n               static const std::string result = \"(\" + exprtk_crtype(T0) + \"o\"   +\n                                                       exprtk_crtype(T1) + \")o(\" +\n                                                       exprtk_crtype(T2) + \")\"   ;\n               return result;\n            }\n         };\n\n         struct mode1\n         {\n            static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)\n            {\n               // T0 o0 (T1 o1 T2)\n               return bf0(t0,bf1(t1,t2));\n            }\n\n            template <typename T0, typename T1, typename T2>\n            static inline std::string id()\n            {\n               static const std::string result = \"(\" + exprtk_crtype(T0) + \")o(\" +\n                                                       exprtk_crtype(T1) + \"o\"   +\n                                                       exprtk_crtype(T2) + \")\"   ;\n               return result;\n            }\n         };\n      };\n\n      template <typename T>\n      struct T0oT1oT20T3process\n      {\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::bfunc_t      bfunc_t;\n\n         struct mode0\n         {\n            static inline T process(const T& t0, const T& t1,\n                                    const T& t2, const T& t3,\n                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)\n            {\n               // (T0 o0 T1) o1 (T2 o2 T3)\n               return bf1(bf0(t0,t1),bf2(t2,t3));\n            }\n\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline std::string id()\n            {\n               static const std::string result = \"(\" + exprtk_crtype(T0) + \"o\"  +\n                                                       exprtk_crtype(T1) + \")o\" +\n                                                 \"(\" + exprtk_crtype(T2) + \"o\"  +\n                                                       exprtk_crtype(T3) + \")\"  ;\n               return result;\n            }\n         };\n\n         struct mode1\n         {\n            static inline T process(const T& t0, const T& t1,\n                                    const T& t2, const T& t3,\n                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)\n            {\n               // (T0 o0 (T1 o1 (T2 o2 T3))\n               return bf0(t0,bf1(t1,bf2(t2,t3)));\n            }\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline std::string id()\n            {\n               static const std::string result = \"(\" + exprtk_crtype(T0) +  \")o((\" +\n                                                       exprtk_crtype(T1) +  \")o(\"  +\n                                                       exprtk_crtype(T2) +  \"o\"    +\n                                                       exprtk_crtype(T3) +  \"))\"   ;\n               return result;\n            }\n         };\n\n         struct mode2\n         {\n            static inline T process(const T& t0, const T& t1,\n                                    const T& t2, const T& t3,\n                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)\n            {\n               // (T0 o0 ((T1 o1 T2) o2 T3)\n               return bf0(t0,bf2(bf1(t1,t2),t3));\n            }\n\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline std::string id()\n            {\n               static const std::string result = \"(\" + exprtk_crtype(T0) + \")o((\" +\n                                                       exprtk_crtype(T1) + \"o\"    +\n                                                       exprtk_crtype(T2) + \")o(\"  +\n                                                       exprtk_crtype(T3) + \"))\"   ;\n               return result;\n            }\n         };\n\n         struct mode3\n         {\n            static inline T process(const T& t0, const T& t1,\n                                    const T& t2, const T& t3,\n                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)\n            {\n               // (((T0 o0 T1) o1 T2) o2 T3)\n               return bf2(bf1(bf0(t0,t1),t2),t3);\n            }\n\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline std::string id()\n            {\n               static const std::string result = \"((\" + exprtk_crtype(T0) + \"o\"    +\n                                                        exprtk_crtype(T1) + \")o(\"  +\n                                                        exprtk_crtype(T2) + \"))o(\" +\n                                                        exprtk_crtype(T3) + \")\";\n               return result;\n            }\n         };\n\n         struct mode4\n         {\n            static inline T process(const T& t0, const T& t1,\n                                    const T& t2, const T& t3,\n                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)\n            {\n               // ((T0 o0 (T1 o1 T2)) o2 T3\n               return bf2(bf0(t0,bf1(t1,t2)),t3);\n            }\n\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline std::string id()\n            {\n               static const std::string result = \"((\" + exprtk_crtype(T0) + \")o(\"  +\n                                                        exprtk_crtype(T1) + \"o\"    +\n                                                        exprtk_crtype(T2) + \"))o(\" +\n                                                        exprtk_crtype(T3) + \")\"    ;\n               return result;\n            }\n         };\n      };\n\n      #undef exprtk_crtype\n\n      template <typename T, typename T0, typename T1>\n      struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };\n      template <typename T, typename T0, typename T1>\n      const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;\n\n      #define synthesis_node_type_define(T0_,T1_,v_)                                                            \\\n      template <typename T, typename T0, typename T1>                                                           \\\n      struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \\\n      template <typename T, typename T0, typename T1>                                                           \\\n      const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \\\n\n      synthesis_node_type_define(const T0&,const T1&, e_vov)\n      synthesis_node_type_define(const T0&,const T1 , e_voc)\n      synthesis_node_type_define(const T0 ,const T1&, e_cov)\n      synthesis_node_type_define(      T0&,      T1&,e_none)\n      synthesis_node_type_define(const T0 ,const T1 ,e_none)\n      synthesis_node_type_define(      T0&,const T1 ,e_none)\n      synthesis_node_type_define(const T0 ,      T1&,e_none)\n      synthesis_node_type_define(const T0&,      T1&,e_none)\n      synthesis_node_type_define(      T0&,const T1&,e_none)\n      #undef synthesis_node_type_define\n\n      template <typename T, typename T0, typename T1, typename T2>\n      struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };\n      template <typename T, typename T0, typename T1, typename T2>\n      const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;\n\n      #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \\\n      template <typename T, typename T0, typename T1, typename T2>                                                     \\\n      struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \\\n      template <typename T, typename T0, typename T1, typename T2>                                                     \\\n      const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \\\n\n      synthesis_node_type_define(const T0&,const T1&,const T2&, e_vovov)\n      synthesis_node_type_define(const T0&,const T1&,const T2 , e_vovoc)\n      synthesis_node_type_define(const T0&,const T1 ,const T2&, e_vocov)\n      synthesis_node_type_define(const T0 ,const T1&,const T2&, e_covov)\n      synthesis_node_type_define(const T0 ,const T1&,const T2 , e_covoc)\n      synthesis_node_type_define(const T0 ,const T1 ,const T2 , e_none )\n      synthesis_node_type_define(const T0 ,const T1 ,const T2&, e_none )\n      synthesis_node_type_define(const T0&,const T1 ,const T2 , e_none )\n      synthesis_node_type_define(      T0&,      T1&,      T2&, e_none )\n      #undef synthesis_node_type_define\n\n      template <typename T, typename T0, typename T1, typename T2, typename T3>\n      struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };\n      template <typename T, typename T0, typename T1, typename T2, typename T3>\n      const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;\n\n      #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \\\n      template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \\\n      struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \\\n      template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \\\n      const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \\\n\n      synthesis_node_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov)\n      synthesis_node_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc)\n      synthesis_node_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov)\n      synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov)\n      synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov)\n      synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov)\n      synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc)\n      synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc)\n      synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov)\n      synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none   )\n      synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none   )\n      synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none   )\n      synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none   )\n      synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none   )\n      synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none   )\n      synthesis_node_type_define(const T0&,const T1&,const T2 , const T3 ,e_none   )\n      #undef synthesis_node_type_define\n\n      template <typename T, typename T0, typename T1>\n      class T0oT1 : public expression_node<T>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::bfunc_t      bfunc_t;\n         typedef T value_type;\n         typedef T0oT1<T,T0,T1> node_type;\n\n         T0oT1(T0 p0, T1 p1, const bfunc_t p2)\n         : t0_(p0),\n           t1_(p1),\n           f_ (p2)\n         {}\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;\n            return result;\n         }\n\n         inline operator_type operation() const\n         {\n            return e_default;\n         }\n\n         inline T value() const\n         {\n            return f_(t0_,t1_);\n         }\n\n         inline T0 t0() const\n         {\n            return t0_;\n         }\n\n         inline T1 t1() const\n         {\n            return t1_;\n         }\n\n         inline bfunc_t f() const\n         {\n            return f_;\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator,\n                                                    T0 p0, T1 p1,\n                                                    bfunc_t p2)\n         {\n            return allocator\n                     .template allocate_type<node_type,T0,T1,bfunc_t&>\n                        (p0, p1, p2);\n         }\n\n      private:\n\n         T0oT1(T0oT1<T,T0,T1>&) {}\n         T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         const bfunc_t f_;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>\n      class T0oT1oT2 : public T0oT1oT2_base_node<T>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::bfunc_t      bfunc_t;\n         typedef T value_type;\n         typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;\n         typedef ProcessMode process_mode_t;\n\n         T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)\n         : t0_(p0),\n           t1_(p1),\n           t2_(p2),\n           f0_(p3),\n           f1_(p4)\n         {}\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;\n            return result;\n         }\n\n         inline operator_type operation() const\n         {\n            return e_default;\n         }\n\n         inline T value() const\n         {\n            return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);\n         }\n\n         inline T0 t0() const\n         {\n            return t0_;\n         }\n\n         inline T1 t1() const\n         {\n            return t1_;\n         }\n\n         inline T2 t2() const\n         {\n            return t2_;\n         }\n\n         bfunc_t f0() const\n         {\n            return f0_;\n         }\n\n         bfunc_t f1() const\n         {\n            return f1_;\n         }\n\n         std::string type_id() const\n         {\n            return id();\n         }\n\n         static inline std::string id()\n         {\n            return process_mode_t::template id<T0,T1,T2>();\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)\n         {\n            return allocator\n                      .template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>\n                         (p0, p1, p2, p3, p4);\n         }\n\n      private:\n\n         T0oT1oT2(node_type&) {}\n         node_type& operator=(node_type&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         T2 t2_;\n         const bfunc_t f0_;\n         const bfunc_t f1_;\n      };\n\n      template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>\n      class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::bfunc_t      bfunc_t;\n         typedef T value_type;\n         typedef T0_ T0;\n         typedef T1_ T1;\n         typedef T2_ T2;\n         typedef T3_ T3;\n         typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;\n         typedef ProcessMode process_mode_t;\n\n         T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)\n         : t0_(p0),\n           t1_(p1),\n           t2_(p2),\n           t3_(p3),\n           f0_(p4),\n           f1_(p5),\n           f2_(p6)\n         {}\n\n         inline T value() const\n         {\n            return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);\n         }\n\n         inline T0 t0() const\n         {\n            return t0_;\n         }\n\n         inline T1 t1() const\n         {\n            return t1_;\n         }\n\n         inline T2 t2() const\n         {\n            return t2_;\n         }\n\n         inline T3 t3() const\n         {\n            return t3_;\n         }\n\n         inline bfunc_t f0() const\n         {\n            return f0_;\n         }\n\n         inline bfunc_t f1() const\n         {\n            return f1_;\n         }\n\n         inline bfunc_t f2() const\n         {\n            return f2_;\n         }\n\n         inline std::string type_id() const\n         {\n            return id();\n         }\n\n         static inline std::string id()\n         {\n            return process_mode_t::template id<T0,T1,T2,T3>();\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator,\n                                                    T0 p0, T1 p1, T2 p2, T3 p3,\n                                                    bfunc_t p4, bfunc_t p5, bfunc_t p6)\n         {\n            return allocator\n                      .template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>\n                         (p0, p1, p2, p3, p4, p5, p6);\n         }\n\n      private:\n\n         T0oT1oT2oT3(node_type&) {}\n         node_type& operator=(node_type&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         T2 t2_;\n         T3 t3_;\n         const bfunc_t f0_;\n         const bfunc_t f1_;\n         const bfunc_t f2_;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2>\n      class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::tfunc_t      tfunc_t;\n         typedef T value_type;\n         typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;\n\n         T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)\n         : t0_(p0),\n           t1_(p1),\n           t2_(p2),\n           f_ (p3)\n         {}\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;\n            return result;\n         }\n\n         inline operator_type operation() const\n         {\n            return e_default;\n         }\n\n         inline T value() const\n         {\n            return f_(t0_, t1_, t2_);\n         }\n\n         inline T0 t0() const\n         {\n            return t0_;\n         }\n\n         inline T1 t1() const\n         {\n            return t1_;\n         }\n\n         inline T2 t2() const\n         {\n            return t2_;\n         }\n\n         tfunc_t f() const\n         {\n            return f_;\n         }\n\n         std::string type_id() const\n         {\n            return id();\n         }\n\n         static inline std::string id()\n         {\n            return \"sf3\";\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)\n         {\n            return allocator\n                     .template allocate_type<node_type,T0,T1,T2,tfunc_t>\n                        (p0, p1, p2, p3);\n         }\n\n      private:\n\n         T0oT1oT2_sf3(node_type&) {}\n         node_type& operator=(node_type&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         T2 t2_;\n         const tfunc_t f_;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2>\n      class sf3ext_type_node : public T0oT1oT2_base_node<T>\n      {\n      public:\n\n         virtual ~sf3ext_type_node()\n         {}\n\n         virtual T0 t0() const = 0;\n\n         virtual T1 t1() const = 0;\n\n         virtual T2 t2() const = 0;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>\n      class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::tfunc_t      tfunc_t;\n         typedef T value_type;\n         typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;\n\n         T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)\n         : t0_(p0),\n           t1_(p1),\n           t2_(p2)\n         {}\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;\n            return result;\n         }\n\n         inline operator_type operation() const\n         {\n            return e_default;\n         }\n\n         inline T value() const\n         {\n            return SF3Operation::process(t0_, t1_, t2_);\n         }\n\n         T0 t0() const\n         {\n            return t0_;\n         }\n\n         T1 t1() const\n         {\n            return t1_;\n         }\n\n         T2 t2() const\n         {\n            return t2_;\n         }\n\n         std::string type_id() const\n         {\n            return id();\n         }\n\n         static inline std::string id()\n         {\n            return SF3Operation::id();\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)\n         {\n            return allocator\n                     .template allocate_type<node_type,T0,T1,T2>\n                        (p0, p1, p2);\n         }\n\n      private:\n\n         T0oT1oT2_sf3ext(node_type&) {}\n         node_type& operator=(node_type&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         T2 t2_;\n      };\n\n      template <typename T>\n      inline bool is_sf3ext_node(const expression_node<T>* n)\n      {\n         switch (n->type())\n         {\n            case expression_node<T>::e_vovov : return true;\n            case expression_node<T>::e_vovoc : return true;\n            case expression_node<T>::e_vocov : return true;\n            case expression_node<T>::e_covov : return true;\n            case expression_node<T>::e_covoc : return true;\n            default                          : return false;\n         }\n      }\n\n      template <typename T, typename T0, typename T1, typename T2, typename T3>\n      class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::qfunc_t      qfunc_t;\n         typedef T value_type;\n         typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;\n\n         T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)\n         : t0_(p0),\n           t1_(p1),\n           t2_(p2),\n           t3_(p3),\n           f_ (p4)\n         {}\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;\n            return result;\n         }\n\n         inline operator_type operation() const\n         {\n            return e_default;\n         }\n\n         inline T value() const\n         {\n            return f_(t0_, t1_, t2_, t3_);\n         }\n\n         inline T0 t0() const\n         {\n            return t0_;\n         }\n\n         inline T1 t1() const\n         {\n            return t1_;\n         }\n\n         inline T2 t2() const\n         {\n            return t2_;\n         }\n\n         inline T3 t3() const\n         {\n            return t3_;\n         }\n\n         qfunc_t f() const\n         {\n            return f_;\n         }\n\n         std::string type_id() const\n         {\n            return id();\n         }\n\n         static inline std::string id()\n         {\n            return \"sf4\";\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)\n         {\n            return allocator\n                     .template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>\n                        (p0, p1, p2, p3, p4);\n         }\n\n      private:\n\n         T0oT1oT2oT3_sf4(node_type&) {}\n         node_type& operator=(node_type&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         T2 t2_;\n         T3 t3_;\n         const qfunc_t f_;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>\n      class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>\n      {\n      public:\n\n         typedef typename details::functor_t<T> functor_t;\n         typedef typename functor_t::tfunc_t      tfunc_t;\n         typedef T value_type;\n         typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;\n\n         T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)\n         : t0_(p0),\n           t1_(p1),\n           t2_(p2),\n           t3_(p3)\n         {}\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;\n            return result;\n         }\n\n         inline operator_type operation() const\n         {\n            return e_default;\n         }\n\n         inline T value() const\n         {\n            return SF4Operation::process(t0_, t1_, t2_, t3_);\n         }\n\n         inline T0 t0() const\n         {\n            return t0_;\n         }\n\n         inline T1 t1() const\n         {\n            return t1_;\n         }\n\n         inline T2 t2() const\n         {\n            return t2_;\n         }\n\n         inline T3 t3() const\n         {\n            return t2_;\n         }\n\n         std::string type_id() const\n         {\n            return id();\n         }\n\n         static inline std::string id()\n         {\n            return SF4Operation::id();\n         }\n\n         template <typename Allocator>\n         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)\n         {\n            return allocator\n                     .template allocate_type<node_type,T0,T1,T2,T3>\n                        (p0, p1, p2, p3);\n         }\n\n      private:\n\n         T0oT1oT2oT3_sf4ext(node_type&) {}\n         node_type& operator=(node_type&) { return (*this); }\n\n         T0 t0_;\n         T1 t1_;\n         T2 t2_;\n         T3 t3_;\n      };\n\n      template <typename T>\n      inline bool is_sf4ext_node(const expression_node<T>* n)\n      {\n         switch (n->type())\n         {\n            case expression_node<T>::e_vovovov : return true;\n            case expression_node<T>::e_vovovoc : return true;\n            case expression_node<T>::e_vovocov : return true;\n            case expression_node<T>::e_vocovov : return true;\n            case expression_node<T>::e_covovov : return true;\n            case expression_node<T>::e_covocov : return true;\n            case expression_node<T>::e_vocovoc : return true;\n            case expression_node<T>::e_covovoc : return true;\n            case expression_node<T>::e_vococov : return true;\n            default                            : return false;\n         }\n      }\n\n      template <typename T, typename T0, typename T1>\n      struct T0oT1_define\n      {\n         typedef details::T0oT1<T,T0,T1> type0;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2>\n      struct T0oT1oT2_define\n      {\n         typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0;\n         typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1;\n         typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type;\n         typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node;\n      };\n\n      template <typename T, typename T0, typename T1, typename T2, typename T3>\n      struct T0oT1oT2oT3_define\n      {\n         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0;\n         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1;\n         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2;\n         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3;\n         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4;\n         typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type;\n      };\n\n      template <typename T, typename Operation>\n      class vov_node : public vov_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // variable op variable node\n         explicit vov_node(const T& var0, const T& var1)\n         : v0_(var0),\n           v1_(var1)\n         {}\n\n         inline T value() const\n         {\n            return Operation::process(v0_,v1_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T& v0() const\n         {\n            return v0_;\n         }\n\n         inline const T& v1() const\n         {\n            return v1_;\n         }\n\n      protected:\n\n         const T& v0_;\n         const T& v1_;\n\n      private:\n\n         vov_node(vov_node<T,Operation>&);\n         vov_node<T,Operation>& operator=(vov_node<T,Operation>&);\n      };\n\n      template <typename T, typename Operation>\n      class cov_node : public cov_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // constant op variable node\n         explicit cov_node(const T& const_var, const T& var)\n         : c_(const_var),\n           v_(var)\n         {}\n\n         inline T value() const\n         {\n            return Operation::process(c_,v_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T c() const\n         {\n            return c_;\n         }\n\n         inline const T& v() const\n         {\n            return v_;\n         }\n\n      protected:\n\n         const T  c_;\n         const T& v_;\n\n      private:\n\n         cov_node(const cov_node<T,Operation>&);\n         cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);\n      };\n\n      template <typename T, typename Operation>\n      class voc_node : public voc_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // variable op constant node\n         explicit voc_node(const T& var, const T& const_var)\n         : v_(var),\n           c_(const_var)\n         {}\n\n         inline T value() const\n         {\n            return Operation::process(v_,c_);\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T c() const\n         {\n            return c_;\n         }\n\n         inline const T& v() const\n         {\n            return v_;\n         }\n\n      protected:\n\n         const T& v_;\n         const T  c_;\n\n      private:\n\n         voc_node(const voc_node<T,Operation>&);\n         voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);\n      };\n\n      template <typename T, typename Operation>\n      class vob_node : public vob_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n         typedef Operation operation_t;\n\n         // variable op constant node\n         explicit vob_node(const T& var, const expression_ptr brnch)\n         : v_(var)\n         {\n            init_branches<1>(branch_,brnch);\n         }\n\n        ~vob_node()\n         {\n            cleanup_branches::execute<T,1>(branch_);\n         }\n\n         inline T value() const\n         {\n            return Operation::process(v_,branch_[0].first->value());\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T& v() const\n         {\n            return v_;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_[0].first;\n         }\n\n      private:\n\n         vob_node(const vob_node<T,Operation>&);\n         vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);\n\n         const T& v_;\n         branch_t branch_[1];\n      };\n\n      template <typename T, typename Operation>\n      class bov_node : public bov_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n         typedef Operation operation_t;\n\n         // variable op constant node\n         explicit bov_node(const expression_ptr brnch, const T& var)\n         : v_(var)\n         {\n            init_branches<1>(branch_,brnch);\n         }\n\n        ~bov_node()\n         {\n            cleanup_branches::execute<T,1>(branch_);\n         }\n\n         inline T value() const\n         {\n            return Operation::process(branch_[0].first->value(),v_);\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T& v() const\n         {\n            return v_;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_[0].first;\n         }\n\n      private:\n\n         bov_node(const bov_node<T,Operation>&);\n         bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);\n\n         const T& v_;\n         branch_t branch_[1];\n      };\n\n      template <typename T, typename Operation>\n      class cob_node : public cob_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n         typedef Operation operation_t;\n\n         // variable op constant node\n         explicit cob_node(const T const_var, const expression_ptr brnch)\n         : c_(const_var)\n         {\n            init_branches<1>(branch_,brnch);\n         }\n\n        ~cob_node()\n         {\n            cleanup_branches::execute<T,1>(branch_);\n         }\n\n         inline T value() const\n         {\n            return Operation::process(c_,branch_[0].first->value());\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T c() const\n         {\n            return c_;\n         }\n\n         inline void set_c(const T new_c)\n         {\n            (*const_cast<T*>(&c_)) = new_c;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_[0].first;\n         }\n\n         inline expression_node<T>* move_branch(const std::size_t&)\n         {\n            branch_[0].second = false;\n            return branch_[0].first;\n         }\n\n      private:\n\n         cob_node(const cob_node<T,Operation>&);\n         cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);\n\n         const T  c_;\n         branch_t branch_[1];\n      };\n\n      template <typename T, typename Operation>\n      class boc_node : public boc_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr,bool> branch_t;\n         typedef Operation operation_t;\n\n         // variable op constant node\n         explicit boc_node(const expression_ptr brnch, const T const_var)\n         : c_(const_var)\n         {\n            init_branches<1>(branch_,brnch);\n         }\n\n        ~boc_node()\n         {\n            cleanup_branches::execute<T,1>(branch_);\n         }\n\n         inline T value() const\n         {\n            return Operation::process(branch_[0].first->value(),c_);\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline const T c() const\n         {\n            return c_;\n         }\n\n         inline void set_c(const T new_c)\n         {\n            (*const_cast<T*>(&c_)) = new_c;\n         }\n\n         inline expression_node<T>* branch(const std::size_t&) const\n         {\n            return branch_[0].first;\n         }\n\n         inline expression_node<T>* move_branch(const std::size_t&)\n         {\n            branch_[0].second = false;\n            return branch_[0].first;\n         }\n\n      private:\n\n         boc_node(const boc_node<T,Operation>&);\n         boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);\n\n         const T  c_;\n         branch_t branch_[1];\n      };\n\n      #ifndef exprtk_disable_string_capabilities\n      template <typename T, typename SType0, typename SType1, typename Operation>\n      class sos_node : public sos_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // string op string node\n         explicit sos_node(SType0 p0, SType1 p1)\n         : s0_(p0),\n           s1_(p1)\n         {}\n\n         inline T value() const\n         {\n            return Operation::process(s0_,s1_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline std::string& s0()\n         {\n            return s0_;\n         }\n\n         inline std::string& s1()\n         {\n            return s1_;\n         }\n\n      protected:\n\n         SType0 s0_;\n         SType1 s1_;\n\n      private:\n\n         sos_node(sos_node<T,SType0,SType1,Operation>&);\n         sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);\n      };\n\n      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>\n      class str_xrox_node : public sos_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // string-range op string node\n         explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)\n         : s0_ (p0 ),\n           s1_ (p1 ),\n           rp0_(rp0)\n         {}\n\n        ~str_xrox_node()\n         {\n            rp0_.free();\n         }\n\n         inline T value() const\n         {\n            std::size_t r0 = 0;\n            std::size_t r1 = 0;\n\n            if (rp0_(r0, r1, s0_.size()))\n               return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);\n            else\n               return T(0);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline std::string& s0()\n         {\n            return s0_;\n         }\n\n         inline std::string& s1()\n         {\n            return s1_;\n         }\n\n      protected:\n\n         SType0    s0_;\n         SType1    s1_;\n         RangePack rp0_;\n\n      private:\n\n         str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);\n         str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);\n      };\n\n      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>\n      class str_xoxr_node : public sos_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // string op string range node\n         explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)\n         : s0_ (p0 ),\n           s1_ (p1 ),\n           rp1_(rp1)\n         {}\n\n        ~str_xoxr_node()\n         {\n            rp1_.free();\n         }\n\n         inline T value() const\n         {\n            std::size_t r0 = 0;\n            std::size_t r1 = 0;\n\n            if (rp1_(r0, r1, s1_.size()))\n               return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));\n            else\n               return T(0);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline std::string& s0()\n         {\n            return s0_;\n         }\n\n         inline std::string& s1()\n         {\n            return s1_;\n         }\n\n      protected:\n\n         SType0    s0_;\n         SType1    s1_;\n         RangePack rp1_;\n\n      private:\n\n         str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);\n         str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);\n      };\n\n      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>\n      class str_xroxr_node : public sos_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // string-range op string-range node\n         explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)\n         : s0_ (p0 ),\n           s1_ (p1 ),\n           rp0_(rp0),\n           rp1_(rp1)\n         {}\n\n        ~str_xroxr_node()\n         {\n            rp0_.free();\n            rp1_.free();\n         }\n\n         inline T value() const\n         {\n            std::size_t r0_0 = 0;\n            std::size_t r0_1 = 0;\n            std::size_t r1_0 = 0;\n            std::size_t r1_1 = 0;\n\n            if (\n                 rp0_(r0_0, r1_0, s0_.size()) &&\n                 rp1_(r0_1, r1_1, s1_.size())\n               )\n            {\n               return Operation::process(\n                                          s0_.substr(r0_0, (r1_0 - r0_0) + 1),\n                                          s1_.substr(r0_1, (r1_1 - r0_1) + 1)\n                                        );\n            }\n            else\n               return T(0);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline std::string& s0()\n         {\n            return s0_;\n         }\n\n         inline std::string& s1()\n         {\n            return s1_;\n         }\n\n      protected:\n\n         SType0    s0_;\n         SType1    s1_;\n         RangePack rp0_;\n         RangePack rp1_;\n\n      private:\n\n         str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);\n         str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);\n      };\n\n      template <typename T, typename Operation>\n      class str_sogens_node : public binary_node<T>\n      {\n      public:\n\n         typedef expression_node <T>* expression_ptr;\n         typedef string_base_node<T>*   str_base_ptr;\n         typedef range_pack      <T>         range_t;\n         typedef range_t*                  range_ptr;\n         typedef range_interface<T>         irange_t;\n         typedef irange_t*                irange_ptr;\n\n         str_sogens_node(const operator_type& opr,\n                         expression_ptr branch0,\n                         expression_ptr branch1)\n         : binary_node<T>(opr, branch0, branch1),\n           str0_base_ptr_ (0),\n           str1_base_ptr_ (0),\n           str0_range_ptr_(0),\n           str1_range_ptr_(0)\n         {\n            if (is_generally_string_node(binary_node<T>::branch_[0].first))\n            {\n               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == str0_base_ptr_)\n                  return;\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str0_range_ptr_ = &(range_ptr->range_ref());\n            }\n\n            if (is_generally_string_node(binary_node<T>::branch_[1].first))\n            {\n               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == str1_base_ptr_)\n                  return;\n\n               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);\n\n               if (0 == range_ptr)\n                  return;\n\n               str1_range_ptr_ = &(range_ptr->range_ref());\n            }\n         }\n\n         inline T value() const\n         {\n            if (\n                 str0_base_ptr_  &&\n                 str1_base_ptr_  &&\n                 str0_range_ptr_ &&\n                 str1_range_ptr_\n               )\n            {\n               binary_node<T>::branch_[0].first->value();\n               binary_node<T>::branch_[1].first->value();\n\n               std::size_t str0_r0 = 0;\n               std::size_t str0_r1 = 0;\n\n               std::size_t str1_r0 = 0;\n               std::size_t str1_r1 = 0;\n\n               range_t& range0 = (*str0_range_ptr_);\n               range_t& range1 = (*str1_range_ptr_);\n\n               if (\n                    range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&\n                    range1(str1_r0, str1_r1, str1_base_ptr_->size())\n                  )\n               {\n                  return Operation::process(\n                                             str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),\n                                             str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)\n                                           );\n               }\n            }\n\n            return std::numeric_limits<T>::quiet_NaN();\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n      private:\n\n         str_sogens_node(str_sogens_node<T,Operation>&);\n         str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);\n\n         str_base_ptr str0_base_ptr_;\n         str_base_ptr str1_base_ptr_;\n         range_ptr    str0_range_ptr_;\n         range_ptr    str1_range_ptr_;\n      };\n\n      template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>\n      class sosos_node : public sosos_base_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef Operation operation_t;\n\n         // variable op variable node\n         explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)\n         : s0_(p0),\n           s1_(p1),\n           s2_(p2)\n         {}\n\n         inline T value() const\n         {\n            return Operation::process(s0_,s1_,s2_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return Operation::type();\n         }\n\n         inline operator_type operation() const\n         {\n            return Operation::operation();\n         }\n\n         inline std::string& s0()\n         {\n            return s0_;\n         }\n\n         inline std::string& s1()\n         {\n            return s1_;\n         }\n\n         inline std::string& s2()\n         {\n            return s2_;\n         }\n\n      protected:\n\n         SType0 s0_;\n         SType1 s1_;\n         SType2 s2_;\n\n      private:\n\n         sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);\n         sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);\n      };\n      #endif\n\n      template <typename T, typename PowOp>\n      class ipow_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef PowOp operation_t;\n\n         explicit ipow_node(const T& v)\n         : v_(v)\n         {}\n\n         inline T value() const\n         {\n            return PowOp::result(v_);\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_ipow;\n         }\n\n      private:\n\n         ipow_node(const ipow_node<T,PowOp>&);\n         ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);\n\n         const T& v_;\n      };\n\n      template <typename T, typename PowOp>\n      class bipow_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr, bool> branch_t;\n         typedef PowOp operation_t;\n\n         explicit bipow_node(expression_ptr brnch)\n         {\n            init_branches<1>(branch_, brnch);\n         }\n\n        ~bipow_node()\n         {\n            cleanup_branches::execute<T,1>(branch_);\n         }\n\n         inline T value() const\n         {\n            return PowOp::result(branch_[0].first->value());\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_ipow;\n         }\n\n      private:\n\n         bipow_node(const bipow_node<T,PowOp>&);\n         bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);\n\n         branch_t branch_[1];\n      };\n\n      template <typename T, typename PowOp>\n      class ipowinv_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef PowOp operation_t;\n\n         explicit ipowinv_node(const T& v)\n         : v_(v)\n         {}\n\n         inline T value() const\n         {\n            return (T(1) / PowOp::result(v_));\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_ipowinv;\n         }\n\n      private:\n\n         ipowinv_node(const ipowinv_node<T,PowOp>&);\n         ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);\n\n         const T& v_;\n      };\n\n      template <typename T, typename PowOp>\n      class bipowninv_node : public expression_node<T>\n      {\n      public:\n\n         typedef expression_node<T>* expression_ptr;\n         typedef std::pair<expression_ptr, bool> branch_t;\n         typedef PowOp operation_t;\n\n         explicit bipowninv_node(expression_ptr brnch)\n         {\n            init_branches<1>(branch_, brnch);\n         }\n\n        ~bipowninv_node()\n         {\n            cleanup_branches::execute<T,1>(branch_);\n         }\n\n         inline T value() const\n         {\n            return (T(1) / PowOp::result(branch_[0].first->value()));\n         }\n\n         inline typename expression_node<T>::node_type type() const\n         {\n            return expression_node<T>::e_ipowinv;\n         }\n\n      private:\n\n         bipowninv_node(const bipowninv_node<T,PowOp>&);\n         bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);\n\n         branch_t branch_[1];\n      };\n\n      template <typename T>\n      inline bool is_vov_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const vov_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_cov_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const cov_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_voc_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const voc_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_cob_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const cob_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_boc_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const boc_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_t0ot1ot2_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_uv_node(const expression_node<T>* node)\n      {\n         return (0 != dynamic_cast<const uv_base_node<T>*>(node));\n      }\n\n      template <typename T>\n      inline bool is_string_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_stringvar == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_range_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_stringvarrng == node->type());\n      }\n\n      template <typename T>\n      inline bool is_const_string_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_stringconst == node->type());\n      }\n\n      template <typename T>\n      inline bool is_const_string_range_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_cstringvarrng == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_assignment_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_strass == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_concat_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_strconcat == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_function_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_strfunction == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_condition_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_strcondition == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_ccondition_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_strccondition == node->type());\n      }\n\n      template <typename T>\n      inline bool is_string_vararg_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_stringvararg == node->type());\n      }\n\n      template <typename T>\n      inline bool is_genricstring_range_node(const expression_node<T>* node)\n      {\n         return node && (expression_node<T>::e_strgenrange == node->type());\n      }\n\n      template <typename T>\n      inline bool is_generally_string_node(const expression_node<T>* node)\n      {\n         if (node)\n         {\n            switch (node->type())\n            {\n               case expression_node<T>::e_stringvar     :\n               case expression_node<T>::e_stringconst   :\n               case expression_node<T>::e_stringvarrng  :\n               case expression_node<T>::e_cstringvarrng :\n               case expression_node<T>::e_strgenrange   :\n               case expression_node<T>::e_strass        :\n               case expression_node<T>::e_strconcat     :\n               case expression_node<T>::e_strfunction   :\n               case expression_node<T>::e_strcondition  :\n               case expression_node<T>::e_strccondition :\n               case expression_node<T>::e_stringvararg  : return true;\n               default                                  : return false;\n            }\n         }\n\n         return false;\n      }\n\n      class node_allocator\n      {\n      public:\n\n         template <typename ResultNode, typename OpType, typename ExprNode>\n         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])\n         {\n            return allocate<ResultNode>(operation,branch[0]);\n         }\n\n         template <typename ResultNode, typename OpType, typename ExprNode>\n         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])\n         {\n            return allocate<ResultNode>(operation,branch[0],branch[1]);\n         }\n\n         template <typename ResultNode, typename OpType, typename ExprNode>\n         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])\n         {\n            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);\n         }\n\n         template <typename ResultNode, typename OpType, typename ExprNode>\n         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])\n         {\n            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);\n         }\n\n         template <typename ResultNode, typename OpType, typename ExprNode>\n         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])\n         {\n            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);\n         }\n\n         template <typename ResultNode, typename OpType, typename ExprNode>\n         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])\n         {\n            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);\n         }\n\n         template <typename node_type>\n         inline expression_node<typename node_type::value_type>* allocate() const\n         {\n            return (new node_type());\n         }\n\n         template <typename node_type,\n                   typename Type,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const\n         {\n            return (new node_type(seq));\n         }\n\n         template <typename node_type, typename T1>\n         inline expression_node<typename node_type::value_type>* allocate(T1& t1) const\n         {\n            return (new node_type(t1));\n         }\n\n         template <typename node_type, typename T1>\n         inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const\n         {\n            return (new node_type(t1));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const\n         {\n            return (new node_type(t1,t2));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2>\n         inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const\n         {\n            return (new node_type(t1,t2));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2>\n         inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const\n         {\n            return (new node_type(t1,t2));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2>\n         inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const\n         {\n            return (new node_type(t1,t2));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2>\n         inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const\n         {\n            return (new node_type(t1,t2));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3>\n         inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const\n         {\n            return (new node_type(t1,t2,t3));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3, typename T4>\n         inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const\n         {\n            return (new node_type(t1,t2,t3,t4));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3>\n         inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const\n         {\n            return (new node_type(t1,t2,t3));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3, typename T4>\n         inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const\n         {\n            return (new node_type(t1,t2,t3,t4));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3, typename T4, typename T5>\n         inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3) const\n         {\n            return (new node_type(t1,t2,t3));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3, const T4& t4) const\n         {\n            return (new node_type(t1,t2,t3,t4));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4, typename T5>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3, const T4& t4,\n                                                                          const T5& t5) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4, typename T5, typename T6>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3, const T4& t4,\n                                                                          const T5& t5, const T6& t6) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5, typename T6, typename T7>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3, const T4& t4,\n                                                                          const T5& t5, const T6& t6,\n                                                                          const T7& t7) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6,t7));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5, typename T6,\n                   typename T7, typename T8>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3, const T4& t4,\n                                                                          const T5& t5, const T6& t6,\n                                                                          const T7& t7, const T8& t8) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6,t7,t8));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5, typename T6,\n                   typename T7, typename T8, typename T9>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,\n                                                                          const T3& t3, const T4& t4,\n                                                                          const T5& t5, const T6& t6,\n                                                                          const T7& t7, const T8& t8,\n                                                                          const T9& t9) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5, typename T6,\n                   typename T7, typename T8,\n                   typename T9, typename T10>\n         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,\n                                                                          const T3& t3, const  T4&  t4,\n                                                                          const T5& t5, const  T6&  t6,\n                                                                          const T7& t7, const  T8&  t8,\n                                                                          const T9& t9, const T10& t10) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2, typename T3>\n         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const\n         {\n            return (new node_type(t1,t2,t3));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4>\n         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,\n                                                                               T3 t3, T4 t4) const\n         {\n            return (new node_type(t1,t2,t3,t4));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5>\n         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,\n                                                                               T3 t3, T4 t4,\n                                                                               T5 t5) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5, typename T6>\n         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,\n                                                                               T3 t3, T4 t4,\n                                                                               T5 t5, T6 t6) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6));\n         }\n\n         template <typename node_type,\n                   typename T1, typename T2,\n                   typename T3, typename T4,\n                   typename T5, typename T6, typename T7>\n         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,\n                                                                               T3 t3, T4 t4,\n                                                                               T5 t5, T6 t6,\n                                                                               T7 t7) const\n         {\n            return (new node_type(t1,t2,t3,t4,t5,t6,t7));\n         }\n\n         template <typename T>\n         void inline free(expression_node<T>*& e) const\n         {\n            delete e;\n            e = 0;\n         }\n      };\n\n      inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)\n      {\n         #define register_op(Symbol,Type,Args)                                               \\\n         m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \\\n\n         register_op(      \"abs\", e_abs     , 1)\n         register_op(     \"acos\", e_acos    , 1)\n         register_op(    \"acosh\", e_acosh   , 1)\n         register_op(     \"asin\", e_asin    , 1)\n         register_op(    \"asinh\", e_asinh   , 1)\n         register_op(     \"atan\", e_atan    , 1)\n         register_op(    \"atanh\", e_atanh   , 1)\n         register_op(     \"ceil\", e_ceil    , 1)\n         register_op(      \"cos\", e_cos     , 1)\n         register_op(     \"cosh\", e_cosh    , 1)\n         register_op(      \"exp\", e_exp     , 1)\n         register_op(    \"expm1\", e_expm1   , 1)\n         register_op(    \"floor\", e_floor   , 1)\n         register_op(      \"log\", e_log     , 1)\n         register_op(    \"log10\", e_log10   , 1)\n         register_op(     \"log2\", e_log2    , 1)\n         register_op(    \"log1p\", e_log1p   , 1)\n         register_op(    \"round\", e_round   , 1)\n         register_op(      \"sin\", e_sin     , 1)\n         register_op(     \"sinc\", e_sinc    , 1)\n         register_op(     \"sinh\", e_sinh    , 1)\n         register_op(      \"sec\", e_sec     , 1)\n         register_op(      \"csc\", e_csc     , 1)\n         register_op(     \"sqrt\", e_sqrt    , 1)\n         register_op(      \"tan\", e_tan     , 1)\n         register_op(     \"tanh\", e_tanh    , 1)\n         register_op(      \"cot\", e_cot     , 1)\n         register_op(  \"rad2deg\", e_r2d     , 1)\n         register_op(  \"deg2rad\", e_d2r     , 1)\n         register_op( \"deg2grad\", e_d2g     , 1)\n         register_op( \"grad2deg\", e_g2d     , 1)\n         register_op(      \"sgn\", e_sgn     , 1)\n         register_op(      \"not\", e_notl    , 1)\n         register_op(      \"erf\", e_erf     , 1)\n         register_op(     \"erfc\", e_erfc    , 1)\n         register_op(     \"ncdf\", e_ncdf    , 1)\n         register_op(     \"frac\", e_frac    , 1)\n         register_op(    \"trunc\", e_trunc   , 1)\n         register_op(    \"atan2\", e_atan2   , 2)\n         register_op(      \"mod\", e_mod     , 2)\n         register_op(     \"logn\", e_logn    , 2)\n         register_op(      \"pow\", e_pow     , 2)\n         register_op(     \"root\", e_root    , 2)\n         register_op(   \"roundn\", e_roundn  , 2)\n         register_op(    \"equal\", e_equal   , 2)\n         register_op(\"not_equal\", e_nequal  , 2)\n         register_op(    \"hypot\", e_hypot   , 2)\n         register_op(      \"shr\", e_shr     , 2)\n         register_op(      \"shl\", e_shl     , 2)\n         register_op(    \"clamp\", e_clamp   , 3)\n         register_op(   \"iclamp\", e_iclamp  , 3)\n         register_op(  \"inrange\", e_inrange , 3)\n         #undef register_op\n      }\n\n   } // namespace details\n\n   class function_traits\n   {\n   public:\n\n      function_traits()\n      : allow_zero_parameters_(false),\n        has_side_effects_(true),\n        min_num_args_(0),\n        max_num_args_(std::numeric_limits<std::size_t>::max())\n      {}\n\n      inline bool& allow_zero_parameters()\n      {\n         return allow_zero_parameters_;\n      }\n\n      inline bool& has_side_effects()\n      {\n         return has_side_effects_;\n      }\n\n      std::size_t& min_num_args()\n      {\n         return min_num_args_;\n      }\n\n      std::size_t& max_num_args()\n      {\n         return max_num_args_;\n      }\n\n   private:\n\n      bool allow_zero_parameters_;\n      bool has_side_effects_;\n      std::size_t min_num_args_;\n      std::size_t max_num_args_;\n   };\n\n   template <typename FunctionType>\n   void enable_zero_parameters(FunctionType& func)\n   {\n      func.allow_zero_parameters() = true;\n\n      if (0 != func.min_num_args())\n      {\n         func.min_num_args() = 0;\n      }\n   }\n\n   template <typename FunctionType>\n   void disable_zero_parameters(FunctionType& func)\n   {\n      func.allow_zero_parameters() = false;\n   }\n\n   template <typename FunctionType>\n   void enable_has_side_effects(FunctionType& func)\n   {\n      func.has_side_effects() = true;\n   }\n\n   template <typename FunctionType>\n   void disable_has_side_effects(FunctionType& func)\n   {\n      func.has_side_effects() = false;\n   }\n\n   template <typename FunctionType>\n   void set_min_num_args(FunctionType& func, const std::size_t& num_args)\n   {\n      func.min_num_args() = num_args;\n\n      if ((0 != func.min_num_args()) && func.allow_zero_parameters())\n         func.allow_zero_parameters() = false;\n   }\n\n   template <typename FunctionType>\n   void set_max_num_args(FunctionType& func, const std::size_t& num_args)\n   {\n      func.max_num_args() = num_args;\n   }\n\n   template <typename T>\n   class ifunction : public function_traits\n   {\n   public:\n\n      explicit ifunction(const std::size_t& pc)\n      : param_count(pc)\n      {}\n\n      virtual ~ifunction()\n      {}\n\n      #define empty_method_body                      \\\n      {                                              \\\n         return std::numeric_limits<T>::quiet_NaN(); \\\n      }                                              \\\n\n      inline virtual T operator() ()\n      empty_method_body\n\n       inline virtual T operator() (const T&)\n      empty_method_body\n\n       inline virtual T operator() (const T&,const T&)\n      empty_method_body\n\n       inline virtual T operator() (const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                  const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,\n                                   const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)\n      empty_method_body\n\n      #undef empty_method_body\n\n      std::size_t param_count;\n   };\n\n   template <typename T>\n   class ivararg_function : public function_traits\n   {\n   public:\n\n      virtual ~ivararg_function()\n      {}\n\n      inline virtual T operator() (const std::vector<T>&)\n      {\n         exprtk_debug((\"ivararg_function::operator() - Operator has not been overridden.\\n\"));\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n   };\n\n   template <typename T>\n   class igeneric_function : public function_traits\n   {\n   public:\n\n      enum return_type\n      {\n         e_rtrn_scalar = 0,\n         e_rtrn_string = 1\n      };\n\n      typedef T type;\n      typedef type_store<T> generic_type;\n      typedef typename generic_type::parameter_list parameter_list_t;\n\n      igeneric_function(const std::string& param_seq = \"\", const return_type rtr_type = e_rtrn_scalar)\n      : parameter_sequence(param_seq),\n        rtrn_type(rtr_type)\n      {}\n\n      virtual ~igeneric_function()\n      {}\n\n      #define igeneric_function_empty_body(N)        \\\n      {                                              \\\n         exprtk_debug((\"igeneric_function::operator() - Operator has not been overridden. [\"#N\"]\\n\")); \\\n         return std::numeric_limits<T>::quiet_NaN(); \\\n      }                                              \\\n\n      // f(i_0,i_1,....,i_N) --> Scalar\n      inline virtual T operator() (parameter_list_t)\n      igeneric_function_empty_body(1)\n\n      // f(i_0,i_1,....,i_N) --> String\n      inline virtual T operator() (std::string&, parameter_list_t)\n      igeneric_function_empty_body(2)\n\n      // f(psi,i_0,i_1,....,i_N) --> Scalar\n      inline virtual T operator() (const std::size_t&, parameter_list_t)\n      igeneric_function_empty_body(3)\n\n      // f(psi,i_0,i_1,....,i_N) --> String\n      inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)\n      igeneric_function_empty_body(4)\n\n      std::string parameter_sequence;\n      return_type rtrn_type;\n   };\n\n   template <typename T> class parser;\n   template <typename T> class expression_helper;\n\n   template <typename T>\n   class symbol_table\n   {\n   public:\n\n      typedef T (*ff00_functor)();\n      typedef T (*ff01_functor)(T);\n      typedef T (*ff02_functor)(T,T);\n      typedef T (*ff03_functor)(T,T,T);\n      typedef T (*ff04_functor)(T,T,T,T);\n      typedef T (*ff05_functor)(T,T,T,T,T);\n      typedef T (*ff06_functor)(T,T,T,T,T,T);\n      typedef T (*ff07_functor)(T,T,T,T,T,T,T);\n      typedef T (*ff08_functor)(T,T,T,T,T,T,T,T);\n      typedef T (*ff09_functor)(T,T,T,T,T,T,T,T,T);\n      typedef T (*ff10_functor)(T,T,T,T,T,T,T,T,T,T);\n      typedef T (*ff11_functor)(T,T,T,T,T,T,T,T,T,T,T);\n      typedef T (*ff12_functor)(T,T,T,T,T,T,T,T,T,T,T,T);\n      typedef T (*ff13_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T);\n      typedef T (*ff14_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T,T);\n      typedef T (*ff15_functor)(T,T,T,T,T,T,T,T,T,T,T,T,T,T,T);\n\n   protected:\n\n       struct freefunc00 : public exprtk::ifunction<T>\n       {\n          using exprtk::ifunction<T>::operator();\n\n          freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}\n          inline T operator() ()\n          { return f(); }\n          ff00_functor f;\n       };\n\n      struct freefunc01 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}\n         inline T operator() (const T& v0)\n         { return f(v0); }\n         ff01_functor f;\n      };\n\n      struct freefunc02 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}\n         inline T operator() (const T& v0, const T& v1)\n         { return f(v0, v1); }\n         ff02_functor f;\n      };\n\n      struct freefunc03 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2)\n         { return f(v0, v1, v2); }\n         ff03_functor f;\n      };\n\n      struct freefunc04 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)\n         { return f(v0, v1, v2, v3); }\n         ff04_functor f;\n      };\n\n      struct freefunc05 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)\n         { return f(v0, v1, v2, v3, v4); }\n         ff05_functor f;\n      };\n\n      struct freefunc06 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)\n         { return f(v0, v1, v2, v3, v4, v5); }\n         ff06_functor f;\n      };\n\n      struct freefunc07 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,\n                              const T& v5, const T& v6)\n         { return f(v0, v1, v2, v3, v4, v5, v6); }\n         ff07_functor f;\n      };\n\n      struct freefunc08 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,\n                              const T& v5, const T& v6, const T& v7)\n         { return f(v0, v1, v2, v3, v4, v5, v6, v7); }\n         ff08_functor f;\n      };\n\n      struct freefunc09 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,\n                              const T& v5, const T& v6, const T& v7, const T& v8)\n         { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }\n         ff09_functor f;\n      };\n\n      struct freefunc10 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,\n                              const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)\n         { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }\n         ff10_functor f;\n      };\n\n      struct freefunc11 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}\n         inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,\n                              const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)\n         { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }\n         ff11_functor f;\n      };\n\n      struct freefunc12 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}\n         inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,\n                              const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,\n                              const T& v10, const T& v11)\n         { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }\n         ff12_functor f;\n      };\n\n      struct freefunc13 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}\n         inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,\n                              const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,\n                              const T& v10, const T& v11, const T& v12)\n         { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }\n         ff13_functor f;\n      };\n\n      struct freefunc14 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}\n         inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,\n                              const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,\n                              const T& v10, const T& v11, const T& v12, const T& v13)\n         { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }\n         ff14_functor f;\n      };\n\n      struct freefunc15 : public exprtk::ifunction<T>\n      {\n         using exprtk::ifunction<T>::operator();\n\n         freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}\n         inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,\n                              const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,\n                              const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)\n         { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }\n         ff15_functor f;\n      };\n\n      template <typename Type, typename RawType>\n      struct type_store\n      {\n         typedef details::expression_node<T>*        expression_ptr;\n         typedef typename details::variable_node<T>  variable_node_t;\n         typedef ifunction<T>                        ifunction_t;\n         typedef ivararg_function<T>                 ivararg_function_t;\n         typedef igeneric_function<T>                igeneric_function_t;\n         typedef details::vector_holder<T>           vector_t;\n         #ifndef exprtk_disable_string_capabilities\n         typedef typename details::stringvar_node<T> stringvar_node_t;\n         #endif\n\n         typedef Type type_t;\n         typedef type_t* type_ptr;\n         typedef std::pair<bool,type_ptr> type_pair_t;\n         typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;\n         typedef typename type_map_t::iterator tm_itr_t;\n         typedef typename type_map_t::const_iterator tm_const_itr_t;\n\n         enum { lut_size = 256 };\n\n         type_map_t  map;\n         std::size_t size;\n\n         type_store()\n         : size(0)\n         {}\n\n         inline bool symbol_exists(const std::string& symbol_name) const\n         {\n            if (symbol_name.empty())\n               return false;\n            else if (map.end() != map.find(symbol_name))\n               return true;\n            else\n               return false;\n         }\n\n         template <typename PtrType>\n         inline std::string entity_name(const PtrType& ptr) const\n         {\n            if (map.empty())\n               return std::string();\n\n            tm_const_itr_t itr = map.begin();\n\n            while (map.end() != itr)\n            {\n               if (itr->second.second == ptr)\n               {\n                  return itr->first;\n               }\n               else\n                  ++itr;\n            }\n\n            return std::string();\n         }\n\n         inline bool is_constant(const std::string& symbol_name) const\n         {\n            if (symbol_name.empty())\n               return false;\n            else\n            {\n               const tm_const_itr_t itr = map.find(symbol_name);\n\n               if (map.end() == itr)\n                  return false;\n               else\n                  return (*itr).second.first;\n            }\n         }\n\n         template <typename Tie, typename RType>\n         inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)\n         {\n            if (symbol_name.size() > 1)\n            {\n               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)\n               {\n                  if (details::imatch(symbol_name, details::reserved_symbols[i]))\n                  {\n                     return false;\n                  }\n               }\n            }\n\n            const tm_itr_t itr = map.find(symbol_name);\n\n            if (map.end() == itr)\n            {\n               map[symbol_name] = Tie::make(t,is_const);\n               ++size;\n            }\n\n            return true;\n         }\n\n         struct tie_array\n         {\n            static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)\n            {\n               return std::make_pair(is_const, new vector_t(v.first, v.second));\n            }\n         };\n\n         struct tie_stdvec\n         {\n            template <typename Allocator>\n            static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)\n            {\n               return std::make_pair(is_const, new vector_t(v));\n            }\n         };\n\n         struct tie_vecview\n         {\n            static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)\n            {\n               return std::make_pair(is_const, new vector_t(v));\n            }\n         };\n\n         struct tie_stddeq\n         {\n            template <typename Allocator>\n            static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)\n            {\n               return std::make_pair(is_const, new vector_t(v));\n            }\n         };\n\n         template <std::size_t v_size>\n         inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)\n         {\n            return add_impl<tie_array,std::pair<T*,std::size_t> >\n                      (symbol_name, std::make_pair(v,v_size), is_const);\n         }\n\n         inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)\n         {\n            return add_impl<tie_array,std::pair<T*,std::size_t> >\n                     (symbol_name, std::make_pair(v,v_size), is_const);\n         }\n\n         template <typename Allocator>\n         inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)\n         {\n            return add_impl<tie_stdvec,std::vector<T,Allocator>&>\n                      (symbol_name, v, is_const);\n         }\n\n         inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)\n         {\n            return add_impl<tie_vecview,exprtk::vector_view<T>&>\n                      (symbol_name, v, is_const);\n         }\n\n         template <typename Allocator>\n         inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)\n         {\n            return add_impl<tie_stddeq,std::deque<T,Allocator>&>\n                      (symbol_name, v, is_const);\n         }\n\n         inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)\n         {\n            struct tie\n            {\n               static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)\n               {\n                  return std::make_pair(is_const, new variable_node_t(t));\n               }\n\n               #ifndef exprtk_disable_string_capabilities\n               static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)\n               {\n                  return std::make_pair(is_const, new stringvar_node_t(t));\n               }\n               #endif\n\n               static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)\n               {\n                  return std::make_pair(is_constant,&t);\n               }\n\n               static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)\n               {\n                  return std::make_pair(is_const,&t);\n               }\n\n               static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)\n               {\n                  return std::make_pair(is_constant,&t);\n               }\n            };\n\n            const tm_itr_t itr = map.find(symbol_name);\n\n            if (map.end() == itr)\n            {\n               map[symbol_name] = tie::make(t,is_const);\n               ++size;\n            }\n\n            return true;\n         }\n\n         inline type_ptr get(const std::string& symbol_name) const\n         {\n            const tm_const_itr_t itr = map.find(symbol_name);\n\n            if (map.end() == itr)\n               return reinterpret_cast<type_ptr>(0);\n            else\n               return itr->second.second;\n         }\n\n         template <typename TType, typename TRawType, typename PtrType>\n         struct ptr_match\n         {\n            static inline bool test(const PtrType, const void*)\n            {\n               return false;\n            }\n         };\n\n         template <typename TType, typename TRawType>\n         struct ptr_match<TType,TRawType,variable_node_t*>\n         {\n            static inline bool test(const variable_node_t* p, const void* ptr)\n            {\n               exprtk_debug((\"ptr_match::test() - %p <--> %p\\n\",(void*)(&(p->ref())),ptr));\n               return (&(p->ref()) == ptr);\n            }\n         };\n\n         inline type_ptr get_from_varptr(const void* ptr) const\n         {\n            tm_const_itr_t itr = map.begin();\n\n            while (map.end() != itr)\n            {\n               type_ptr ret_ptr = itr->second.second;\n\n               if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))\n               {\n                  return ret_ptr;\n               }\n\n               ++itr;\n            }\n\n            return type_ptr(0);\n         }\n\n         inline bool remove(const std::string& symbol_name, const bool delete_node = true)\n         {\n            const tm_itr_t itr = map.find(symbol_name);\n\n            if (map.end() != itr)\n            {\n               struct deleter\n               {\n                  static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }\n                  static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }\n                  #ifndef exprtk_disable_string_capabilities\n                  static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }\n                  #endif\n                  static inline void process(std::pair<bool,function_t*>&)         {                  }\n               };\n\n               if (delete_node)\n               {\n                  deleter::process((*itr).second);\n               }\n\n               map.erase(itr);\n               --size;\n\n               return true;\n            }\n            else\n               return false;\n         }\n\n         inline RawType& type_ref(const std::string& symbol_name)\n         {\n            struct init_type\n            {\n               static inline double set(double)           { return (0.0);           }\n               static inline double set(long double)      { return (0.0);           }\n               static inline float  set(float)            { return (0.0f);          }\n               static inline std::string set(std::string) { return std::string(\"\"); }\n            };\n\n            static RawType null_type = init_type::set(RawType());\n\n            const tm_const_itr_t itr = map.find(symbol_name);\n\n            if (map.end() == itr)\n               return null_type;\n            else\n               return itr->second.second->ref();\n         }\n\n         inline void clear(const bool delete_node = true)\n         {\n            struct deleter\n            {\n               static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }\n               static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }\n               static inline void process(std::pair<bool,function_t*>&)         {                  }\n               #ifndef exprtk_disable_string_capabilities\n               static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }\n               #endif\n            };\n\n            if (!map.empty())\n            {\n               if (delete_node)\n               {\n                  tm_itr_t itr = map.begin();\n                  tm_itr_t end = map.end  ();\n\n                  while (end != itr)\n                  {\n                     deleter::process((*itr).second);\n                     ++itr;\n                  }\n               }\n\n               map.clear();\n            }\n\n            size = 0;\n         }\n\n         template <typename Allocator,\n                   template <typename, typename> class Sequence>\n         inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const\n         {\n            std::size_t count = 0;\n\n            if (!map.empty())\n            {\n               tm_const_itr_t itr = map.begin();\n               tm_const_itr_t end = map.end  ();\n\n               while (end != itr)\n               {\n                  list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));\n                  ++itr;\n                  ++count;\n               }\n            }\n\n            return count;\n         }\n\n         template <typename Allocator,\n                   template <typename, typename> class Sequence>\n         inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const\n         {\n            std::size_t count = 0;\n\n            if (!map.empty())\n            {\n               tm_const_itr_t itr = map.begin();\n               tm_const_itr_t end = map.end  ();\n\n               while (end != itr)\n               {\n                  vlist.push_back((*itr).first);\n                  ++itr;\n                  ++count;\n               }\n            }\n\n            return count;\n         }\n      };\n\n      typedef details::expression_node<T>* expression_ptr;\n      typedef typename details::variable_node<T> variable_t;\n      typedef typename details::vector_holder<T> vector_holder_t;\n      typedef variable_t* variable_ptr;\n      #ifndef exprtk_disable_string_capabilities\n      typedef typename details::stringvar_node<T> stringvar_t;\n      typedef stringvar_t* stringvar_ptr;\n      #endif\n      typedef ifunction        <T> function_t;\n      typedef ivararg_function <T> vararg_function_t;\n      typedef igeneric_function<T> generic_function_t;\n      typedef function_t* function_ptr;\n      typedef vararg_function_t*  vararg_function_ptr;\n      typedef generic_function_t* generic_function_ptr;\n\n      static const std::size_t lut_size = 256;\n\n      // Symbol Table Holder\n      struct control_block\n      {\n         struct st_data\n         {\n            type_store<typename details::variable_node<T>,T> variable_store;\n            #ifndef exprtk_disable_string_capabilities\n            type_store<typename details::stringvar_node<T>,std::string> stringvar_store;\n            #endif\n            type_store<ifunction<T>,ifunction<T> > function_store;\n            type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;\n            type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;\n            type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;\n            type_store<vector_holder_t,vector_holder_t> vector_store;\n\n            st_data()\n            {\n               for (std::size_t i = 0; i < details::reserved_words_size; ++i)\n               {\n                  reserved_symbol_table_.insert(details::reserved_words[i]);\n               }\n\n               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)\n               {\n                  reserved_symbol_table_.insert(details::reserved_symbols[i]);\n               }\n            }\n\n           ~st_data()\n            {\n               for (std::size_t i = 0; i < free_function_list_.size(); ++i)\n               {\n                  delete free_function_list_[i];\n               }\n            }\n\n            inline bool is_reserved_symbol(const std::string& symbol) const\n            {\n               return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));\n            }\n\n            static inline st_data* create()\n            {\n               return (new st_data);\n            }\n\n            static inline void destroy(st_data*& sd)\n            {\n               delete sd;\n               sd = reinterpret_cast<st_data*>(0);\n            }\n\n            std::list<T>               local_symbol_list_;\n            std::list<std::string>     local_stringvar_list_;\n            std::set<std::string>      reserved_symbol_table_;\n            std::vector<ifunction<T>*> free_function_list_;\n         };\n\n         control_block()\n         : ref_count(1),\n           data_(st_data::create())\n         {}\n\n         control_block(st_data* data)\n         : ref_count(1),\n           data_(data)\n         {}\n\n        ~control_block()\n         {\n            if (data_ && (0 == ref_count))\n            {\n               st_data::destroy(data_);\n            }\n         }\n\n         static inline control_block* create()\n         {\n            return (new control_block);\n         }\n\n         template <typename SymTab>\n         static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)\n         {\n            if (cntrl_blck)\n            {\n               if (\n                    (0 !=   cntrl_blck->ref_count) &&\n                    (0 == --cntrl_blck->ref_count)\n                  )\n               {\n                  if (sym_tab)\n                     sym_tab->clear();\n\n                  delete cntrl_blck;\n               }\n\n               cntrl_blck = 0;\n            }\n         }\n\n         std::size_t ref_count;\n         st_data* data_;\n      };\n\n   public:\n\n      symbol_table()\n      : control_block_(control_block::create())\n      {\n         clear();\n      }\n\n     ~symbol_table()\n      {\n         control_block::destroy(control_block_,this);\n      }\n\n      symbol_table(const symbol_table<T>& st)\n      {\n         control_block_ = st.control_block_;\n         control_block_->ref_count++;\n      }\n\n      inline symbol_table<T>& operator=(const symbol_table<T>& st)\n      {\n         if (this != &st)\n         {\n            control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));\n\n            control_block_ = st.control_block_;\n            control_block_->ref_count++;\n         }\n\n         return (*this);\n      }\n\n      inline bool operator==(const symbol_table<T>& st)\n      {\n         return (this == &st) || (control_block_ == st.control_block_);\n      }\n\n      inline void clear_variables(const bool delete_node = true)\n      {\n         local_data().variable_store.clear(delete_node);\n      }\n\n      inline void clear_functions()\n      {\n         local_data().function_store.clear();\n      }\n\n      inline void clear_strings()\n      {\n         #ifndef exprtk_disable_string_capabilities\n         local_data().stringvar_store.clear();\n         #endif\n      }\n\n      inline void clear_vectors()\n      {\n         local_data().vector_store.clear();\n      }\n\n      inline void clear_local_constants()\n      {\n         local_data().local_symbol_list_.clear();\n      }\n\n      inline void clear()\n      {\n         if (!valid()) return;\n         clear_variables      ();\n         clear_functions      ();\n         clear_strings        ();\n         clear_vectors        ();\n         clear_local_constants();\n      }\n\n      inline std::size_t variable_count() const\n      {\n         if (valid())\n            return local_data().variable_store.size;\n         else\n            return 0;\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline std::size_t stringvar_count() const\n      {\n         if (valid())\n            return local_data().stringvar_store.size;\n         else\n            return 0;\n      }\n      #endif\n\n      inline std::size_t function_count() const\n      {\n         if (valid())\n            return local_data().function_store.size;\n         else\n            return 0;\n      }\n\n      inline std::size_t vector_count() const\n      {\n         if (valid())\n            return local_data().vector_store.size;\n         else\n            return 0;\n      }\n\n      inline variable_ptr get_variable(const std::string& variable_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<variable_ptr>(0);\n         else if (!valid_symbol(variable_name))\n            return reinterpret_cast<variable_ptr>(0);\n         else\n            return local_data().variable_store.get(variable_name);\n      }\n\n      inline variable_ptr get_variable(const T& var_ref) const\n      {\n         if (!valid())\n            return reinterpret_cast<variable_ptr>(0);\n         else\n            return local_data().variable_store.get_from_varptr(\n                                                  reinterpret_cast<const void*>(&var_ref));\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline stringvar_ptr get_stringvar(const std::string& string_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<stringvar_ptr>(0);\n         else if (!valid_symbol(string_name))\n            return reinterpret_cast<stringvar_ptr>(0);\n         else\n            return local_data().stringvar_store.get(string_name);\n      }\n      #endif\n\n      inline function_ptr get_function(const std::string& function_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<function_ptr>(0);\n         else if (!valid_symbol(function_name))\n            return reinterpret_cast<function_ptr>(0);\n         else\n            return local_data().function_store.get(function_name);\n      }\n\n      inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<vararg_function_ptr>(0);\n         else if (!valid_symbol(vararg_function_name))\n            return reinterpret_cast<vararg_function_ptr>(0);\n         else\n            return local_data().vararg_function_store.get(vararg_function_name);\n      }\n\n      inline generic_function_ptr get_generic_function(const std::string& function_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<generic_function_ptr>(0);\n         else if (!valid_symbol(function_name))\n            return reinterpret_cast<generic_function_ptr>(0);\n         else\n            return local_data().generic_function_store.get(function_name);\n      }\n\n      inline generic_function_ptr get_string_function(const std::string& function_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<generic_function_ptr>(0);\n         else if (!valid_symbol(function_name))\n            return reinterpret_cast<generic_function_ptr>(0);\n         else\n            return local_data().string_function_store.get(function_name);\n      }\n\n      typedef vector_holder_t* vector_holder_ptr;\n\n      inline vector_holder_ptr get_vector(const std::string& vector_name) const\n      {\n         if (!valid())\n            return reinterpret_cast<vector_holder_ptr>(0);\n         else if (!valid_symbol(vector_name))\n            return reinterpret_cast<vector_holder_ptr>(0);\n         else\n            return local_data().vector_store.get(vector_name);\n      }\n\n      inline T& variable_ref(const std::string& symbol_name)\n      {\n         static T null_var = T(0);\n         if (!valid())\n            return null_var;\n         else if (!valid_symbol(symbol_name))\n            return null_var;\n         else\n            return local_data().variable_store.type_ref(symbol_name);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline std::string& stringvar_ref(const std::string& symbol_name)\n      {\n         static std::string null_stringvar;\n         if (!valid())\n            return null_stringvar;\n         else if (!valid_symbol(symbol_name))\n            return null_stringvar;\n         else\n            return local_data().stringvar_store.type_ref(symbol_name);\n      }\n      #endif\n\n      inline bool is_constant_node(const std::string& symbol_name) const\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(symbol_name))\n            return false;\n         else\n            return local_data().variable_store.is_constant(symbol_name);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline bool is_constant_string(const std::string& symbol_name) const\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(symbol_name))\n            return false;\n         else if (!local_data().stringvar_store.symbol_exists(symbol_name))\n            return false;\n         else\n            return local_data().stringvar_store.is_constant(symbol_name);\n      }\n      #endif\n\n      inline bool create_variable(const std::string& variable_name, const T& value = T(0))\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(variable_name))\n            return false;\n         else if (symbol_exists(variable_name))\n            return false;\n\n         local_data().local_symbol_list_.push_back(value);\n         T& t = local_data().local_symbol_list_.back();\n\n         return add_variable(variable_name,t);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(\"\"))\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(stringvar_name))\n            return false;\n         else if (symbol_exists(stringvar_name))\n            return false;\n\n         local_data().local_stringvar_list_.push_back(value);\n         std::string& s = local_data().local_stringvar_list_.back();\n\n         return add_stringvar(stringvar_name,s);\n      }\n      #endif\n\n      inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(variable_name))\n            return false;\n         else if (symbol_exists(variable_name))\n            return false;\n         else\n            return local_data().variable_store.add(variable_name,t,is_constant);\n      }\n\n      inline bool add_constant(const std::string& constant_name, const T& value)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(constant_name))\n            return false;\n         else if (symbol_exists(constant_name))\n            return false;\n\n         local_data().local_symbol_list_.push_back(value);\n         T& t = local_data().local_symbol_list_.back();\n\n         return add_variable(constant_name,t,true);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(stringvar_name))\n            return false;\n         else if (symbol_exists(stringvar_name))\n            return false;\n         else\n            return local_data().stringvar_store.add(stringvar_name,s,is_constant);\n      }\n      #endif\n\n      inline bool add_function(const std::string& function_name, function_t& function)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(function_name))\n            return false;\n         else if (symbol_exists(function_name))\n            return false;\n         else\n            return local_data().function_store.add(function_name,function);\n      }\n\n      inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(vararg_function_name))\n            return false;\n         else if (symbol_exists(vararg_function_name))\n            return false;\n         else\n            return local_data().vararg_function_store.add(vararg_function_name,vararg_function);\n      }\n\n      inline bool add_function(const std::string& function_name, generic_function_t& function)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(function_name))\n            return false;\n         else if (symbol_exists(function_name))\n            return false;\n         else if (std::string::npos != function.parameter_sequence.find_first_not_of(\"STVZ*?|\"))\n            return false;\n         else if (generic_function_t::e_rtrn_scalar == function.rtrn_type)\n            return local_data().generic_function_store.add(function_name,function);\n         else if (generic_function_t::e_rtrn_string == function.rtrn_type)\n            return local_data().string_function_store.add(function_name, function);\n         else\n            return false;\n      }\n\n      #define exprtk_define_freefunction(NN)                                                \\\n      inline bool add_function(const std::string& function_name, ff##NN##_functor function) \\\n      {                                                                                     \\\n         if (!valid())                                                                      \\\n            return false;                                                                   \\\n         else if (!valid_symbol(function_name))                                             \\\n            return false;                                                                   \\\n         else if (symbol_exists(function_name))                                             \\\n            return false;                                                                   \\\n                                                                                            \\\n         exprtk::ifunction<T>* ifunc = new freefunc##NN(function);                          \\\n                                                                                            \\\n         local_data().free_function_list_.push_back(ifunc);                                 \\\n                                                                                            \\\n         return add_function(function_name,(*local_data().free_function_list_.back()));     \\\n      }                                                                                     \\\n\n      exprtk_define_freefunction(00) exprtk_define_freefunction(01)\n      exprtk_define_freefunction(02) exprtk_define_freefunction(03)\n      exprtk_define_freefunction(04) exprtk_define_freefunction(05)\n      exprtk_define_freefunction(06) exprtk_define_freefunction(07)\n      exprtk_define_freefunction(08) exprtk_define_freefunction(09)\n      exprtk_define_freefunction(10) exprtk_define_freefunction(11)\n      exprtk_define_freefunction(12) exprtk_define_freefunction(13)\n      exprtk_define_freefunction(14) exprtk_define_freefunction(15)\n\n      #undef exprtk_define_freefunction\n\n      inline bool add_reserved_function(const std::string& function_name, function_t& function)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(function_name,false))\n            return false;\n         else if (symbol_exists(function_name,false))\n            return false;\n         else\n            return local_data().function_store.add(function_name,function);\n      }\n\n      inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(vararg_function_name,false))\n            return false;\n         else if (symbol_exists(vararg_function_name,false))\n            return false;\n         else\n            return local_data().vararg_function_store.add(vararg_function_name,vararg_function);\n      }\n\n      inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(function_name,false))\n            return false;\n         else if (symbol_exists(function_name,false))\n            return false;\n         else if (std::string::npos != function.parameter_sequence.find_first_not_of(\"STV*?|\"))\n            return false;\n         else if (generic_function_t::e_rtrn_scalar == function.rtrn_type)\n            return local_data().generic_function_store.add(function_name,function);\n         else if (generic_function_t::e_rtrn_string == function.rtrn_type)\n            return local_data().string_function_store.add(function_name, function);\n         else\n            return false;\n      }\n\n      template <std::size_t N>\n      inline bool add_vector(const std::string& vector_name, T (&v)[N])\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(vector_name))\n            return false;\n         else if (symbol_exists(vector_name))\n            return false;\n         else\n            return local_data().vector_store.add(vector_name,v);\n      }\n\n      inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(vector_name))\n            return false;\n         else if (symbol_exists(vector_name))\n            return false;\n         else if (0 == v_size)\n            return false;\n         else\n            return local_data().vector_store.add(vector_name,v,v_size);\n      }\n\n      template <typename Allocator>\n      inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(vector_name))\n            return false;\n         else if (symbol_exists(vector_name))\n            return false;\n         else if (0 == v.size())\n            return false;\n         else\n            return local_data().vector_store.add(vector_name,v);\n      }\n\n      inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(vector_name))\n            return false;\n         else if (symbol_exists(vector_name))\n            return false;\n         else if (0 == v.size())\n            return false;\n         else\n            return local_data().vector_store.add(vector_name,v);\n      }\n\n      inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().variable_store.remove(variable_name, delete_node);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline bool remove_stringvar(const std::string& string_name)\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().stringvar_store.remove(string_name);\n      }\n      #endif\n\n      inline bool remove_function(const std::string& function_name)\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().function_store.remove(function_name);\n      }\n\n      inline bool remove_vararg_function(const std::string& vararg_function_name)\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().vararg_function_store.remove(vararg_function_name);\n      }\n\n      inline bool remove_vector(const std::string& vector_name)\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().vector_store.remove(vector_name);\n      }\n\n      inline bool add_constants()\n      {\n         return add_pi      () &&\n                add_epsilon () &&\n                add_infinity() ;\n      }\n\n      inline bool add_pi()\n      {\n         const typename details::numeric::details::number_type<T>::type num_type;\n         static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);\n         return add_constant(\"pi\",local_pi);\n      }\n\n      inline bool add_epsilon()\n      {\n         static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();\n         return add_constant(\"epsilon\",local_epsilon);\n      }\n\n      inline bool add_infinity()\n      {\n         static const T local_infinity = std::numeric_limits<T>::infinity();\n         return add_constant(\"inf\",local_infinity);\n      }\n\n      template <typename Package>\n      inline bool add_package(Package& package)\n      {\n         return package.register_package(*this);\n      }\n\n      template <typename Allocator,\n                template <typename, typename> class Sequence>\n      inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const\n      {\n         if (!valid())\n            return 0;\n         else\n            return local_data().variable_store.get_list(vlist);\n      }\n\n      template <typename Allocator,\n                template <typename, typename> class Sequence>\n      inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const\n      {\n         if (!valid())\n            return 0;\n         else\n            return local_data().variable_store.get_list(vlist);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      template <typename Allocator,\n                template <typename, typename> class Sequence>\n      inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const\n      {\n         if (!valid())\n            return 0;\n         else\n            return local_data().stringvar_store.get_list(svlist);\n      }\n\n      template <typename Allocator,\n                template <typename, typename> class Sequence>\n      inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const\n      {\n         if (!valid())\n            return 0;\n         else\n            return local_data().stringvar_store.get_list(svlist);\n      }\n      #endif\n\n      template <typename Allocator,\n                template <typename, typename> class Sequence>\n      inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const\n      {\n         if (!valid())\n            return 0;\n         else\n            return local_data().vector_store.get_list(vlist);\n      }\n\n      inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const\n      {\n         /*\n            Function will return true if symbol_name exists as either a\n            reserved symbol, variable, stringvar or function name in any\n            of the type stores.\n         */\n         if (!valid())\n            return false;\n         else if (local_data().variable_store.symbol_exists(symbol_name))\n            return true;\n         #ifndef exprtk_disable_string_capabilities\n         else if (local_data().stringvar_store.symbol_exists(symbol_name))\n            return true;\n         #endif\n         else if (local_data().function_store.symbol_exists(symbol_name))\n            return true;\n         else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))\n            return true;\n         else\n            return false;\n      }\n\n      inline bool is_variable(const std::string& variable_name) const\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().variable_store.symbol_exists(variable_name);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline bool is_stringvar(const std::string& stringvar_name) const\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().stringvar_store.symbol_exists(stringvar_name);\n      }\n\n      inline bool is_conststr_stringvar(const std::string& symbol_name) const\n      {\n         if (!valid())\n            return false;\n         else if (!valid_symbol(symbol_name))\n            return false;\n         else if (!local_data().stringvar_store.symbol_exists(symbol_name))\n            return false;\n\n         return (\n                  local_data().stringvar_store.symbol_exists(symbol_name) ||\n                  local_data().stringvar_store.is_constant  (symbol_name)\n                );\n      }\n      #endif\n\n      inline bool is_function(const std::string& function_name) const\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().function_store.symbol_exists(function_name);\n      }\n\n      inline bool is_vararg_function(const std::string& vararg_function_name) const\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().vararg_function_store.symbol_exists(vararg_function_name);\n      }\n\n      inline bool is_vector(const std::string& vector_name) const\n      {\n         if (!valid())\n            return false;\n         else\n            return local_data().vector_store.symbol_exists(vector_name);\n      }\n\n      inline std::string get_variable_name(const expression_ptr& ptr) const\n      {\n         return local_data().variable_store.entity_name(ptr);\n      }\n\n      inline std::string get_vector_name(const vector_holder_ptr& ptr) const\n      {\n         return local_data().vector_store.entity_name(ptr);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline std::string get_stringvar_name(const expression_ptr& ptr) const\n      {\n         return local_data().stringvar_store.entity_name(ptr);\n      }\n\n      inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const\n      {\n         return local_data().stringvar_store.entity_name(ptr);\n      }\n      #endif\n\n      inline bool valid() const\n      {\n         // Symbol table sanity check.\n         return control_block_ && control_block_->data_;\n      }\n\n      inline void load_from(const symbol_table<T>& st)\n      {\n         {\n            std::vector<std::string> name_list;\n\n            st.local_data().function_store.get_list(name_list);\n\n            if (!name_list.empty())\n            {\n               for (std::size_t i = 0; i < name_list.size(); ++i)\n               {\n                  exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);\n                  add_function(name_list[i],ifunc);\n               }\n            }\n         }\n\n         {\n            std::vector<std::string> name_list;\n\n            st.local_data().vararg_function_store.get_list(name_list);\n\n            if (!name_list.empty())\n            {\n               for (std::size_t i = 0; i < name_list.size(); ++i)\n               {\n                  exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);\n                  add_function(name_list[i],ivafunc);\n               }\n            }\n         }\n\n         {\n            std::vector<std::string> name_list;\n\n            st.local_data().generic_function_store.get_list(name_list);\n\n            if (!name_list.empty())\n            {\n               for (std::size_t i = 0; i < name_list.size(); ++i)\n               {\n                  exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);\n                  add_function(name_list[i],ifunc);\n               }\n            }\n         }\n\n         {\n            std::vector<std::string> name_list;\n\n            st.local_data().string_function_store.get_list(name_list);\n\n            if (!name_list.empty())\n            {\n               for (std::size_t i = 0; i < name_list.size(); ++i)\n               {\n                  exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);\n                  add_function(name_list[i],ifunc);\n               }\n            }\n         }\n      }\n\n   private:\n\n      inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const\n      {\n         if (symbol.empty())\n            return false;\n         else if (!details::is_letter(symbol[0]))\n            return false;\n         else if (symbol.size() > 1)\n         {\n            for (std::size_t i = 1; i < symbol.size(); ++i)\n            {\n               if (\n                    !details::is_letter_or_digit(symbol[i]) &&\n                    ('_' != symbol[i])\n                  )\n               {\n                  if (('.' == symbol[i]) && (i < (symbol.size() - 1)))\n                     continue;\n                  else\n                     return false;\n               }\n            }\n         }\n\n         return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;\n      }\n\n      inline bool valid_function(const std::string& symbol) const\n      {\n         if (symbol.empty())\n            return false;\n         else if (!details::is_letter(symbol[0]))\n            return false;\n         else if (symbol.size() > 1)\n         {\n            for (std::size_t i = 1; i < symbol.size(); ++i)\n            {\n               if (\n                    !details::is_letter_or_digit(symbol[i]) &&\n                    ('_' != symbol[i])\n                  )\n               {\n                  if (('.' == symbol[i]) && (i < (symbol.size() - 1)))\n                     continue;\n                  else\n                     return false;\n               }\n            }\n         }\n\n         return true;\n      }\n\n      typedef typename control_block::st_data local_data_t;\n\n      inline local_data_t& local_data()\n      {\n         return *(control_block_->data_);\n      }\n\n      inline const local_data_t& local_data() const\n      {\n         return *(control_block_->data_);\n      }\n\n      control_block* control_block_;\n\n      friend class parser<T>;\n   };\n\n   template <typename T>\n   class function_compositor;\n\n   template <typename T>\n   class expression\n   {\n   private:\n\n      typedef details::expression_node<T>*  expression_ptr;\n      typedef details::vector_holder<T>* vector_holder_ptr;\n      typedef std::vector<symbol_table<T> >  symtab_list_t;\n\n      struct control_block\n      {\n         enum data_type\n         {\n            e_unknown  ,\n            e_expr     ,\n            e_vecholder,\n            e_data     ,\n            e_vecdata  ,\n            e_string\n         };\n\n         struct data_pack\n         {\n            data_pack()\n            : pointer(0),\n              type(e_unknown),\n              size(0)\n            {}\n\n            data_pack(void* ptr, data_type dt, std::size_t sz = 0)\n            : pointer(ptr),\n              type(dt),\n              size(sz)\n            {}\n\n            void*       pointer;\n            data_type   type;\n            std::size_t size;\n         };\n\n         typedef std::vector<data_pack> local_data_list_t;\n         typedef results_context<T>     results_context_t;\n\n         control_block()\n         : ref_count(0),\n           expr     (0),\n           results  (0),\n           retinv_null(false),\n           return_invoked(&retinv_null)\n         {}\n\n         control_block(expression_ptr e)\n         : ref_count(1),\n           expr     (e),\n           results  (0),\n           retinv_null(false),\n           return_invoked(&retinv_null)\n         {}\n\n        ~control_block()\n         {\n            if (expr && details::branch_deletable(expr))\n            {\n               destroy_node(expr);\n            }\n\n            if (!local_data_list.empty())\n            {\n               for (std::size_t i = 0; i < local_data_list.size(); ++i)\n               {\n                  switch (local_data_list[i].type)\n                  {\n                     case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);\n                                        break;\n\n                     case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);\n                                        break;\n\n                     case e_data      : delete (T*)(local_data_list[i].pointer);\n                                        break;\n\n                     case e_vecdata   : delete [] (T*)(local_data_list[i].pointer);\n                                        break;\n\n                     case e_string    : delete (std::string*)(local_data_list[i].pointer);\n                                        break;\n\n                     default          : break;\n                  }\n               }\n            }\n\n            if (results)\n            {\n               delete results;\n            }\n         }\n\n         static inline control_block* create(expression_ptr e)\n         {\n            return new control_block(e);\n         }\n\n         static inline void destroy(control_block*& cntrl_blck)\n         {\n            if (cntrl_blck)\n            {\n               if (\n                    (0 !=   cntrl_blck->ref_count) &&\n                    (0 == --cntrl_blck->ref_count)\n                  )\n               {\n                  delete cntrl_blck;\n               }\n\n               cntrl_blck = 0;\n            }\n         }\n\n         std::size_t ref_count;\n         expression_ptr expr;\n         local_data_list_t local_data_list;\n         results_context_t* results;\n         bool  retinv_null;\n         bool* return_invoked;\n\n         friend class function_compositor<T>;\n      };\n\n   public:\n\n      expression()\n      : control_block_(0)\n      {\n         set_expression(new details::null_node<T>());\n      }\n\n      expression(const expression<T>& e)\n      : control_block_    (e.control_block_    ),\n        symbol_table_list_(e.symbol_table_list_)\n      {\n         control_block_->ref_count++;\n      }\n\n      inline expression<T>& operator=(const expression<T>& e)\n      {\n         if (this != &e)\n         {\n            if (control_block_)\n            {\n               if (\n                    (0 !=   control_block_->ref_count) &&\n                    (0 == --control_block_->ref_count)\n                  )\n               {\n                  delete control_block_;\n               }\n\n               control_block_ = 0;\n            }\n\n            control_block_ = e.control_block_;\n            control_block_->ref_count++;\n            symbol_table_list_ = e.symbol_table_list_;\n         }\n\n         return *this;\n      }\n\n      inline bool operator==(const expression<T>& e)\n      {\n         return (this == &e);\n      }\n\n      inline bool operator!() const\n      {\n         return (\n                  (0 == control_block_      ) ||\n                  (0 == control_block_->expr)\n                );\n      }\n\n      inline expression<T>& release()\n      {\n         control_block::destroy(control_block_);\n\n         return (*this);\n      }\n\n     ~expression()\n      {\n         control_block::destroy(control_block_);\n      }\n\n      inline T value() const\n      {\n         return control_block_->expr->value();\n      }\n\n      inline T operator() () const\n      {\n         return value();\n      }\n\n      inline operator T() const\n      {\n         return value();\n      }\n\n      inline operator bool() const\n      {\n         return details::is_true(value());\n      }\n\n      inline void register_symbol_table(symbol_table<T>& st)\n      {\n         symbol_table_list_.push_back(st);\n      }\n\n      inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const\n      {\n         return symbol_table_list_[index];\n      }\n\n      inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)\n      {\n         return symbol_table_list_[index];\n      }\n\n      typedef results_context<T> results_context_t;\n\n      inline const results_context_t& results() const\n      {\n         if (control_block_->results)\n            return (*control_block_->results);\n         else\n         {\n            static const results_context_t null_results;\n            return null_results;\n         }\n      }\n\n      inline bool return_invoked() const\n      {\n         return (*control_block_->return_invoked);\n      }\n\n   private:\n\n      inline symtab_list_t get_symbol_table_list() const\n      {\n         return symbol_table_list_;\n      }\n\n      inline void set_expression(const expression_ptr expr)\n      {\n         if (expr)\n         {\n            if (control_block_)\n            {\n               if (0 == --control_block_->ref_count)\n               {\n                  delete control_block_;\n               }\n            }\n\n            control_block_ = control_block::create(expr);\n         }\n      }\n\n      inline void register_local_var(expression_ptr expr)\n      {\n         if (expr)\n         {\n            if (control_block_)\n            {\n               control_block_->\n                  local_data_list.push_back(\n                     typename expression<T>::control_block::\n                        data_pack(reinterpret_cast<void*>(expr),\n                                  control_block::e_expr));\n            }\n         }\n      }\n\n      inline void register_local_var(vector_holder_ptr vec_holder)\n      {\n         if (vec_holder)\n         {\n            if (control_block_)\n            {\n               control_block_->\n                  local_data_list.push_back(\n                     typename expression<T>::control_block::\n                        data_pack(reinterpret_cast<void*>(vec_holder),\n                                  control_block::e_vecholder));\n            }\n         }\n      }\n\n      inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)\n      {\n         if (data)\n         {\n            if (control_block_)\n            {\n               typename control_block::data_type dt = control_block::e_data;\n\n               switch (data_mode)\n               {\n                  case 0 : dt = control_block::e_data;    break;\n                  case 1 : dt = control_block::e_vecdata; break;\n                  case 2 : dt = control_block::e_string;  break;\n               }\n\n               control_block_->\n                  local_data_list.push_back(\n                     typename expression<T>::control_block::\n                        data_pack(reinterpret_cast<void*>(data),dt,size));\n            }\n         }\n      }\n\n      inline const typename control_block::local_data_list_t& local_data_list()\n      {\n         if (control_block_)\n         {\n            return control_block_->local_data_list;\n         }\n         else\n         {\n            static typename control_block::local_data_list_t null_local_data_list;\n            return null_local_data_list;\n         }\n      }\n\n      inline void register_return_results(results_context_t* rc)\n      {\n         if (control_block_ && rc)\n         {\n            control_block_->results = rc;\n         }\n      }\n\n      inline void set_retinvk(bool* retinvk_ptr)\n      {\n         if (control_block_)\n         {\n            control_block_->return_invoked = retinvk_ptr;\n         }\n      }\n\n      control_block* control_block_;\n      symtab_list_t      symbol_table_list_;\n\n      friend class parser<T>;\n      friend class expression_helper<T>;\n      friend class function_compositor<T>;\n   };\n\n   template <typename T>\n   class expression_helper\n   {\n   public:\n\n      static inline bool is_constant(const expression<T>& expr)\n      {\n         return details::is_constant_node(expr.control_block_->expr);\n      }\n\n      static inline bool is_variable(const expression<T>& expr)\n      {\n         return details::is_variable_node(expr.control_block_->expr);\n      }\n\n      static inline bool is_unary(const expression<T>& expr)\n      {\n         return details::is_unary_node(expr.control_block_->expr);\n      }\n\n      static inline bool is_binary(const expression<T>& expr)\n      {\n         return details::is_binary_node(expr.control_block_->expr);\n      }\n\n      static inline bool is_function(const expression<T>& expr)\n      {\n         return details::is_function(expr.control_block_->expr);\n      }\n\n      static inline bool is_null(const expression<T>& expr)\n      {\n         return details::is_null_node(expr.control_block_->expr);\n      }\n   };\n\n   template <typename T>\n   inline bool is_valid(const expression<T>& expr)\n   {\n      return !expression_helper<T>::is_null(expr);\n   }\n\n   namespace parser_error\n   {\n      enum error_mode\n      {\n         e_unknown = 0,\n         e_syntax  = 1,\n         e_token   = 2,\n         e_numeric = 4,\n         e_symtab  = 5,\n         e_lexer   = 6,\n         e_helper  = 7\n      };\n\n      struct type\n      {\n         type()\n         : mode(parser_error::e_unknown),\n           line_no  (0),\n           column_no(0)\n         {}\n\n         lexer::token token;\n         error_mode mode;\n         std::string diagnostic;\n         std::string src_location;\n         std::string error_line;\n         std::size_t line_no;\n         std::size_t column_no;\n      };\n\n      inline type make_error(error_mode mode,\n                             const std::string& diagnostic   = \"\",\n                             const std::string& src_location = \"\")\n      {\n         type t;\n         t.mode         = mode;\n         t.token.type   = lexer::token::e_error;\n         t.diagnostic   = diagnostic;\n         t.src_location = src_location;\n         exprtk_debug((\"%s\\n\",diagnostic .c_str()));\n         return t;\n      }\n\n      inline type make_error(error_mode mode,\n                             const lexer::token& tk,\n                             const std::string& diagnostic   = \"\",\n                             const std::string& src_location = \"\")\n      {\n         type t;\n         t.mode       = mode;\n         t.token      = tk;\n         t.diagnostic = diagnostic;\n         t.src_location = src_location;\n         exprtk_debug((\"%s\\n\",diagnostic .c_str()));\n         return t;\n      }\n\n      inline std::string to_str(error_mode mode)\n      {\n         switch (mode)\n         {\n            case e_unknown : return std::string(\"Unknown Error\");\n            case e_syntax  : return std::string(\"Syntax Error\" );\n            case e_token   : return std::string(\"Token Error\"  );\n            case e_numeric : return std::string(\"Numeric Error\");\n            case e_symtab  : return std::string(\"Symbol Error\" );\n            case e_lexer   : return std::string(\"Lexer Error\"  );\n            case e_helper  : return std::string(\"Helper Error\" );\n            default        : return std::string(\"Unknown Error\");\n         }\n      }\n\n      inline bool update_error(type& error, const std::string& expression)\n      {\n         if (\n              expression.empty()                         ||\n              (error.token.position > expression.size()) ||\n              (std::numeric_limits<std::size_t>::max() == error.token.position)\n            )\n         {\n            return false;\n         }\n\n         std::size_t error_line_start = 0;\n\n         for (std::size_t i = error.token.position; i > 0; --i)\n         {\n            const details::char_t c = expression[i];\n\n            if (('\\n' == c) || ('\\r' == c))\n            {\n               error_line_start = i + 1;\n               break;\n            }\n         }\n\n         std::size_t next_nl_position = std::min(expression.size(),\n                                                 expression.find_first_of('\\n',error.token.position + 1));\n\n         error.column_no  = error.token.position - error_line_start;\n         error.error_line = expression.substr(error_line_start,\n                                              next_nl_position - error_line_start);\n\n         error.line_no = 0;\n\n         for (std::size_t i = 0; i < next_nl_position; ++i)\n         {\n            if ('\\n' == expression[i])\n               ++error.line_no;\n         }\n\n         return true;\n      }\n\n      inline void dump_error(const type& error)\n      {\n         printf(\"Position: %02d   Type: [%s]   Msg: %s\\n\",\n                static_cast<int>(error.token.position),\n                exprtk::parser_error::to_str(error.mode).c_str(),\n                error.diagnostic.c_str());\n      }\n   }\n\n   namespace details\n   {\n      template <typename Parser>\n      inline void disable_type_checking(Parser& p)\n      {\n         p.state_.type_check_enabled = false;\n      }\n   }\n\n   template <typename T>\n   class parser : public lexer::parser_helper\n   {\n   private:\n\n      enum precedence_level\n      {\n         e_level00,\n         e_level01,\n         e_level02,\n         e_level03,\n         e_level04,\n         e_level05,\n         e_level06,\n         e_level07,\n         e_level08,\n         e_level09,\n         e_level10,\n         e_level11,\n         e_level12,\n         e_level13,\n         e_level14\n      };\n\n      typedef const T&                                               cref_t;\n      typedef const T                                               const_t;\n      typedef ifunction                <T>                                F;\n      typedef ivararg_function         <T>                              VAF;\n      typedef igeneric_function        <T>                               GF;\n      typedef ifunction                <T>                      ifunction_t;\n      typedef ivararg_function         <T>               ivararg_function_t;\n      typedef igeneric_function        <T>              igeneric_function_t;\n      typedef details::expression_node <T>                expression_node_t;\n      typedef details::literal_node    <T>                   literal_node_t;\n      typedef details::unary_node      <T>                     unary_node_t;\n      typedef details::binary_node     <T>                    binary_node_t;\n      typedef details::trinary_node    <T>                   trinary_node_t;\n      typedef details::quaternary_node <T>                quaternary_node_t;\n      typedef details::conditional_node<T>               conditional_node_t;\n      typedef details::cons_conditional_node<T>     cons_conditional_node_t;\n      typedef details::while_loop_node <T>                while_loop_node_t;\n      typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;\n      typedef details::for_loop_node   <T>                  for_loop_node_t;\n      #ifndef exprtk_disable_break_continue\n      typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;\n      typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;\n      typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;\n      #endif\n      typedef details::switch_node     <T>                    switch_node_t;\n      typedef details::variable_node   <T>                  variable_node_t;\n      typedef details::vector_elem_node<T>               vector_elem_node_t;\n      typedef details::rebasevector_elem_node<T>   rebasevector_elem_node_t;\n      typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t;\n      typedef details::vector_node     <T>                    vector_node_t;\n      typedef details::range_pack      <T>                          range_t;\n      #ifndef exprtk_disable_string_capabilities\n      typedef details::stringvar_node     <T>              stringvar_node_t;\n      typedef details::string_literal_node<T>         string_literal_node_t;\n      typedef details::string_range_node  <T>           string_range_node_t;\n      typedef details::const_string_range_node<T> const_string_range_node_t;\n      typedef details::generic_string_range_node<T> generic_string_range_node_t;\n      typedef details::string_concat_node <T>          string_concat_node_t;\n      typedef details::assignment_string_node<T>   assignment_string_node_t;\n      typedef details::assignment_string_range_node<T> assignment_string_range_node_t;\n      typedef details::conditional_string_node<T>  conditional_string_node_t;\n      typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;\n      #endif\n      typedef details::assignment_node<T>                 assignment_node_t;\n      typedef details::assignment_vec_elem_node       <T> assignment_vec_elem_node_t;\n      typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t;\n      typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t;\n      typedef details::assignment_vec_node     <T>    assignment_vec_node_t;\n      typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;\n      typedef details::scand_node<T>                           scand_node_t;\n      typedef details::scor_node<T>                             scor_node_t;\n      typedef lexer::token                                          token_t;\n      typedef expression_node_t*                        expression_node_ptr;\n      typedef expression<T>                                    expression_t;\n      typedef symbol_table<T>                                symbol_table_t;\n      typedef typename expression<T>::symtab_list_t     symbol_table_list_t;\n      typedef details::vector_holder<T>*                  vector_holder_ptr;\n\n      typedef typename details::functor_t<T>         functor_t;\n      typedef typename functor_t::qfunc_t quaternary_functor_t;\n      typedef typename functor_t::tfunc_t    trinary_functor_t;\n      typedef typename functor_t::bfunc_t     binary_functor_t;\n      typedef typename functor_t::ufunc_t      unary_functor_t;\n\n      typedef details::operator_type operator_t;\n\n      typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;\n      typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;\n      typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;\n\n      typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;\n      typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;\n\n      typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;\n      typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;\n      typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;\n\n      typedef details::T0oT1_define<T,  cref_t,  cref_t> vov_t;\n      typedef details::T0oT1_define<T, const_t,  cref_t> cov_t;\n      typedef details::T0oT1_define<T,  cref_t, const_t> voc_t;\n\n      typedef details::T0oT1oT2_define<T,  cref_t,  cref_t,  cref_t> vovov_t;\n      typedef details::T0oT1oT2_define<T,  cref_t,  cref_t, const_t> vovoc_t;\n      typedef details::T0oT1oT2_define<T,  cref_t, const_t,  cref_t> vocov_t;\n      typedef details::T0oT1oT2_define<T, const_t,  cref_t,  cref_t> covov_t;\n      typedef details::T0oT1oT2_define<T, const_t,  cref_t, const_t> covoc_t;\n      typedef details::T0oT1oT2_define<T, const_t, const_t,  cref_t> cocov_t;\n      typedef details::T0oT1oT2_define<T,  cref_t, const_t, const_t> vococ_t;\n\n      typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t,  cref_t> vovovov_t;\n      typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t,  cref_t, const_t> vovovoc_t;\n      typedef details::T0oT1oT2oT3_define<T,  cref_t,  cref_t, const_t,  cref_t> vovocov_t;\n      typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t,  cref_t> vocovov_t;\n      typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t,  cref_t> covovov_t;\n\n      typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t, const_t,  cref_t> covocov_t;\n      typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t,  cref_t, const_t> vocovoc_t;\n      typedef details::T0oT1oT2oT3_define<T, const_t,  cref_t,  cref_t, const_t> covovoc_t;\n      typedef details::T0oT1oT2oT3_define<T,  cref_t, const_t, const_t,  cref_t> vococov_t;\n\n      typedef results_context<T> results_context_t;\n\n      typedef parser_helper prsrhlpr_t;\n\n      struct scope_element\n      {\n         enum element_type\n         {\n            e_none    ,\n            e_variable,\n            e_vector  ,\n            e_vecelem ,\n            e_string\n         };\n\n         typedef details::vector_holder<T> vector_holder_t;\n         typedef variable_node_t*        variable_node_ptr;\n         typedef vector_holder_t*        vector_holder_ptr;\n         typedef expression_node_t*    expression_node_ptr;\n         #ifndef exprtk_disable_string_capabilities\n         typedef stringvar_node_t*      stringvar_node_ptr;\n         #endif\n\n         scope_element()\n         : name(\"???\"),\n           size (std::numeric_limits<std::size_t>::max()),\n           index(std::numeric_limits<std::size_t>::max()),\n           depth(std::numeric_limits<std::size_t>::max()),\n           ref_count(0),\n           ip_index (0),\n           type (e_none),\n           active(false),\n           data    (0),\n           var_node(0),\n           vec_node(0)\n           #ifndef exprtk_disable_string_capabilities\n           ,str_node(0)\n           #endif\n         {}\n\n         bool operator < (const scope_element& se) const\n         {\n            if (ip_index < se.ip_index)\n               return true;\n            else if (ip_index > se.ip_index)\n               return false;\n            else if (depth < se.depth)\n               return true;\n            else if (depth > se.depth)\n               return false;\n            else if (index < se.index)\n               return true;\n            else if (index > se.index)\n               return false;\n            else\n               return (name < se.name);\n         }\n\n         void clear()\n         {\n            name   = \"???\";\n            size   = std::numeric_limits<std::size_t>::max();\n            index  = std::numeric_limits<std::size_t>::max();\n            depth  = std::numeric_limits<std::size_t>::max();\n            type   = e_none;\n            active = false;\n            ref_count = 0;\n            ip_index  = 0;\n            data      = 0;\n            var_node  = 0;\n            vec_node  = 0;\n            #ifndef exprtk_disable_string_capabilities\n            str_node  = 0;\n            #endif\n         }\n\n         std::string  name;\n         std::size_t  size;\n         std::size_t  index;\n         std::size_t  depth;\n         std::size_t  ref_count;\n         std::size_t  ip_index;\n         element_type type;\n         bool         active;\n         void*        data;\n         expression_node_ptr var_node;\n         vector_holder_ptr   vec_node;\n         #ifndef exprtk_disable_string_capabilities\n         stringvar_node_ptr str_node;\n         #endif\n      };\n\n      class scope_element_manager\n      {\n      public:\n\n         typedef expression_node_t* expression_node_ptr;\n         typedef variable_node_t*     variable_node_ptr;\n         typedef parser<T>                     parser_t;\n\n         scope_element_manager(parser<T>& p)\n         : parser_(p),\n           input_param_cnt_(0)\n         {}\n\n         inline std::size_t size() const\n         {\n            return element_.size();\n         }\n\n         inline bool empty() const\n         {\n            return element_.empty();\n         }\n\n         inline scope_element& get_element(const std::size_t& index)\n         {\n            if (index < element_.size())\n               return element_[index];\n            else\n               return null_element_;\n         }\n\n         inline scope_element& get_element(const std::string& var_name,\n                                           const std::size_t index = std::numeric_limits<std::size_t>::max())\n         {\n            const std::size_t current_depth = parser_.state_.scope_depth;\n\n            for (std::size_t i = 0; i < element_.size(); ++i)\n            {\n               scope_element& se = element_[i];\n\n               if (se.depth > current_depth)\n                  continue;\n               else if (\n                         details::imatch(se.name, var_name) &&\n                         (se.index == index)\n                       )\n                  return se;\n            }\n\n            return null_element_;\n         }\n\n         inline scope_element& get_active_element(const std::string& var_name,\n                                                  const std::size_t index = std::numeric_limits<std::size_t>::max())\n         {\n            const std::size_t current_depth = parser_.state_.scope_depth;\n\n            for (std::size_t i = 0; i < element_.size(); ++i)\n            {\n               scope_element& se = element_[i];\n\n               if (se.depth > current_depth)\n                  continue;\n               else if (\n                         details::imatch(se.name, var_name) &&\n                         (se.index == index)                &&\n                         (se.active)\n                       )\n                  return se;\n            }\n\n            return null_element_;\n         }\n\n         inline bool add_element(const scope_element& se)\n         {\n            for (std::size_t i = 0; i < element_.size(); ++i)\n            {\n               scope_element& cse = element_[i];\n\n               if (\n                    details::imatch(cse.name, se.name) &&\n                    (cse.depth <= se.depth)            &&\n                    (cse.index == se.index)            &&\n                    (cse.size  == se.size )            &&\n                    (cse.type  == se.type )            &&\n                    (cse.active)\n                  )\n                  return false;\n            }\n\n            element_.push_back(se);\n            std::sort(element_.begin(),element_.end());\n\n            return true;\n         }\n\n         inline void deactivate(const std::size_t& scope_depth)\n         {\n            exprtk_debug((\"deactivate() - Scope depth: %d\\n\",\n                          static_cast<int>(parser_.state_.scope_depth)));\n\n            for (std::size_t i = 0; i < element_.size(); ++i)\n            {\n               scope_element& se = element_[i];\n\n               if (se.active && (se.depth >= scope_depth))\n               {\n                  exprtk_debug((\"deactivate() - element[%02d] '%s'\\n\",\n                                static_cast<int>(i),\n                                se.name.c_str()));\n\n                  se.active = false;\n               }\n            }\n         }\n\n         inline void free_element(scope_element& se)\n         {\n            switch (se.type)\n            {\n               case scope_element::e_variable   : if (se.data    ) delete (T*) se.data;\n                                                  if (se.var_node) delete se.var_node;\n                                                  break;\n\n               case scope_element::e_vector     : if (se.data    ) delete[] (T*) se.data;\n                                                  if (se.vec_node) delete se.vec_node;\n                                                  break;\n\n               case scope_element::e_vecelem    : if (se.var_node) delete se.var_node;\n                                                  break;\n\n               #ifndef exprtk_disable_string_capabilities\n               case scope_element::e_string     : if (se.data    ) delete (std::string*) se.data;\n                                                  if (se.str_node) delete se.str_node;\n                                                  break;\n               #endif\n\n               default                          : return;\n            }\n\n            se.clear();\n         }\n\n         inline void cleanup()\n         {\n            for (std::size_t i = 0; i < element_.size(); ++i)\n            {\n               free_element(element_[i]);\n            }\n\n            element_.clear();\n\n            input_param_cnt_ = 0;\n         }\n\n         inline std::size_t next_ip_index()\n         {\n            return ++input_param_cnt_;\n         }\n\n         inline expression_node_ptr get_variable(const T& v)\n         {\n            for (std::size_t i = 0; i < element_.size(); ++i)\n            {\n               scope_element& se = element_[i];\n\n               if (\n                    se.active   &&\n                    se.var_node &&\n                    details::is_variable_node(se.var_node)\n                  )\n               {\n                  variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);\n\n                  if (&(vn->ref()) == (&v))\n                  {\n                     return se.var_node;\n                  }\n               }\n            }\n\n            return expression_node_ptr(0);\n         }\n\n      private:\n\n         scope_element_manager& operator=(const scope_element_manager&);\n\n         parser_t& parser_;\n         std::vector<scope_element> element_;\n         scope_element null_element_;\n         std::size_t input_param_cnt_;\n      };\n\n      class scope_handler\n      {\n      public:\n\n         typedef parser<T> parser_t;\n\n         scope_handler(parser<T>& p)\n         : parser_(p)\n         {\n            parser_.state_.scope_depth++;\n            #ifdef exprtk_enable_debugging\n            std::string depth(2 * parser_.state_.scope_depth,'-');\n            exprtk_debug((\"%s> Scope Depth: %02d\\n\",\n                          depth.c_str(),\n                          static_cast<int>(parser_.state_.scope_depth)));\n            #endif\n         }\n\n        ~scope_handler()\n         {\n            parser_.sem_.deactivate(parser_.state_.scope_depth);\n            parser_.state_.scope_depth--;\n            #ifdef exprtk_enable_debugging\n            std::string depth(2 * parser_.state_.scope_depth,'-');\n            exprtk_debug((\"<%s Scope Depth: %02d\\n\",\n                          depth.c_str(),\n                          static_cast<int>(parser_.state_.scope_depth)));\n            #endif\n         }\n\n      private:\n\n         scope_handler& operator=(const scope_handler&);\n\n         parser_t& parser_;\n      };\n\n      struct symtab_store\n      {\n         symbol_table_list_t symtab_list_;\n\n         typedef typename symbol_table_t::local_data_t   local_data_t;\n         typedef typename symbol_table_t::variable_ptr   variable_ptr;\n         typedef typename symbol_table_t::function_ptr   function_ptr;\n         #ifndef exprtk_disable_string_capabilities\n         typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;\n         #endif\n         typedef typename symbol_table_t::vector_holder_ptr       vector_holder_ptr;\n         typedef typename symbol_table_t::vararg_function_ptr   vararg_function_ptr;\n         typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;\n\n         inline bool empty() const\n         {\n            return symtab_list_.empty();\n         }\n\n         inline void clear()\n         {\n            symtab_list_.clear();\n         }\n\n         inline bool valid() const\n         {\n            if (!empty())\n            {\n               for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n               {\n                  if (symtab_list_[i].valid())\n                     return true;\n               }\n            }\n\n            return false;\n         }\n\n         inline bool valid_symbol(const std::string& symbol) const\n         {\n            if (!symtab_list_.empty())\n               return symtab_list_[0].valid_symbol(symbol);\n            else\n               return false;\n         }\n\n         inline bool valid_function_name(const std::string& symbol) const\n         {\n            if (!symtab_list_.empty())\n               return symtab_list_[0].valid_function(symbol);\n            else\n               return false;\n         }\n\n         inline variable_ptr get_variable(const std::string& variable_name) const\n         {\n            if (!valid_symbol(variable_name))\n               return reinterpret_cast<variable_ptr>(0);\n\n            variable_ptr result = reinterpret_cast<variable_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result = local_data(i)\n                              .variable_store.get(variable_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         inline variable_ptr get_variable(const T& var_ref) const\n         {\n            variable_ptr result = reinterpret_cast<variable_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result = local_data(i).variable_store\n                              .get_from_varptr(reinterpret_cast<const void*>(&var_ref));\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline stringvar_ptr get_stringvar(const std::string& string_name) const\n         {\n            if (!valid_symbol(string_name))\n               return reinterpret_cast<stringvar_ptr>(0);\n\n            stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result = local_data(i)\n                              .stringvar_store.get(string_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n         #endif\n\n         inline function_ptr get_function(const std::string& function_name) const\n         {\n            if (!valid_function_name(function_name))\n               return reinterpret_cast<function_ptr>(0);\n\n            function_ptr result = reinterpret_cast<function_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result = local_data(i)\n                              .function_store.get(function_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const\n         {\n            if (!valid_function_name(vararg_function_name))\n               return reinterpret_cast<vararg_function_ptr>(0);\n\n            vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result = local_data(i)\n                              .vararg_function_store.get(vararg_function_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         inline generic_function_ptr get_generic_function(const std::string& function_name) const\n         {\n            if (!valid_function_name(function_name))\n               return reinterpret_cast<generic_function_ptr>(0);\n\n            generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result = local_data(i)\n                              .generic_function_store.get(function_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         inline generic_function_ptr get_string_function(const std::string& function_name) const\n         {\n            if (!valid_function_name(function_name))\n               return reinterpret_cast<generic_function_ptr>(0);\n\n            generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result =\n                     local_data(i).string_function_store.get(function_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         inline vector_holder_ptr get_vector(const std::string& vector_name) const\n         {\n            if (!valid_symbol(vector_name))\n               return reinterpret_cast<vector_holder_ptr>(0);\n\n            vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else\n                  result =\n                     local_data(i).vector_store.get(vector_name);\n\n               if (result) break;\n            }\n\n            return result;\n         }\n\n         inline bool is_constant_node(const std::string& symbol_name) const\n         {\n            if (!valid_symbol(symbol_name))\n               return false;\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (local_data(i).variable_store.is_constant(symbol_name))\n                  return true;\n            }\n\n            return false;\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline bool is_constant_string(const std::string& symbol_name) const\n         {\n            if (!valid_symbol(symbol_name))\n               return false;\n\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))\n                  continue;\n               else if ( local_data(i).stringvar_store.is_constant(symbol_name))\n                  return true;\n            }\n\n            return false;\n         }\n         #endif\n\n         inline bool symbol_exists(const std::string& symbol) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (symtab_list_[i].symbol_exists(symbol))\n                  return true;\n            }\n\n            return false;\n         }\n\n         inline bool is_variable(const std::string& variable_name) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (\n                         symtab_list_[i].local_data().variable_store\n                           .symbol_exists(variable_name)\n                       )\n                  return true;\n            }\n\n            return false;\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline bool is_stringvar(const std::string& stringvar_name) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (\n                         symtab_list_[i].local_data().stringvar_store\n                           .symbol_exists(stringvar_name)\n                       )\n                  return true;\n            }\n\n            return false;\n         }\n\n         inline bool is_conststr_stringvar(const std::string& symbol_name) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (\n                         symtab_list_[i].local_data().stringvar_store\n                           .symbol_exists(symbol_name)\n                       )\n               {\n                  return (\n                           local_data(i).stringvar_store.symbol_exists(symbol_name) ||\n                           local_data(i).stringvar_store.is_constant  (symbol_name)\n                         );\n\n               }\n            }\n\n            return false;\n         }\n         #endif\n\n         inline bool is_function(const std::string& function_name) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (\n                         local_data(i).vararg_function_store\n                           .symbol_exists(function_name)\n                       )\n                  return true;\n            }\n\n            return false;\n         }\n\n         inline bool is_vararg_function(const std::string& vararg_function_name) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (\n                         local_data(i).vararg_function_store\n                           .symbol_exists(vararg_function_name)\n                       )\n                  return true;\n            }\n\n            return false;\n         }\n\n         inline bool is_vector(const std::string& vector_name) const\n         {\n            for (std::size_t i = 0; i < symtab_list_.size(); ++i)\n            {\n               if (!symtab_list_[i].valid())\n                  continue;\n               else if (\n                         local_data(i).vector_store\n                           .symbol_exists(vector_name)\n                       )\n                  return true;\n            }\n\n            return false;\n         }\n\n         inline std::string get_variable_name(const expression_node_ptr& ptr) const\n         {\n            return local_data().variable_store.entity_name(ptr);\n         }\n\n         inline std::string get_vector_name(const vector_holder_ptr& ptr) const\n         {\n            return local_data().vector_store.entity_name(ptr);\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline std::string get_stringvar_name(const expression_node_ptr& ptr) const\n         {\n            return local_data().stringvar_store.entity_name(ptr);\n         }\n\n         inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const\n         {\n            return local_data().stringvar_store.entity_name(ptr);\n         }\n         #endif\n\n         inline local_data_t& local_data(const std::size_t& index = 0)\n         {\n            return symtab_list_[index].local_data();\n         }\n\n         inline const local_data_t& local_data(const std::size_t& index = 0) const\n         {\n            return symtab_list_[index].local_data();\n         }\n\n         inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)\n         {\n            return symtab_list_[index];\n         }\n      };\n\n      struct parser_state\n      {\n         parser_state()\n         : type_check_enabled(true)\n         {\n            reset();\n         }\n\n         void reset()\n         {\n            parsing_return_stmt = false;\n            parsing_break_stmt  = false;\n            return_stmt_present = false;\n            side_effect_present = false;\n            scope_depth         = 0;\n         }\n\n         #ifndef exprtk_enable_debugging\n         void activate_side_effect(const std::string&)\n         #else\n         void activate_side_effect(const std::string& source)\n         #endif\n         {\n            if (!side_effect_present)\n            {\n               side_effect_present = true;\n\n               exprtk_debug((\"activate_side_effect() - caller: %s\\n\",source.c_str()));\n            }\n         }\n\n         bool parsing_return_stmt;\n         bool parsing_break_stmt;\n         bool return_stmt_present;\n         bool side_effect_present;\n         bool type_check_enabled;\n         std::size_t scope_depth;\n      };\n\n   public:\n\n      struct unknown_symbol_resolver\n      {\n\n         enum usr_symbol_type\n         {\n            e_usr_variable_type = 0,\n            e_usr_constant_type = 1\n         };\n\n         enum usr_mode\n         {\n            e_usrmode_default  = 0,\n            e_usrmode_extended = 1\n         };\n\n         usr_mode mode;\n\n         unknown_symbol_resolver(const usr_mode m = e_usrmode_default)\n         : mode(m)\n         {}\n\n         virtual ~unknown_symbol_resolver()\n         {}\n\n         virtual bool process(const std::string& /*unknown_symbol*/,\n                              usr_symbol_type&   st,\n                              T&                 default_value,\n                              std::string&       error_message)\n         {\n            if (e_usrmode_default != mode)\n               return false;\n\n            st = e_usr_variable_type;\n            default_value = T(0);\n            error_message.clear();\n\n            return true;\n         }\n\n         virtual bool process(const std::string& /* unknown_symbol */,\n                              symbol_table_t&    /* symbol_table   */,\n                              std::string&       /* error_message  */)\n         {\n            return false;\n         }\n      };\n\n      enum collect_type\n      {\n         e_ct_none        = 0,\n         e_ct_variables   = 1,\n         e_ct_functions   = 2,\n         e_ct_assignments = 4\n      };\n\n      enum symbol_type\n      {\n         e_st_unknown        = 0,\n         e_st_variable       = 1,\n         e_st_vector         = 2,\n         e_st_vecelem        = 3,\n         e_st_string         = 4,\n         e_st_function       = 5,\n         e_st_local_variable = 6,\n         e_st_local_vector   = 7,\n         e_st_local_string   = 8\n      };\n\n      class dependent_entity_collector\n      {\n      public:\n\n         typedef std::pair<std::string,symbol_type> symbol_t;\n         typedef std::vector<symbol_t> symbol_list_t;\n\n         dependent_entity_collector(const std::size_t options = e_ct_none)\n         : options_(options),\n           collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),\n           collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),\n           collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),\n           return_present_   (false),\n           final_stmt_return_(false)\n         {}\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)\n         {\n            if (!collect_variables_ && !collect_functions_)\n               return 0;\n            else if (symbol_name_list_.empty())\n               return 0;\n\n            for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)\n            {\n               details::case_normalise(symbol_name_list_[i].first);\n            }\n\n            std::sort(symbol_name_list_.begin(),symbol_name_list_.end());\n\n            std::unique_copy(symbol_name_list_.begin(),\n                             symbol_name_list_.end  (),\n                             std::back_inserter(symbols_list));\n\n            return symbols_list.size();\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)\n         {\n            if (!collect_assignments_)\n               return 0;\n            else if (assignment_name_list_.empty())\n               return 0;\n\n            for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)\n            {\n               details::case_normalise(assignment_name_list_[i].first);\n            }\n\n            std::sort(assignment_name_list_.begin(),assignment_name_list_.end());\n\n            std::unique_copy(assignment_name_list_.begin(),\n                             assignment_name_list_.end  (),\n                             std::back_inserter(assignment_list));\n\n            return assignment_list.size();\n         }\n\n         void clear()\n         {\n            symbol_name_list_    .clear();\n            assignment_name_list_.clear();\n            retparam_list_       .clear();\n            return_present_    = false;\n            final_stmt_return_ = false;\n         }\n\n         bool& collect_variables()\n         {\n            return collect_variables_;\n         }\n\n         bool& collect_functions()\n         {\n            return collect_functions_;\n         }\n\n         bool& collect_assignments()\n         {\n            return collect_assignments_;\n         }\n\n         bool return_present() const\n         {\n            return return_present_;\n         }\n\n         bool final_stmt_return() const\n         {\n            return final_stmt_return_;\n         }\n\n         typedef std::vector<std::string> retparam_list_t;\n\n         retparam_list_t return_param_type_list() const\n         {\n            return retparam_list_;\n         }\n\n      private:\n\n         inline void add_symbol(const std::string& symbol, const symbol_type st)\n         {\n            switch (st)\n            {\n               case e_st_variable       :\n               case e_st_vector         :\n               case e_st_string         :\n               case e_st_local_variable :\n               case e_st_local_vector   :\n               case e_st_local_string   : if (collect_variables_)\n                                             symbol_name_list_\n                                                .push_back(std::make_pair(symbol, st));\n                                          break;\n\n               case e_st_function       : if (collect_functions_)\n                                             symbol_name_list_\n                                                .push_back(std::make_pair(symbol, st));\n                                          break;\n\n               default                  : return;\n            }\n         }\n\n         inline void add_assignment(const std::string& symbol, const symbol_type st)\n         {\n            switch (st)\n            {\n               case e_st_variable       :\n               case e_st_vector         :\n               case e_st_string         : if (collect_assignments_)\n                                             assignment_name_list_\n                                                .push_back(std::make_pair(symbol, st));\n                                          break;\n\n               default                  : return;\n            }\n         }\n\n         std::size_t options_;\n         bool collect_variables_;\n         bool collect_functions_;\n         bool collect_assignments_;\n         bool return_present_;\n         bool final_stmt_return_;\n         symbol_list_t symbol_name_list_;\n         symbol_list_t assignment_name_list_;\n         retparam_list_t retparam_list_;\n\n         friend class parser<T>;\n      };\n\n      class settings_store\n      {\n      private:\n\n         typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;\n         typedef disabled_entity_set_t::iterator des_itr_t;\n\n      public:\n\n         enum settings_compilation_options\n         {\n            e_unknown              =    0,\n            e_replacer             =    1,\n            e_joiner               =    2,\n            e_numeric_check        =    4,\n            e_bracket_check        =    8,\n            e_sequence_check       =   16,\n            e_commutative_check    =   32,\n            e_strength_reduction   =   64,\n            e_disable_vardef       =  128,\n            e_collect_vars         =  256,\n            e_collect_funcs        =  512,\n            e_collect_assings      = 1024,\n            e_disable_usr_on_rsrvd = 2048,\n            e_disable_zero_return  = 4096\n         };\n\n         enum settings_base_funcs\n         {\n            e_bf_unknown = 0,\n            e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin   ,\n            e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh  ,\n            e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos    ,\n            e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal  ,\n            e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1  ,\n            e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp ,\n            e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p  ,\n            e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max    ,\n            e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul    ,\n            e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round  ,\n            e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin    ,\n            e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum    ,\n            e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc  ,\n            e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad,\n            e_bf_rad2deg   , e_bf_grad2deg\n         };\n\n         enum settings_control_structs\n         {\n            e_ctrl_unknown = 0,\n            e_ctrl_ifelse,\n            e_ctrl_switch,\n            e_ctrl_for_loop,\n            e_ctrl_while_loop,\n            e_ctrl_repeat_loop,\n            e_ctrl_return\n         };\n\n         enum settings_logic_opr\n         {\n            e_logic_unknown = 0,\n            e_logic_and, e_logic_nand,  e_logic_nor,\n            e_logic_not, e_logic_or,    e_logic_xnor,\n            e_logic_xor, e_logic_scand, e_logic_scor\n         };\n\n         enum settings_arithmetic_opr\n         {\n            e_arith_unknown = 0,\n            e_arith_add, e_arith_sub, e_arith_mul,\n            e_arith_div, e_arith_mod, e_arith_pow\n         };\n\n         enum settings_assignment_opr\n         {\n            e_assign_unknown = 0,\n            e_assign_assign, e_assign_addass, e_assign_subass,\n            e_assign_mulass, e_assign_divass, e_assign_modass\n         };\n\n         enum settings_inequality_opr\n         {\n            e_ineq_unknown = 0,\n            e_ineq_lt,    e_ineq_lte, e_ineq_eq,\n            e_ineq_equal, e_ineq_ne,  e_ineq_nequal,\n            e_ineq_gte,   e_ineq_gt\n         };\n\n         static const std::size_t compile_all_opts = e_replacer          +\n                                                     e_joiner            +\n                                                     e_numeric_check     +\n                                                     e_bracket_check     +\n                                                     e_sequence_check    +\n                                                     e_commutative_check +\n                                                     e_strength_reduction;\n\n         settings_store(const std::size_t compile_options = compile_all_opts)\n         {\n           load_compile_options(compile_options);\n         }\n\n         settings_store& enable_all_base_functions()\n         {\n            disabled_func_set_.clear();\n            return (*this);\n         }\n\n         settings_store& enable_all_control_structures()\n         {\n            disabled_ctrl_set_.clear();\n            return (*this);\n         }\n\n         settings_store& enable_all_logic_ops()\n         {\n            disabled_logic_set_.clear();\n            return (*this);\n         }\n\n         settings_store& enable_all_arithmetic_ops()\n         {\n            disabled_arithmetic_set_.clear();\n            return (*this);\n         }\n\n         settings_store& enable_all_assignment_ops()\n         {\n            disabled_assignment_set_.clear();\n            return (*this);\n         }\n\n         settings_store& enable_all_inequality_ops()\n         {\n            disabled_inequality_set_.clear();\n            return (*this);\n         }\n\n         settings_store& enable_local_vardef()\n         {\n            disable_vardef_ = false;\n            return (*this);\n         }\n\n         settings_store& disable_all_base_functions()\n         {\n            std::copy(details::base_function_list,\n                      details::base_function_list + details::base_function_list_size,\n                      std::insert_iterator<disabled_entity_set_t>\n                        (disabled_func_set_, disabled_func_set_.begin()));\n            return (*this);\n         }\n\n         settings_store& disable_all_control_structures()\n         {\n            std::copy(details::cntrl_struct_list,\n                      details::cntrl_struct_list + details::cntrl_struct_list_size,\n                      std::insert_iterator<disabled_entity_set_t>\n                        (disabled_ctrl_set_, disabled_ctrl_set_.begin()));\n            return (*this);\n         }\n\n         settings_store& disable_all_logic_ops()\n         {\n            std::copy(details::logic_ops_list,\n                      details::logic_ops_list + details::logic_ops_list_size,\n                      std::insert_iterator<disabled_entity_set_t>\n                        (disabled_logic_set_, disabled_logic_set_.begin()));\n            return (*this);\n         }\n\n         settings_store& disable_all_arithmetic_ops()\n         {\n            std::copy(details::arithmetic_ops_list,\n                      details::arithmetic_ops_list + details::arithmetic_ops_list_size,\n                      std::insert_iterator<disabled_entity_set_t>\n                        (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));\n            return (*this);\n         }\n\n         settings_store& disable_all_assignment_ops()\n         {\n            std::copy(details::assignment_ops_list,\n                      details::assignment_ops_list + details::assignment_ops_list_size,\n                      std::insert_iterator<disabled_entity_set_t>\n                        (disabled_assignment_set_, disabled_assignment_set_.begin()));\n            return (*this);\n         }\n\n         settings_store& disable_all_inequality_ops()\n         {\n            std::copy(details::inequality_ops_list,\n                      details::inequality_ops_list + details::inequality_ops_list_size,\n                      std::insert_iterator<disabled_entity_set_t>\n                        (disabled_inequality_set_, disabled_inequality_set_.begin()));\n            return (*this);\n         }\n\n         settings_store& disable_local_vardef()\n         {\n            disable_vardef_ = true;\n            return (*this);\n         }\n\n         bool replacer_enabled           () const { return enable_replacer_;           }\n         bool commutative_check_enabled  () const { return enable_commutative_check_;  }\n         bool joiner_enabled             () const { return enable_joiner_;             }\n         bool numeric_check_enabled      () const { return enable_numeric_check_;      }\n         bool bracket_check_enabled      () const { return enable_bracket_check_;      }\n         bool sequence_check_enabled     () const { return enable_sequence_check_;     }\n         bool strength_reduction_enabled () const { return enable_strength_reduction_; }\n         bool collect_variables_enabled  () const { return enable_collect_vars_;       }\n         bool collect_functions_enabled  () const { return enable_collect_funcs_;      }\n         bool collect_assignments_enabled() const { return enable_collect_assings_;    }\n         bool vardef_disabled            () const { return disable_vardef_;            }\n         bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }\n         bool zero_return_disabled       () const { return disable_zero_return_;       }\n\n         bool function_enabled(const std::string& function_name)\n         {\n            if (disabled_func_set_.empty())\n               return true;\n            else\n               return (disabled_func_set_.end() == disabled_func_set_.find(function_name));\n         }\n\n         bool control_struct_enabled(const std::string& control_struct)\n         {\n            if (disabled_ctrl_set_.empty())\n               return true;\n            else\n               return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));\n         }\n\n         bool logic_enabled(const std::string& logic_operation)\n         {\n            if (disabled_logic_set_.empty())\n               return true;\n            else\n               return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));\n         }\n\n         bool arithmetic_enabled(const details::operator_type& arithmetic_operation)\n         {\n            if (disabled_logic_set_.empty())\n               return true;\n            else\n               return disabled_arithmetic_set_.end() == disabled_arithmetic_set_\n                                                            .find(arith_opr_to_string(arithmetic_operation));\n         }\n\n         bool assignment_enabled(const details::operator_type& assignment)\n         {\n            if (disabled_assignment_set_.empty())\n               return true;\n            else\n               return disabled_assignment_set_.end() == disabled_assignment_set_\n                                                           .find(assign_opr_to_string(assignment));\n         }\n\n         bool inequality_enabled(const details::operator_type& inequality)\n         {\n            if (disabled_inequality_set_.empty())\n               return true;\n            else\n               return disabled_inequality_set_.end() == disabled_inequality_set_\n                                                           .find(inequality_opr_to_string(inequality));\n         }\n\n         bool function_disabled(const std::string& function_name)\n         {\n            if (disabled_func_set_.empty())\n               return false;\n            else\n               return (disabled_func_set_.end() != disabled_func_set_.find(function_name));\n         }\n\n         bool control_struct_disabled(const std::string& control_struct)\n         {\n            if (disabled_ctrl_set_.empty())\n               return false;\n            else\n               return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));\n         }\n\n         bool logic_disabled(const std::string& logic_operation)\n         {\n            if (disabled_logic_set_.empty())\n               return false;\n            else\n               return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));\n         }\n\n         bool assignment_disabled(const details::operator_type assignment_operation)\n         {\n            if (disabled_assignment_set_.empty())\n               return false;\n            else\n               return disabled_assignment_set_.end() != disabled_assignment_set_\n                                                           .find(assign_opr_to_string(assignment_operation));\n         }\n\n         bool arithmetic_disabled(const details::operator_type arithmetic_operation)\n         {\n            if (disabled_arithmetic_set_.empty())\n               return false;\n            else\n               return disabled_arithmetic_set_.end() != disabled_arithmetic_set_\n                                                           .find(arith_opr_to_string(arithmetic_operation));\n         }\n\n         bool inequality_disabled(const details::operator_type& inequality)\n         {\n            if (disabled_inequality_set_.empty())\n               return false;\n            else\n               return disabled_inequality_set_.end() != disabled_inequality_set_\n                                                           .find(inequality_opr_to_string(inequality));\n         }\n\n         settings_store& disable_base_function(settings_base_funcs bf)\n         {\n            if (\n                 (e_bf_unknown != bf) &&\n                 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))\n               )\n            {\n               disabled_func_set_.insert(details::base_function_list[bf - 1]);\n            }\n\n            return (*this);\n         }\n\n         settings_store& disable_control_structure(settings_control_structs ctrl_struct)\n         {\n            if (\n                 (e_ctrl_unknown != ctrl_struct) &&\n                 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))\n               )\n            {\n               disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);\n            }\n\n            return (*this);\n         }\n\n         settings_store& disable_logic_operation(settings_logic_opr logic)\n         {\n            if (\n                 (e_logic_unknown != logic) &&\n                 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))\n               )\n            {\n               disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);\n            }\n\n            return (*this);\n         }\n\n         settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)\n         {\n            if (\n                 (e_arith_unknown != arithmetic) &&\n                 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))\n               )\n            {\n               disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);\n            }\n\n            return (*this);\n         }\n\n         settings_store& disable_assignment_operation(settings_assignment_opr assignment)\n         {\n            if (\n                 (e_assign_unknown != assignment) &&\n                 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))\n               )\n            {\n               disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);\n            }\n\n            return (*this);\n         }\n\n         settings_store& disable_inequality_operation(settings_inequality_opr inequality)\n         {\n            if (\n                 (e_ineq_unknown != inequality) &&\n                 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))\n               )\n            {\n               disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);\n            }\n\n            return (*this);\n         }\n\n         settings_store& enable_base_function(settings_base_funcs bf)\n         {\n            if (\n                 (e_bf_unknown != bf) &&\n                 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))\n               )\n            {\n               const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);\n\n               if (disabled_func_set_.end() != itr)\n               {\n                  disabled_func_set_.erase(itr);\n               }\n            }\n\n            return (*this);\n         }\n\n         settings_store& enable_control_structure(settings_control_structs ctrl_struct)\n         {\n            if (\n                 (e_ctrl_unknown != ctrl_struct) &&\n                 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))\n               )\n            {\n               const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);\n\n               if (disabled_ctrl_set_.end() != itr)\n               {\n                  disabled_ctrl_set_.erase(itr);\n               }\n            }\n\n            return (*this);\n         }\n\n         settings_store& enable_logic_operation(settings_logic_opr logic)\n         {\n            if (\n                 (e_logic_unknown != logic) &&\n                 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))\n               )\n            {\n               const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);\n\n               if (disabled_logic_set_.end() != itr)\n               {\n                  disabled_logic_set_.erase(itr);\n               }\n            }\n\n            return (*this);\n         }\n\n         settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)\n         {\n            if (\n                 (e_arith_unknown != arithmetic) &&\n                 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))\n               )\n            {\n               const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);\n\n               if (disabled_arithmetic_set_.end() != itr)\n               {\n                  disabled_arithmetic_set_.erase(itr);\n               }\n            }\n\n            return (*this);\n         }\n\n         settings_store& enable_assignment_operation(settings_assignment_opr assignment)\n         {\n            if (\n                 (e_assign_unknown != assignment) &&\n                 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))\n               )\n            {\n               const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);\n\n               if (disabled_assignment_set_.end() != itr)\n               {\n                  disabled_assignment_set_.erase(itr);\n               }\n            }\n\n            return (*this);\n         }\n\n         settings_store& enable_inequality_operation(settings_inequality_opr inequality)\n         {\n            if (\n                 (e_ineq_unknown != inequality) &&\n                 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))\n               )\n            {\n               const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);\n\n               if (disabled_inequality_set_.end() != itr)\n               {\n                  disabled_inequality_set_.erase(itr);\n               }\n            }\n\n            return (*this);\n         }\n\n      private:\n\n         void load_compile_options(const std::size_t compile_options)\n         {\n            enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;\n            enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;\n            enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;\n            enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;\n            enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;\n            enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;\n            enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;\n            enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;\n            enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;\n            enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;\n            disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;\n            disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;\n            disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;\n         }\n\n         std::string assign_opr_to_string(details::operator_type opr)\n         {\n            switch (opr)\n            {\n               case details::e_assign : return \":=\";\n               case details::e_addass : return \"+=\";\n               case details::e_subass : return \"-=\";\n               case details::e_mulass : return \"*=\";\n               case details::e_divass : return \"/=\";\n               case details::e_modass : return \"%=\";\n               default                : return   \"\";\n            }\n         }\n\n         std::string arith_opr_to_string(details::operator_type opr)\n         {\n            switch (opr)\n            {\n               case details::e_add : return \"+\";\n               case details::e_sub : return \"-\";\n               case details::e_mul : return \"*\";\n               case details::e_div : return \"/\";\n               case details::e_mod : return \"%\";\n               default             : return  \"\";\n            }\n         }\n\n         std::string inequality_opr_to_string(details::operator_type opr)\n         {\n            switch (opr)\n            {\n               case details::e_lt    : return  \"<\";\n               case details::e_lte   : return \"<=\";\n               case details::e_eq    : return \"==\";\n               case details::e_equal : return  \"=\";\n               case details::e_ne    : return \"!=\";\n               case details::e_nequal: return \"<>\";\n               case details::e_gte   : return \">=\";\n               case details::e_gt    : return  \">\";\n               default               : return   \"\";\n            }\n         }\n\n         bool enable_replacer_;\n         bool enable_joiner_;\n         bool enable_numeric_check_;\n         bool enable_bracket_check_;\n         bool enable_sequence_check_;\n         bool enable_commutative_check_;\n         bool enable_strength_reduction_;\n         bool enable_collect_vars_;\n         bool enable_collect_funcs_;\n         bool enable_collect_assings_;\n         bool disable_vardef_;\n         bool disable_rsrvd_sym_usr_;\n         bool disable_zero_return_;\n\n         disabled_entity_set_t disabled_func_set_ ;\n         disabled_entity_set_t disabled_ctrl_set_ ;\n         disabled_entity_set_t disabled_logic_set_;\n         disabled_entity_set_t disabled_arithmetic_set_;\n         disabled_entity_set_t disabled_assignment_set_;\n         disabled_entity_set_t disabled_inequality_set_;\n\n         friend class parser<T>;\n      };\n\n      typedef settings_store settings_t;\n\n      parser(const settings_t& settings = settings_t())\n      : settings_(settings),\n        resolve_unknown_symbol_(false),\n        results_context_(0),\n        unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),\n        #ifdef _MSC_VER\n        #pragma warning(push)\n        #pragma warning (disable:4355)\n        #endif\n        sem_(*this),\n        #ifdef _MSC_VER\n        #pragma warning(pop)\n        #endif\n        operator_joiner_2_(2),\n        operator_joiner_3_(3)\n      {\n         init_precompilation();\n\n         load_operations_map           (base_ops_map_     );\n         load_unary_operations_map     (unary_op_map_     );\n         load_binary_operations_map    (binary_op_map_    );\n         load_inv_binary_operations_map(inv_binary_op_map_);\n         load_sf3_map                  (sf3_map_          );\n         load_sf4_map                  (sf4_map_          );\n\n         expression_generator_.init_synthesize_map();\n         expression_generator_.set_parser(*this);\n         expression_generator_.set_uom(unary_op_map_);\n         expression_generator_.set_bom(binary_op_map_);\n         expression_generator_.set_ibom(inv_binary_op_map_);\n         expression_generator_.set_sf3m(sf3_map_);\n         expression_generator_.set_sf4m(sf4_map_);\n         expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());\n      }\n\n     ~parser()\n      {}\n\n      inline void init_precompilation()\n      {\n         if (settings_.collect_variables_enabled())\n            dec_.collect_variables() = true;\n\n         if (settings_.collect_functions_enabled())\n            dec_.collect_functions() = true;\n\n         if (settings_.collect_assignments_enabled())\n            dec_.collect_assignments() = true;\n\n         if (settings_.replacer_enabled())\n         {\n            symbol_replacer_.clear();\n            symbol_replacer_.add_replace(\"true\" ,\"1\",lexer::token::e_number);\n            symbol_replacer_.add_replace(\"false\",\"0\",lexer::token::e_number);\n            helper_assembly_.token_modifier_list.clear();\n            helper_assembly_.register_modifier(&symbol_replacer_);\n         }\n\n         if (settings_.commutative_check_enabled())\n         {\n            for (std::size_t i = 0; i < details::reserved_words_size; ++i)\n            {\n               commutative_inserter_.ignore_symbol(details::reserved_words[i]);\n            }\n\n            helper_assembly_.token_inserter_list.clear();\n            helper_assembly_.register_inserter(&commutative_inserter_);\n         }\n\n         if (settings_.joiner_enabled())\n         {\n            helper_assembly_.token_joiner_list.clear();\n            helper_assembly_.register_joiner(&operator_joiner_2_);\n            helper_assembly_.register_joiner(&operator_joiner_3_);\n         }\n\n         if (\n              settings_.numeric_check_enabled () ||\n              settings_.bracket_check_enabled () ||\n              settings_.sequence_check_enabled()\n            )\n         {\n            helper_assembly_.token_scanner_list.clear();\n\n            if (settings_.numeric_check_enabled())\n            {\n               helper_assembly_.register_scanner(&numeric_checker_);\n            }\n\n            if (settings_.bracket_check_enabled())\n            {\n               helper_assembly_.register_scanner(&bracket_checker_);\n            }\n\n            if (settings_.sequence_check_enabled())\n            {\n               helper_assembly_.register_scanner(&sequence_validator_);\n            }\n         }\n      }\n\n      inline bool compile(const std::string& expression_string, expression<T>& expr)\n      {\n         state_          .reset();\n         error_list_     .clear();\n         brkcnt_list_    .clear();\n         synthesis_error_.clear();\n         sem_            .cleanup();\n\n         return_cleanup();\n\n         expression_generator_.set_allocator(node_allocator_);\n\n         if (expression_string.empty())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          \"ERR000 - Empty expression!\",\n                          exprtk_error_location));\n\n            return false;\n         }\n\n         if (!init(expression_string))\n         {\n            process_lexer_errors();\n            return false;\n         }\n\n         if (lexer().empty())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          \"ERR001 - Empty expression!\",\n                          exprtk_error_location));\n\n            return false;\n         }\n\n         if (!run_assemblies())\n         {\n            return false;\n         }\n\n         symtab_store_.symtab_list_ = expr.get_symbol_table_list();\n         dec_.clear();\n\n         lexer().begin();\n\n         next_token();\n\n         expression_node_ptr e = parse_corpus();\n\n         if ((0 != e) && (token_t::e_eof == current_token().type))\n         {\n            bool* retinvk_ptr = 0;\n\n            if (state_.return_stmt_present)\n            {\n               dec_.return_present_ = true;\n\n               e = expression_generator_\n                     .return_envelope(e,results_context_,retinvk_ptr);\n            }\n\n            expr.set_expression(e);\n            expr.set_retinvk(retinvk_ptr);\n\n            register_local_vars(expr);\n            register_return_results(expr);\n\n            return !(!expr);\n         }\n         else\n         {\n            if (error_list_.empty())\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR002 - Invalid expression encountered\",\n                             exprtk_error_location));\n            }\n\n            dec_.clear    ();\n            sem_.cleanup  ();\n            return_cleanup();\n\n            if ((0 != e) && branch_deletable(e))\n            {\n               destroy_node(e);\n            }\n\n            return false;\n         }\n      }\n\n      inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)\n      {\n         expression_t expr;\n\n         expr.register_symbol_table(symtab);\n\n         compile(expression_string,expr);\n\n         return expr;\n      }\n\n      void process_lexer_errors()\n      {\n         for (std::size_t i = 0; i < lexer().size(); ++i)\n         {\n            if (lexer()[i].is_error())\n            {\n               std::string diagnostic = \"ERR003 - \";\n\n               switch (lexer()[i].type)\n               {\n                  case lexer::token::e_error      : diagnostic += \"General token error\";\n                                                    break;\n\n                  case lexer::token::e_err_symbol : diagnostic += \"Symbol error\";\n                                                    break;\n\n                  case lexer::token::e_err_number : diagnostic += \"Invalid numeric token\";\n                                                    break;\n\n                  case lexer::token::e_err_string : diagnostic += \"Invalid string token\";\n                                                    break;\n\n                  case lexer::token::e_err_sfunc  : diagnostic += \"Invalid special function token\";\n                                                    break;\n\n                  default                         : diagnostic += \"Unknown compiler error\";\n               }\n\n               set_error(\n                  make_error(parser_error::e_lexer,\n                             lexer()[i],\n                             diagnostic + \": \" + lexer()[i].value,\n                             exprtk_error_location));\n            }\n         }\n      }\n\n      inline bool run_assemblies()\n      {\n         if (settings_.commutative_check_enabled())\n         {\n            helper_assembly_.run_inserters(lexer());\n         }\n\n         if (settings_.joiner_enabled())\n         {\n            helper_assembly_.run_joiners(lexer());\n         }\n\n         if (settings_.replacer_enabled())\n         {\n            helper_assembly_.run_modifiers(lexer());\n         }\n\n         if (\n              settings_.numeric_check_enabled () ||\n              settings_.bracket_check_enabled () ||\n              settings_.sequence_check_enabled()\n            )\n         {\n            if (!helper_assembly_.run_scanners(lexer()))\n            {\n               if (helper_assembly_.error_token_scanner)\n               {\n                  lexer::helper::bracket_checker*    bracket_checker_ptr    = 0;\n                  lexer::helper::numeric_checker*    numeric_checker_ptr    = 0;\n                  lexer::helper::sequence_validator* sequence_validator_ptr = 0;\n\n                  if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))\n                  {\n                     set_error(\n                        make_error(parser_error::e_token,\n                                   bracket_checker_ptr->error_token(),\n                                   \"ERR004 - Mismatched brackets: '\" + bracket_checker_ptr->error_token().value + \"'\",\n                                   exprtk_error_location));\n                  }\n                  else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))\n                  {\n                     for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)\n                     {\n                        lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];\n\n                        set_error(\n                           make_error(parser_error::e_token,\n                                      error_token,\n                                      \"ERR005 - Invalid numeric token: '\" + error_token.value + \"'\",\n                                      exprtk_error_location));\n                     }\n\n                     if (numeric_checker_ptr->error_count())\n                     {\n                        numeric_checker_ptr->clear_errors();\n                     }\n                  }\n                  else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))\n                  {\n                     for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)\n                     {\n                        std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);\n\n                        set_error(\n                           make_error(parser_error::e_token,\n                                      error_token.first,\n                                      \"ERR006 - Invalid token sequence: '\" +\n                                      error_token.first.value  + \"' and '\" +\n                                      error_token.second.value + \"'\",\n                                      exprtk_error_location));\n                     }\n\n                     if (sequence_validator_ptr->error_count())\n                     {\n                        sequence_validator_ptr->clear_errors();\n                     }\n                  }\n               }\n\n               return false;\n            }\n         }\n\n         return true;\n      }\n\n      inline settings_store& settings()\n      {\n         return settings_;\n      }\n\n      inline parser_error::type get_error(const std::size_t& index)\n      {\n         if (index < error_list_.size())\n            return error_list_[index];\n         else\n            throw std::invalid_argument(\"parser::get_error() - Invalid error index specificed\");\n      }\n\n      inline std::string error() const\n      {\n         if (!error_list_.empty())\n         {\n            return error_list_[0].diagnostic;\n         }\n         else\n            return std::string(\"No Error\");\n      }\n\n      inline std::size_t error_count() const\n      {\n         return error_list_.size();\n      }\n\n      inline dependent_entity_collector& dec()\n      {\n         return dec_;\n      }\n\n      inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)\n      {\n         if (!settings_.replacer_enabled())\n            return false;\n         else if (details::is_reserved_word(old_symbol))\n            return false;\n         else\n            return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);\n      }\n\n      inline bool remove_replace_symbol(const std::string& symbol)\n      {\n         if (!settings_.replacer_enabled())\n            return false;\n         else if (details::is_reserved_word(symbol))\n            return false;\n         else\n            return symbol_replacer_.remove(symbol);\n      }\n\n      inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))\n      {\n         resolve_unknown_symbol_ = true;\n\n         if (usr)\n            unknown_symbol_resolver_ = usr;\n         else\n            unknown_symbol_resolver_ = &default_usr_;\n      }\n\n      inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)\n      {\n         enable_unknown_symbol_resolver(&usr);\n      }\n\n      inline void disable_unknown_symbol_resolver()\n      {\n         resolve_unknown_symbol_  = false;\n         unknown_symbol_resolver_ = &default_usr_;\n      }\n\n   private:\n\n      inline bool valid_base_operation(const std::string& symbol)\n      {\n         const std::size_t length = symbol.size();\n\n         if (\n              (length < 3) || // Shortest base op symbol length\n              (length > 9)    // Longest base op symbol length\n            )\n            return false;\n         else\n            return settings_.function_enabled(symbol) &&\n                   (base_ops_map_.end() != base_ops_map_.find(symbol));\n      }\n\n      inline bool valid_vararg_operation(const std::string& symbol)\n      {\n         static const std::string s_sum     = \"sum\" ;\n         static const std::string s_mul     = \"mul\" ;\n         static const std::string s_avg     = \"avg\" ;\n         static const std::string s_min     = \"min\" ;\n         static const std::string s_max     = \"max\" ;\n         static const std::string s_mand    = \"mand\";\n         static const std::string s_mor     = \"mor\" ;\n         static const std::string s_multi   = \"~\"   ;\n         static const std::string s_mswitch = \"[*]\" ;\n\n         return\n               (\n                  details::imatch(symbol,s_sum    ) ||\n                  details::imatch(symbol,s_mul    ) ||\n                  details::imatch(symbol,s_avg    ) ||\n                  details::imatch(symbol,s_min    ) ||\n                  details::imatch(symbol,s_max    ) ||\n                  details::imatch(symbol,s_mand   ) ||\n                  details::imatch(symbol,s_mor    ) ||\n                  details::imatch(symbol,s_multi  ) ||\n                  details::imatch(symbol,s_mswitch)\n               ) &&\n               settings_.function_enabled(symbol);\n      }\n\n      bool is_invalid_arithmetic_operation(const details::operator_type operation)\n      {\n         return settings_.arithmetic_disabled(operation);\n      }\n\n      bool is_invalid_assignment_operation(const details::operator_type operation)\n      {\n         return settings_.assignment_disabled(operation);\n      }\n\n      bool is_invalid_inequality_operation(const details::operator_type operation)\n      {\n         return settings_.inequality_disabled(operation);\n      }\n\n      #ifdef exprtk_enable_debugging\n      inline void next_token()\n      {\n         std::string ct_str = current_token().value;\n         parser_helper::next_token();\n         std::string depth(2 * state_.scope_depth,' ');\n         exprtk_debug((\"%s\"\n                       \"prev[%s] --> curr[%s]\\n\",\n                       depth.c_str(),\n                       ct_str.c_str(),\n                       current_token().value.c_str()));\n      }\n      #endif\n\n      inline expression_node_ptr parse_corpus()\n      {\n         std::vector<expression_node_ptr> arg_list;\n         std::vector<bool> side_effect_list;\n\n         expression_node_ptr result = error_node();\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         lexer::token begin_token;\n         lexer::token   end_token;\n\n         for ( ; ; )\n         {\n            state_.side_effect_present = false;\n\n            begin_token = current_token();\n\n            expression_node_ptr arg = parse_expression();\n\n            if (0 == arg)\n            {\n               if (error_list_.empty())\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR007 - Invalid expression encountered\",\n                                exprtk_error_location));\n               }\n\n               return error_node();\n            }\n            else\n            {\n               arg_list.push_back(arg);\n\n               side_effect_list.push_back(state_.side_effect_present);\n\n               end_token = current_token();\n\n               std::string sub_expr = construct_subexpr(begin_token,end_token);\n\n               exprtk_debug((\"parse_corpus(%02d) Subexpr: %s\\n\",\n                             static_cast<int>(arg_list.size() - 1),\n                             sub_expr.c_str()));\n\n               exprtk_debug((\"parse_corpus(%02d) - Side effect present: %s\\n\",\n                             static_cast<int>(arg_list.size() - 1),\n                             state_.side_effect_present ? \"true\" : \"false\"));\n\n               exprtk_debug((\"-------------------------------------------------\\n\"));\n            }\n\n            if (lexer().finished())\n               break;\n            else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))\n            {\n               if (lexer().finished())\n                  break;\n               else\n                  next_token();\n            }\n         }\n\n         if (\n              !arg_list.empty() &&\n              is_return_node(arg_list.back())\n            )\n         {\n            dec_.final_stmt_return_ = true;\n         }\n\n         result = simplify(arg_list,side_effect_list);\n\n         sdd.delete_ptr = (0 == result);\n\n         return result;\n      }\n\n      std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)\n      {\n         std::string result = lexer().substr(begin_token.position,end_token.position);\n\n         for (std::size_t i = 0; i < result.size(); ++i)\n         {\n            if (details::is_whitespace(result[i])) result[i] = ' ';\n         }\n\n         return result;\n      }\n\n      static const precedence_level default_precedence = e_level00;\n\n      struct state_t\n      {\n         inline void set(const precedence_level& l,\n                         const precedence_level& r,\n                         const details::operator_type& o)\n         {\n            left  = l;\n            right = r;\n            operation = o;\n         }\n\n         inline void reset()\n         {\n            left      = e_level00;\n            right     = e_level00;\n            operation = details::e_default;\n         }\n\n         precedence_level left;\n         precedence_level right;\n         details::operator_type operation;\n      };\n\n      inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)\n      {\n         expression_node_ptr expression = parse_branch(precedence);\n\n         if (0 == expression)\n         {\n            return error_node();\n         }\n\n         bool break_loop = false;\n\n         state_t current_state;\n\n         for ( ; ; )\n         {\n            current_state.reset();\n\n            switch (current_token().type)\n            {\n               case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;\n               case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;\n               case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;\n               case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;\n               case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;\n               case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break;\n               case token_t::e_swap   : current_state.set(e_level00,e_level00,details::e_swap  ); break;\n               case token_t::e_lt     : current_state.set(e_level05,e_level06,details::    e_lt); break;\n               case token_t::e_lte    : current_state.set(e_level05,e_level06,details::   e_lte); break;\n               case token_t::e_eq     : current_state.set(e_level05,e_level06,details::    e_eq); break;\n               case token_t::e_ne     : current_state.set(e_level05,e_level06,details::    e_ne); break;\n               case token_t::e_gte    : current_state.set(e_level05,e_level06,details::   e_gte); break;\n               case token_t::e_gt     : current_state.set(e_level05,e_level06,details::    e_gt); break;\n               case token_t::e_add    : current_state.set(e_level07,e_level08,details::   e_add); break;\n               case token_t::e_sub    : current_state.set(e_level07,e_level08,details::   e_sub); break;\n               case token_t::e_div    : current_state.set(e_level10,e_level11,details::   e_div); break;\n               case token_t::e_mul    : current_state.set(e_level10,e_level11,details::   e_mul); break;\n               case token_t::e_mod    : current_state.set(e_level10,e_level11,details::   e_mod); break;\n               case token_t::e_pow    : current_state.set(e_level12,e_level12,details::   e_pow); break;\n               default                : if (token_t::e_symbol == current_token().type)\n                                        {\n                                           static const std::string s_and   =   \"and\";\n                                           static const std::string s_nand  =  \"nand\";\n                                           static const std::string s_or    =    \"or\";\n                                           static const std::string s_nor   =   \"nor\";\n                                           static const std::string s_xor   =   \"xor\";\n                                           static const std::string s_xnor  =  \"xnor\";\n                                           static const std::string s_in    =    \"in\";\n                                           static const std::string s_like  =  \"like\";\n                                           static const std::string s_ilike = \"ilike\";\n                                           static const std::string s_and1  =     \"&\";\n                                           static const std::string s_or1   =     \"|\";\n                                           static const std::string s_not   =   \"not\";\n\n                                           if (details::imatch(current_token().value,s_and))\n                                           {\n                                              current_state.set(e_level03, e_level04, details::e_and);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_and1))\n                                           {\n                                              #ifndef exprtk_disable_sc_andor\n                                              current_state.set(e_level03, e_level04, details::e_scand);\n                                              #else\n                                              current_state.set(e_level03, e_level04, details::e_and);\n                                              #endif\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_nand))\n                                           {\n                                              current_state.set(e_level03, e_level04, details::e_nand);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_or))\n                                           {\n                                              current_state.set(e_level01, e_level02, details::e_or);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_or1))\n                                           {\n                                              #ifndef exprtk_disable_sc_andor\n                                              current_state.set(e_level01, e_level02, details::e_scor);\n                                              #else\n                                              current_state.set(e_level01, e_level02, details::e_or);\n                                              #endif\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_nor))\n                                           {\n                                              current_state.set(e_level01, e_level02, details::e_nor);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_xor))\n                                           {\n                                              current_state.set(e_level01, e_level02, details::e_xor);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_xnor))\n                                           {\n                                              current_state.set(e_level01, e_level02, details::e_xnor);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_in))\n                                           {\n                                              current_state.set(e_level04, e_level04, details::e_in);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_like))\n                                           {\n                                              current_state.set(e_level04, e_level04, details::e_like);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_ilike))\n                                           {\n                                              current_state.set(e_level04, e_level04, details::e_ilike);\n                                              break;\n                                           }\n                                           else if (details::imatch(current_token().value,s_not))\n                                           {\n                                              break;\n                                           }\n                                        }\n\n                                        break_loop = true;\n            }\n\n            if (break_loop)\n            {\n               parse_pending_string_rangesize(expression);\n               break;\n            }\n            else if (current_state.left < precedence)\n               break;\n\n            lexer::token prev_token = current_token();\n\n            next_token();\n\n            expression_node_ptr right_branch   = error_node();\n            expression_node_ptr new_expression = error_node();\n\n            if (is_invalid_arithmetic_operation(current_state.operation))\n            {\n               free_node(node_allocator_,expression);\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             prev_token,\n                             \"ERR008 - Invalid arithmetic operation '\" + details::to_str(current_state.operation) + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else if (is_invalid_inequality_operation(current_state.operation))\n            {\n               free_node(node_allocator_,expression);\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             prev_token,\n                             \"ERR009 - Invalid inequality operation '\" + details::to_str(current_state.operation) + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else if (is_invalid_assignment_operation(current_state.operation))\n            {\n               free_node(node_allocator_,expression);\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             prev_token,\n                             \"ERR010 - Invalid assignment operation '\" + details::to_str(current_state.operation) + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            if (0 != (right_branch = parse_expression(current_state.right)))\n            {\n               if (\n                    details::is_return_node(  expression) ||\n                    details::is_return_node(right_branch)\n                  )\n               {\n                  free_node(node_allocator_,  expression);\n                  free_node(node_allocator_,right_branch);\n\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                prev_token,\n                                \"ERR011 - Return statements cannot be part of sub-expressions\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               new_expression = expression_generator_\n                                  (\n                                    current_state.operation,\n                                    expression,\n                                    right_branch\n                                  );\n            }\n\n            if (0 == new_expression)\n            {\n               if (error_list_.empty())\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                prev_token,\n                                !synthesis_error_.empty() ?\n                                synthesis_error_ :\n                                \"ERR012 - General parsing error at token: '\" + prev_token.value + \"'\",\n                                exprtk_error_location));\n               }\n\n               free_node(node_allocator_,expression);\n\n               return error_node();\n            }\n            else\n            {\n               if (\n                    token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&\n                    (precedence == e_level00)\n                  )\n               {\n                  expression = parse_ternary_conditional_statement(new_expression);\n               }\n               else\n                  expression = new_expression;\n\n               parse_pending_string_rangesize(expression);\n            }\n         }\n\n         return expression;\n      }\n\n      bool simplify_unary_negation_branch(expression_node_ptr& node)\n      {\n         {\n            typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;\n            ubn_t* n = dynamic_cast<ubn_t*>(node);\n\n            if (n)\n            {\n               expression_node_ptr un_r = n->branch(0);\n               n->release();\n               free_node(node_allocator_,node);\n               node = un_r;\n\n               return true;\n            }\n         }\n\n         {\n            typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;\n\n            uvn_t* n = dynamic_cast<uvn_t*>(node);\n\n            if (n)\n            {\n               const T& v = n->v();\n               expression_node_ptr return_node = error_node();\n\n               if (\n                    (0 != (return_node = symtab_store_.get_variable(v))) ||\n                    (0 != (return_node = sem_         .get_variable(v)))\n                  )\n               {\n                  free_node(node_allocator_,node);\n                  node = return_node;\n\n                  return true;\n               }\n               else\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR013 - Failed to find variable node in symbol table\",\n                                exprtk_error_location));\n\n                  free_node(node_allocator_,node);\n\n                  return false;\n               }\n            }\n         }\n\n         return false;\n      }\n\n      static inline expression_node_ptr error_node()\n      {\n         return reinterpret_cast<expression_node_ptr>(0);\n      }\n\n      template <typename Type, std::size_t N>\n      struct scoped_delete\n      {\n         typedef Type* ptr_t;\n\n         scoped_delete(parser<T>& pr, ptr_t& p)\n         : delete_ptr(true),\n           parser_(pr),\n           p_(&p)\n         {}\n\n         scoped_delete(parser<T>& pr, ptr_t (&p)[N])\n         : delete_ptr(true),\n           parser_(pr),\n           p_(&p[0])\n         {}\n\n        ~scoped_delete()\n         {\n            if (delete_ptr)\n            {\n               for (std::size_t i = 0; i < N; ++i)\n               {\n                  free_node(parser_.node_allocator_,p_[i]);\n               }\n            }\n         }\n\n         bool delete_ptr;\n         parser<T>& parser_;\n         ptr_t* p_;\n\n      private:\n\n         scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);\n      };\n\n      template <typename Type>\n      struct scoped_deq_delete\n      {\n         typedef Type* ptr_t;\n\n         scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)\n         : delete_ptr(true),\n           parser_(pr),\n           deq_(deq)\n         {}\n\n        ~scoped_deq_delete()\n         {\n            if (delete_ptr && !deq_.empty())\n            {\n               for (std::size_t i = 0; i < deq_.size(); ++i)\n               {\n                  free_node(parser_.node_allocator_,deq_[i]);\n               }\n\n               deq_.clear();\n            }\n         }\n\n         bool delete_ptr;\n         parser<T>& parser_;\n         std::deque<ptr_t>& deq_;\n\n      private:\n\n         scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);\n      };\n\n      template <typename Type>\n      struct scoped_vec_delete\n      {\n         typedef Type* ptr_t;\n\n         scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)\n         : delete_ptr(true),\n           parser_(pr),\n           vec_(vec)\n         {}\n\n        ~scoped_vec_delete()\n         {\n            if (delete_ptr && !vec_.empty())\n            {\n               for (std::size_t i = 0; i < vec_.size(); ++i)\n               {\n                  free_node(parser_.node_allocator_,vec_[i]);\n               }\n\n               vec_.clear();\n            }\n         }\n\n         bool delete_ptr;\n         parser<T>& parser_;\n         std::vector<ptr_t>& vec_;\n\n      private:\n\n         scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);\n      };\n\n      struct scoped_bool_negator\n      {\n         scoped_bool_negator(bool& bb)\n         : b(bb)\n         { b = !b; }\n\n        ~scoped_bool_negator()\n         { b = !b; }\n\n         bool& b;\n      };\n\n      struct scoped_bool_or_restorer\n      {\n         scoped_bool_or_restorer(bool& bb)\n         : b(bb),\n           original_value_(bb)\n         {}\n\n        ~scoped_bool_or_restorer()\n         {\n            b = b || original_value_;\n         }\n\n         bool& b;\n         bool original_value_;\n      };\n\n      inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)\n      {\n         expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);\n\n         switch (function->param_count)\n         {\n            case  0 : func_node = parse_function_call_0  (function,function_name); break;\n            case  1 : func_node = parse_function_call< 1>(function,function_name); break;\n            case  2 : func_node = parse_function_call< 2>(function,function_name); break;\n            case  3 : func_node = parse_function_call< 3>(function,function_name); break;\n            case  4 : func_node = parse_function_call< 4>(function,function_name); break;\n            case  5 : func_node = parse_function_call< 5>(function,function_name); break;\n            case  6 : func_node = parse_function_call< 6>(function,function_name); break;\n            case  7 : func_node = parse_function_call< 7>(function,function_name); break;\n            case  8 : func_node = parse_function_call< 8>(function,function_name); break;\n            case  9 : func_node = parse_function_call< 9>(function,function_name); break;\n            case 10 : func_node = parse_function_call<10>(function,function_name); break;\n            case 11 : func_node = parse_function_call<11>(function,function_name); break;\n            case 12 : func_node = parse_function_call<12>(function,function_name); break;\n            case 13 : func_node = parse_function_call<13>(function,function_name); break;\n            case 14 : func_node = parse_function_call<14>(function,function_name); break;\n            case 15 : func_node = parse_function_call<15>(function,function_name); break;\n            case 16 : func_node = parse_function_call<16>(function,function_name); break;\n            case 17 : func_node = parse_function_call<17>(function,function_name); break;\n            case 18 : func_node = parse_function_call<18>(function,function_name); break;\n            case 19 : func_node = parse_function_call<19>(function,function_name); break;\n            case 20 : func_node = parse_function_call<20>(function,function_name); break;\n            default : {\n                         set_error(\n                            make_error(parser_error::e_syntax,\n                                       current_token(),\n                                       \"ERR014 - Invalid number of parameters for function: '\" + function_name + \"'\",\n                                       exprtk_error_location));\n\n                         return error_node();\n                      }\n         }\n\n         if (func_node)\n            return func_node;\n         else\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR015 - Failed to generate call to function: '\" + function_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n      }\n\n      template <std::size_t NumberofParameters>\n      inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)\n      {\n         #ifdef _MSC_VER\n            #pragma warning(push)\n            #pragma warning(disable: 4127)\n         #endif\n         if (0 == NumberofParameters)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR016 - Expecting ifunction '\" + function_name + \"' to have non-zero parameter count\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         #ifdef _MSC_VER\n            #pragma warning(pop)\n         #endif\n\n         expression_node_ptr branch[NumberofParameters];\n         expression_node_ptr result  = error_node();\n\n         std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));\n\n         scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);\n\n         next_token();\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR017 - Expecting argument list for function: '\" + function_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)\n         {\n            branch[i] = parse_expression();\n\n            if (0 == branch[i])\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR018 - Failed to parse argument \" + details::to_str(i) + \" for function: '\" + function_name + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else if (i < static_cast<int>(NumberofParameters - 1))\n            {\n               if (!token_is(token_t::e_comma))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR019 - Invalid number of arguments for function: '\" + function_name + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n         }\n\n         if (!token_is(token_t::e_rbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR020 - Invalid number of arguments for function: '\" + function_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else\n            result = expression_generator_.function(function,branch);\n\n         sd.delete_ptr = false;\n\n         return result;\n      }\n\n      inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)\n      {\n         expression_node_ptr result = expression_generator_.function(function);\n\n         state_.side_effect_present = function->has_side_effects();\n\n         next_token();\n\n         if (\n               token_is(token_t::e_lbracket) &&\n              !token_is(token_t::e_rbracket)\n            )\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR021 - Expecting '()' to proceed call to function: '\" + function_name + \"'\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,result);\n\n            return error_node();\n         }\n         else\n            return result;\n      }\n\n      template <std::size_t MaxNumberofParameters>\n      inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = \"\")\n      {\n         std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));\n\n         scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);\n\n         next_token();\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR022 - Expected a '(' at start of function call to '\" + function_name  +\n                          \"', instead got: '\" + current_token().value + \"'\",\n                          exprtk_error_location));\n\n            return 0;\n         }\n\n         if (token_is(token_t::e_rbracket, e_hold))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR023 - Expected at least one input parameter for function call '\" + function_name + \"'\",\n                          exprtk_error_location));\n\n            return 0;\n         }\n\n         std::size_t param_index = 0;\n\n         for (; param_index < MaxNumberofParameters; ++param_index)\n         {\n            param_list[param_index] = parse_expression();\n\n            if (0 == param_list[param_index])\n               return 0;\n            else if (token_is(token_t::e_rbracket))\n            {\n               sd.delete_ptr = false;\n               break;\n            }\n            else if (token_is(token_t::e_comma))\n               continue;\n            else\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR024 - Expected a ',' between function input parameters, instead got: '\" + current_token().value + \"'\",\n                             exprtk_error_location));\n\n               return 0;\n            }\n         }\n\n         if (sd.delete_ptr)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR025 - Invalid number of input parameters passed to function '\" + function_name  + \"'\",\n                          exprtk_error_location));\n\n            return 0;\n         }\n\n         return (param_index + 1);\n      }\n\n      inline expression_node_ptr parse_base_operation()\n      {\n         typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;\n\n         const std::string operation_name   = current_token().value;\n         const token_t     diagnostic_token = current_token();\n\n         map_range_t itr_range = base_ops_map_.equal_range(operation_name);\n\n         if (0 == std::distance(itr_range.first,itr_range.second))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          diagnostic_token,\n                          \"ERR026 - No entry found for base operation: \" + operation_name,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         static const std::size_t MaxNumberofParameters = 4;\n         expression_node_ptr param_list[MaxNumberofParameters] = {0};\n\n         const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);\n\n         if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))\n         {\n            for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)\n            {\n               details::base_operation_t& operation = itr->second;\n\n               if (operation.num_params == parameter_count)\n               {\n                  switch (parameter_count)\n                  {\n                     #define base_opr_case(N)                                         \\\n                     case N : {                                                       \\\n                                 expression_node_ptr pl##N[N] = {0};                  \\\n                                 std::copy(param_list, param_list + N, pl##N);        \\\n                                 lodge_symbol(operation_name, e_st_function);         \\\n                                 return expression_generator_(operation.type, pl##N); \\\n                              }                                                       \\\n\n                     base_opr_case(1)\n                     base_opr_case(2)\n                     base_opr_case(3)\n                     base_opr_case(4)\n                     #undef base_opr_case\n                  }\n               }\n            }\n         }\n\n         for (std::size_t i = 0; i < MaxNumberofParameters; ++i)\n         {\n            free_node(node_allocator_, param_list[i]);\n         }\n\n         set_error(\n            make_error(parser_error::e_syntax,\n                       diagnostic_token,\n                       \"ERR027 - Invalid number of input parameters for call to function: '\" + operation_name + \"'\",\n                       exprtk_error_location));\n\n         return error_node();\n      }\n\n      inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)\n      {\n         // Parse: [if][(][condition][,][consequent][,][alternative][)]\n\n         expression_node_ptr consequent  = error_node();\n         expression_node_ptr alternative = error_node();\n\n         bool result = true;\n\n         if (!token_is(token_t::e_comma))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR028 - Expected ',' between if-statement condition and consequent\",\n                          exprtk_error_location));\n            result = false;\n         }\n         else if (0 == (consequent = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR029 - Failed to parse consequent for if-statement\",\n                          exprtk_error_location));\n            result = false;\n         }\n         else if (!token_is(token_t::e_comma))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR030 - Expected ',' between if-statement consequent and alternative\",\n                          exprtk_error_location));\n            result = false;\n         }\n         else if (0 == (alternative = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR031 - Failed to parse alternative for if-statement\",\n                          exprtk_error_location));\n            result = false;\n         }\n         else if (!token_is(token_t::e_rbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR032 - Expected ')' at the end of if-statement\",\n                          exprtk_error_location));\n            result = false;\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         if (result)\n         {\n            const bool consq_is_str = is_generally_string_node( consequent);\n            const bool alter_is_str = is_generally_string_node(alternative);\n\n            if (consq_is_str || alter_is_str)\n            {\n               if (consq_is_str && alter_is_str)\n               {\n                  return expression_generator_\n                           .conditional_string(condition,consequent,alternative);\n               }\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR033 - Return types of ternary if-statement differ\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n         #endif\n\n         if (!result)\n         {\n            free_node(node_allocator_,  condition);\n            free_node(node_allocator_, consequent);\n            free_node(node_allocator_,alternative);\n\n            return error_node();\n         }\n         else\n            return expression_generator_\n                      .conditional(condition,consequent,alternative);\n      }\n\n      inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)\n      {\n         expression_node_ptr consequent  = error_node();\n         expression_node_ptr alternative = error_node();\n\n         bool result = true;\n\n         if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))\n         {\n            if (0 == (consequent = parse_multi_sequence(\"if-statement-01\")))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR034 - Failed to parse body of consequent for if-statement\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n         else\n         {\n            if (\n                 settings_.commutative_check_enabled() &&\n                 token_is(token_t::e_mul,prsrhlpr_t::e_hold)\n               )\n            {\n               next_token();\n            }\n\n            if (0 != (consequent = parse_expression()))\n            {\n               if (!token_is(token_t::e_eof))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR035 - Expected ';' at the end of the consequent for if-statement\",\n                                exprtk_error_location));\n\n                  result = false;\n               }\n            }\n            else\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR036 - Failed to parse body of consequent for if-statement\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n\n         if (result)\n         {\n            if (details::imatch(current_token().value,\"else\"))\n            {\n               next_token();\n\n               if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))\n               {\n                  if (0 == (alternative = parse_multi_sequence(\"else-statement-01\")))\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR037 - Failed to parse body of the 'else' for if-statement\",\n                                   exprtk_error_location));\n\n                     result = false;\n                  }\n               }\n               else if (details::imatch(current_token().value,\"if\"))\n               {\n                  if (0 == (alternative = parse_conditional_statement()))\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR038 - Failed to parse body of if-else statement\",\n                                   exprtk_error_location));\n\n                     result = false;\n                  }\n               }\n               else if (0 != (alternative = parse_expression()))\n               {\n                  if (!token_is(token_t::e_eof))\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR039 - Expected ';' at the end of the 'else-if' for the if-statement\",\n                                   exprtk_error_location));\n\n                     result = false;\n                  }\n               }\n               else\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR040 - Failed to parse body of the 'else' for if-statement\",\n                                exprtk_error_location));\n\n                  result = false;\n               }\n            }\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         if (result)\n         {\n            const bool consq_is_str = is_generally_string_node( consequent);\n            const bool alter_is_str = is_generally_string_node(alternative);\n\n            if (consq_is_str || alter_is_str)\n            {\n               if (consq_is_str && alter_is_str)\n               {\n                  return expression_generator_\n                           .conditional_string(condition,consequent,alternative);\n               }\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR041 - Return types of ternary if-statement differ\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n         #endif\n\n         if (!result)\n         {\n            free_node(node_allocator_,  condition);\n            free_node(node_allocator_, consequent);\n            free_node(node_allocator_,alternative);\n\n            return error_node();\n         }\n         else\n            return expression_generator_\n                      .conditional(condition,consequent,alternative);\n      }\n\n      inline expression_node_ptr parse_conditional_statement()\n      {\n         expression_node_ptr condition = error_node();\n\n         next_token();\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR042 - Expected '(' at start of if-statement, instead got: '\" + current_token().value + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (0 == (condition = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR043 - Failed to parse condition for if-statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))\n         {\n            // if (x,y,z)\n            return parse_conditional_statement_01(condition);\n         }\n         else if (token_is(token_t::e_rbracket))\n         {\n            // 00. if (x) y;\n            // 01. if (x) y; else z;\n            // 02. if (x) y; else {z0; ... zn;}\n            // 03. if (x) y; else if (z) w;\n            // 04. if (x) y; else if (z) w; else u;\n            // 05. if (x) y; else if (z) w; else {u0; ... un;}\n            // 06. if (x) y; else if (z) {w0; ... wn;}\n            // 07. if (x) {y0; ... yn;}\n            // 08. if (x) {y0; ... yn;} else z;\n            // 09. if (x) {y0; ... yn;} else {z0; ... zn;};\n            // 10. if (x) {y0; ... yn;} else if (z) w;\n            // 11. if (x) {y0; ... yn;} else if (z) w; else u;\n            // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}\n            // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}\n            return parse_conditional_statement_02(condition);\n         }\n\n         set_error(\n            make_error(parser_error::e_syntax,\n                       current_token(),\n                       \"ERR044 - Invalid if-statement\",\n                       exprtk_error_location));\n\n         free_node(node_allocator_,condition);\n\n         return error_node();\n      }\n\n      inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)\n      {\n         // Parse: [condition][?][consequent][:][alternative]\n         expression_node_ptr consequent  = error_node();\n         expression_node_ptr alternative = error_node();\n\n         bool result = true;\n\n         if (0 == condition)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR045 - Encountered invalid condition branch for ternary if-statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_ternary))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR046 - Expected '?' after condition of ternary if-statement\",\n                          exprtk_error_location));\n\n            result = false;\n         }\n         else if (0 == (consequent = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR047 - Failed to parse consequent for ternary if-statement\",\n                          exprtk_error_location));\n\n            result = false;\n         }\n         else if (!token_is(token_t::e_colon))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR048 - Expected ':' between ternary if-statement consequent and alternative\",\n                          exprtk_error_location));\n\n            result = false;\n         }\n         else if (0 == (alternative = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR049 - Failed to parse alternative for ternary if-statement\",\n                          exprtk_error_location));\n\n            result = false;\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         if (result)\n         {\n            const bool consq_is_str = is_generally_string_node( consequent);\n            const bool alter_is_str = is_generally_string_node(alternative);\n\n            if (consq_is_str || alter_is_str)\n            {\n               if (consq_is_str && alter_is_str)\n               {\n                  return expression_generator_\n                           .conditional_string(condition, consequent, alternative);\n               }\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR050 - Return types of ternary if-statement differ\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n         #endif\n\n         if (!result)\n         {\n            free_node(node_allocator_,   condition);\n            free_node(node_allocator_,  consequent);\n            free_node(node_allocator_, alternative);\n\n            return error_node();\n         }\n         else\n            return expression_generator_\n                      .conditional(condition, consequent, alternative);\n      }\n\n      inline expression_node_ptr parse_while_loop()\n      {\n         // Parse: [while][(][test expr][)][{][expression][}]\n         expression_node_ptr condition   = error_node();\n         expression_node_ptr branch      = error_node();\n         expression_node_ptr result_node = error_node();\n\n         bool result = true;\n\n         next_token();\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR051 - Expected '(' at start of while-loop condition statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (0 == (condition = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR052 - Failed to parse condition for while-loop\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_rbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR053 - Expected ')' at end of while-loop condition statement\",\n                          exprtk_error_location));\n\n            result = false;\n         }\n\n         brkcnt_list_.push_front(false);\n\n         if (result)\n         {\n            if (0 == (branch = parse_multi_sequence(\"while-loop\")))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR054 - Failed to parse body of while-loop\"));\n               result = false;\n            }\n            else if (0 == (result_node = expression_generator_.while_loop(condition,\n                                                                          branch,\n                                                                          brkcnt_list_.front())))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR055 - Failed to synthesize while-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n\n         if (!result)\n         {\n            free_node(node_allocator_,     branch);\n            free_node(node_allocator_,  condition);\n            free_node(node_allocator_,result_node);\n\n            brkcnt_list_.pop_front();\n\n            return error_node();\n         }\n         else\n            return result_node;\n      }\n\n      inline expression_node_ptr parse_repeat_until_loop()\n      {\n         // Parse: [repeat][{][expression][}][until][(][test expr][)]\n         expression_node_ptr condition = error_node();\n         expression_node_ptr branch    = error_node();\n         next_token();\n\n         std::vector<expression_node_ptr> arg_list;\n         std::vector<bool> side_effect_list;\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         brkcnt_list_.push_front(false);\n\n         if (details::imatch(current_token().value,\"until\"))\n         {\n            next_token();\n            branch = node_allocator_.allocate<details::null_node<T> >();\n         }\n         else\n         {\n            token_t::token_type seperator = token_t::e_eof;\n\n            scope_handler sh(*this);\n\n            scoped_bool_or_restorer sbr(state_.side_effect_present);\n\n            for ( ; ; )\n            {\n               state_.side_effect_present = false;\n\n               expression_node_ptr arg = parse_expression();\n\n               if (0 == arg)\n                  return error_node();\n               else\n               {\n                  arg_list.push_back(arg);\n                  side_effect_list.push_back(state_.side_effect_present);\n               }\n\n               if (details::imatch(current_token().value,\"until\"))\n               {\n                  next_token();\n                  break;\n               }\n\n               bool is_next_until = peek_token_is(token_t::e_symbol) &&\n                                    peek_token_is(\"until\");\n\n               if (!token_is(seperator) && is_next_until)\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR056 - Expected '\" + token_t::to_str(seperator) + \"' in body of repeat until loop\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               if (details::imatch(current_token().value,\"until\"))\n               {\n                  next_token();\n                  break;\n               }\n            }\n\n            branch = simplify(arg_list,side_effect_list);\n\n            sdd.delete_ptr = (0 == branch);\n\n            if (sdd.delete_ptr)\n            {\n               brkcnt_list_.pop_front();\n\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR057 - Failed to parse body of repeat until loop\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            brkcnt_list_.pop_front();\n\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR058 - Expected '(' before condition statement of repeat until loop\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,branch);\n\n            return error_node();\n         }\n         else if (0 == (condition = parse_expression()))\n         {\n            brkcnt_list_.pop_front();\n\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR059 - Failed to parse condition for repeat until loop\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,branch);\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_rbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR060 - Expected ')' after condition of repeat until loop\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,    branch);\n            free_node(node_allocator_, condition);\n\n            brkcnt_list_.pop_front();\n\n            return error_node();\n         }\n\n         expression_node_ptr result;\n\n         result = expression_generator_\n                     .repeat_until_loop(condition, branch, brkcnt_list_.front());\n\n         if (0 == result)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR061 - Failed to synthesize repeat until loop\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,condition);\n\n            brkcnt_list_.pop_front();\n\n            return error_node();\n         }\n         else\n         {\n            brkcnt_list_.pop_front();\n            return result;\n         }\n      }\n\n      inline expression_node_ptr parse_for_loop()\n      {\n         expression_node_ptr initialiser = error_node();\n         expression_node_ptr condition   = error_node();\n         expression_node_ptr incrementor = error_node();\n         expression_node_ptr loop_body   = error_node();\n\n         scope_element* se = 0;\n         bool result       = true;\n         std::string loop_counter_symbol;\n\n         next_token();\n\n         scope_handler sh(*this);\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR062 - Expected '(' at start of for-loop\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         if (!token_is(token_t::e_eof))\n         {\n            if (\n                 !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&\n                 details::imatch(current_token().value,\"var\")\n               )\n            {\n               next_token();\n\n               if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR063 - Expected a variable at the start of initialiser section of for-loop\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n               else if (!peek_token_is(token_t::e_assign))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR064 - Expected variable assignment of initialiser section of for-loop\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               loop_counter_symbol = current_token().value;\n\n               se = &sem_.get_element(loop_counter_symbol);\n\n               if ((se->name == loop_counter_symbol) && se->active)\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR065 - For-loop variable '\" + loop_counter_symbol+ \"' is being shadowed by a previous declaration\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n               else if (!symtab_store_.is_variable(loop_counter_symbol))\n               {\n                  if (\n                       !se->active &&\n                       (se->name == loop_counter_symbol) &&\n                       (se->type ==  scope_element::e_variable)\n                     )\n                  {\n                     se->active = true;\n                     se->ref_count++;\n                  }\n                  else\n                  {\n                     scope_element nse;\n                     nse.name      = loop_counter_symbol;\n                     nse.active    = true;\n                     nse.ref_count = 1;\n                     nse.type      = scope_element::e_variable;\n                     nse.depth     = state_.scope_depth;\n                     nse.data      = new T(T(0));\n                     nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));\n\n                     if (!sem_.add_element(nse))\n                     {\n                        set_error(\n                           make_error(parser_error::e_syntax,\n                                      current_token(),\n                                      \"ERR066 - Failed to add new local variable '\" + loop_counter_symbol + \"' to SEM\",\n                                      exprtk_error_location));\n\n                        sem_.free_element(nse);\n\n                        result = false;\n                     }\n                     else\n                     {\n                        exprtk_debug((\"parse_for_loop() - INFO - Added new local variable: %s\\n\",nse.name.c_str()));\n\n                        state_.activate_side_effect(\"parse_for_loop()\");\n                     }\n                  }\n               }\n            }\n\n            if (0 == (initialiser = parse_expression()))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR067 - Failed to parse initialiser of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n            else if (!token_is(token_t::e_eof))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR068 - Expected ';' after initialiser of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n\n         if (!token_is(token_t::e_eof))\n         {\n            if (0 == (condition = parse_expression()))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR069 - Failed to parse condition of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n            else if (!token_is(token_t::e_eof))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR070 - Expected ';' after condition section of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n\n         if (!token_is(token_t::e_rbracket))\n         {\n            if (0 == (incrementor = parse_expression()))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR071 - Failed to parse incrementor of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n            else if (!token_is(token_t::e_rbracket))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR072 - Expected ')' after incrementor section of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n\n         if (result)\n         {\n            brkcnt_list_.push_front(false);\n\n            if (0 == (loop_body = parse_multi_sequence(\"for-loop\")))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR073 - Failed to parse body of for-loop\",\n                             exprtk_error_location));\n\n               result = false;\n            }\n         }\n\n         if (!result)\n         {\n            if (se)\n            {\n               se->ref_count--;\n            }\n\n            sem_.cleanup();\n\n            free_node(node_allocator_, initialiser);\n            free_node(node_allocator_,   condition);\n            free_node(node_allocator_, incrementor);\n            free_node(node_allocator_,   loop_body);\n\n            if (!brkcnt_list_.empty())\n            {\n               brkcnt_list_.pop_front();\n            }\n\n            return error_node();\n         }\n         else\n         {\n            expression_node_ptr result_node =\n               expression_generator_.for_loop(initialiser,\n                                              condition,\n                                              incrementor,\n                                              loop_body,\n                                              brkcnt_list_.front());\n            brkcnt_list_.pop_front();\n\n            return result_node;\n         }\n      }\n\n      inline expression_node_ptr parse_switch_statement()\n      {\n         std::vector<expression_node_ptr> arg_list;\n         expression_node_ptr result = error_node();\n\n         if (!details::imatch(current_token().value,\"switch\"))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR074 - Expected keyword 'switch'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         scoped_vec_delete<expression_node_t> svd((*this),arg_list);\n\n         next_token();\n\n         if (!token_is(token_t::e_lcrlbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR075 - Expected '{' for call to switch statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         for ( ; ; )\n         {\n            if (!details::imatch(\"case\",current_token().value))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR076 - Expected either a 'case' or 'default' statement\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            next_token();\n\n            expression_node_ptr condition = parse_expression();\n\n            if (0 == condition)\n               return error_node();\n            else if (!token_is(token_t::e_colon))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR077 - Expected ':' for case of switch statement\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            expression_node_ptr consequent = parse_expression();\n\n            if (0 == consequent)\n               return error_node();\n            else if (!token_is(token_t::e_eof))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR078 - Expected ';' at end of case for switch statement\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            // Can we optimise away the case statement?\n            if (is_constant_node(condition) && is_false(condition))\n            {\n               free_node(node_allocator_,  condition);\n               free_node(node_allocator_, consequent);\n            }\n            else\n            {\n               arg_list.push_back( condition);\n               arg_list.push_back(consequent);\n            }\n\n            if (details::imatch(\"default\",current_token().value))\n            {\n               next_token();\n               if (!token_is(token_t::e_colon))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR079 - Expected ':' for default of switch statement\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               expression_node_ptr default_statement = error_node();\n\n               if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))\n                  default_statement = parse_multi_sequence(\"switch-default\");\n               else\n                  default_statement = parse_expression();\n\n               if (0 == default_statement)\n                  return error_node();\n               else if (!token_is(token_t::e_eof))\n               {\n                  free_node(node_allocator_,default_statement);\n\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR080 - Expected ';' at end of default for switch statement\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               arg_list.push_back(default_statement);\n               break;\n            }\n         }\n\n         if (!token_is(token_t::e_rcrlbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR081 - Expected '}' at end of switch statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         result = expression_generator_.switch_statement(arg_list);\n\n         svd.delete_ptr = (0 == result);\n\n         return result;\n      }\n\n      inline expression_node_ptr parse_multi_switch_statement()\n      {\n         std::vector<expression_node_ptr> arg_list;\n         expression_node_ptr result = error_node();\n\n         if (!details::imatch(current_token().value,\"[*]\"))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR082 - Expected token '[*]'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         scoped_vec_delete<expression_node_t> svd((*this),arg_list);\n\n         next_token();\n\n         if (!token_is(token_t::e_lcrlbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR083 - Expected '{' for call to [*] statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         for ( ; ; )\n         {\n            if (!details::imatch(\"case\",current_token().value))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR084 - Expected a 'case' statement for multi-switch\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            next_token();\n\n            expression_node_ptr condition = parse_expression();\n\n            if (0 == condition)\n               return error_node();\n\n            if (!token_is(token_t::e_colon))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR085 - Expected ':' for case of [*] statement\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            expression_node_ptr consequent = parse_expression();\n\n            if (0 == consequent)\n               return error_node();\n\n            if (!token_is(token_t::e_eof))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR086 - Expected ';' at end of case for [*] statement\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            // Can we optimise away the case statement?\n            if (is_constant_node(condition) && is_false(condition))\n            {\n               free_node(node_allocator_,  condition);\n               free_node(node_allocator_, consequent);\n            }\n            else\n            {\n               arg_list.push_back(condition);\n               arg_list.push_back(consequent);\n            }\n\n            if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))\n            {\n               break;\n            }\n         }\n\n         if (!token_is(token_t::e_rcrlbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR087 - Expected '}' at end of [*] statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         result = expression_generator_.multi_switch_statement(arg_list);\n\n         svd.delete_ptr = (0 == result);\n\n         return result;\n      }\n\n      inline expression_node_ptr parse_vararg_function()\n      {\n         std::vector<expression_node_ptr> arg_list;\n         expression_node_ptr result = error_node();\n\n         details::operator_type opt_type = details::e_default;\n         const std::string symbol = current_token().value;\n\n         if (details::imatch(symbol,\"~\"))\n         {\n            next_token();\n            return parse_multi_sequence();\n         }\n         else if (details::imatch(symbol,\"[*]\"))\n         {\n            return parse_multi_switch_statement();\n         }\n         else if (details::imatch(symbol,\"avg\" )) opt_type = details::e_avg ;\n         else if (details::imatch(symbol,\"mand\")) opt_type = details::e_mand;\n         else if (details::imatch(symbol,\"max\" )) opt_type = details::e_max ;\n         else if (details::imatch(symbol,\"min\" )) opt_type = details::e_min ;\n         else if (details::imatch(symbol,\"mor\" )) opt_type = details::e_mor ;\n         else if (details::imatch(symbol,\"mul\" )) opt_type = details::e_prod;\n         else if (details::imatch(symbol,\"sum\" )) opt_type = details::e_sum ;\n         else\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR088 - Unsupported vararg function: \" + symbol,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         lodge_symbol(symbol,e_st_function);\n\n         next_token();\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR089 - Expected '(' for call to vararg function: \" + symbol,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         for ( ; ; )\n         {\n            expression_node_ptr arg = parse_expression();\n\n            if (0 == arg)\n               return error_node();\n            else\n               arg_list.push_back(arg);\n\n            if (token_is(token_t::e_rbracket))\n               break;\n            else if (!token_is(token_t::e_comma))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR090 - Expected ',' for call to vararg function: \" + symbol,\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n\n         result = expression_generator_.vararg_function(opt_type,arg_list);\n\n         sdd.delete_ptr = (0 == result);\n         return result;\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)\n      {\n         if (!token_is(token_t::e_lsqrbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR091 - Expected '[' as start of string range definition\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,expression);\n\n            return error_node();\n         }\n         else if (token_is(token_t::e_rsqrbracket))\n         {\n            return node_allocator_.allocate<details::string_size_node<T> >(expression);\n         }\n\n         range_t rp;\n\n         if (!parse_range(rp,true))\n         {\n            free_node(node_allocator_,expression);\n\n            return error_node();\n         }\n\n         expression_node_ptr result = expression_generator_(expression,rp);\n\n         if (0 == result)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR092 - Failed to generate string range node\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,expression);\n         }\n\n         rp.clear();\n\n         return result;\n      }\n      #else\n      inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)\n      {\n         return error_node();\n      }\n      #endif\n\n      inline void parse_pending_string_rangesize(expression_node_ptr& expression)\n      {\n         // Allow no more than 100 range calls, eg: s[][][]...[][]\n         const std::size_t max_rangesize_parses = 100;\n\n         std::size_t i = 0;\n\n         while\n            (\n              (0 != expression)                     &&\n              (i++ < max_rangesize_parses)          &&\n              error_list_.empty()                   &&\n              is_generally_string_node(expression)  &&\n              token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)\n            )\n         {\n            expression = parse_string_range_statement(expression);\n         }\n      }\n\n      template <typename Allocator1,\n                typename Allocator2,\n                template <typename,typename> class Sequence>\n      inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,\n                                          Sequence<bool,Allocator2>& side_effect_list,\n                                          const bool specialise_on_final_type = false)\n      {\n         if (expression_list.empty())\n            return error_node();\n         else if (1 == expression_list.size())\n            return expression_list[0];\n\n         Sequence<expression_node_ptr,Allocator1> tmp_expression_list;\n\n         bool return_node_present = false;\n\n         for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)\n         {\n            if (is_variable_node(expression_list[i]))\n               continue;\n            else if (\n                      is_return_node  (expression_list[i]) ||\n                      is_break_node   (expression_list[i]) ||\n                      is_continue_node(expression_list[i])\n                    )\n            {\n               tmp_expression_list.push_back(expression_list[i]);\n\n               // Remove all subexpressions after first short-circuit\n               // node has been encountered.\n\n               for (std::size_t j = i + 1; j < expression_list.size(); ++j)\n               {\n                  free_node(node_allocator_,expression_list[j]);\n               }\n\n               return_node_present = true;\n\n               break;\n            }\n            else if (\n                      is_constant_node(expression_list[i]) ||\n                      is_null_node    (expression_list[i]) ||\n                      !side_effect_list[i]\n                    )\n            {\n               free_node(node_allocator_,expression_list[i]);\n               continue;\n            }\n            else\n               tmp_expression_list.push_back(expression_list[i]);\n         }\n\n         if (!return_node_present)\n         {\n            tmp_expression_list.push_back(expression_list.back());\n         }\n\n         expression_list.swap(tmp_expression_list);\n\n         if (tmp_expression_list.size() > expression_list.size())\n         {\n            exprtk_debug((\"simplify() - Reduced subexpressions from %d to %d\\n\",\n                          static_cast<int>(tmp_expression_list.size()),\n                          static_cast<int>(expression_list    .size())));\n         }\n\n         if (\n              return_node_present          ||\n              side_effect_list.back()      ||\n              (expression_list.size() > 1)\n            )\n            state_.activate_side_effect(\"simplify()\");\n\n         if (1 == expression_list.size())\n            return expression_list[0];\n         else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))\n            return expression_generator_.vararg_function(details::e_smulti,expression_list);\n         else\n            return expression_generator_.vararg_function(details::e_multi,expression_list);\n      }\n\n      inline expression_node_ptr parse_multi_sequence(const std::string& source = \"\")\n      {\n         token_t::token_type close_bracket = token_t::e_rcrlbracket;\n         token_t::token_type seperator     = token_t::e_eof;\n\n         if (!token_is(token_t::e_lcrlbracket))\n         {\n            if (token_is(token_t::e_lbracket))\n            {\n               close_bracket = token_t::e_rbracket;\n               seperator     = token_t::e_comma;\n            }\n            else\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR093 - Expected '\" + token_t::to_str(close_bracket) + \"' for call to multi-sequence\" +\n                             ((!source.empty()) ? std::string(\" section of \" + source): \"\"),\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n         else if (token_is(token_t::e_rcrlbracket))\n         {\n            return node_allocator_.allocate<details::null_node<T> >();\n         }\n\n         std::vector<expression_node_ptr> arg_list;\n         std::vector<bool> side_effect_list;\n\n         expression_node_ptr result = error_node();\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         scope_handler sh(*this);\n\n         scoped_bool_or_restorer sbr(state_.side_effect_present);\n\n         for ( ; ; )\n         {\n            state_.side_effect_present = false;\n\n            expression_node_ptr arg = parse_expression();\n\n            if (0 == arg)\n               return error_node();\n            else\n            {\n               arg_list.push_back(arg);\n               side_effect_list.push_back(state_.side_effect_present);\n            }\n\n            if (token_is(close_bracket))\n               break;\n\n            bool is_next_close = peek_token_is(close_bracket);\n\n            if (!token_is(seperator) && is_next_close)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR094 - Expected '\" + details::to_str(seperator) + \"' for call to multi-sequence section of \" + source,\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            if (token_is(close_bracket))\n               break;\n         }\n\n         result = simplify(arg_list,side_effect_list,source.empty());\n\n         sdd.delete_ptr = (0 == result);\n         return result;\n      }\n\n      inline bool parse_range(range_t& rp, const bool skip_lsqr = false)\n      {\n         // Examples of valid ranges:\n         // 1. [1:5]     -> 1..5\n         // 2. [ :5]     -> 0..5\n         // 3. [1: ]     -> 1..end\n         // 4. [x:y]     -> x..y where x <= y\n         // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2\n         // 6. [ :y]     -> 0..y where 0 <= y\n         // 7. [x: ]     -> x..end where x <= end\n\n         rp.clear();\n\n         if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR095 - Expected '[' for start of range\",\n                          exprtk_error_location));\n\n            return false;\n         }\n\n         if (token_is(token_t::e_colon))\n         {\n            rp.n0_c.first  = true;\n            rp.n0_c.second = 0;\n            rp.cache.first = 0;\n         }\n         else\n         {\n            expression_node_ptr r0 = parse_expression();\n\n            if (0 == r0)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR096 - Failed parse begin section of range\",\n                             exprtk_error_location));\n\n               return false;\n\n            }\n            else if (is_constant_node(r0))\n            {\n               const T r0_value = r0->value();\n\n               if (r0_value >= T(0))\n               {\n                  rp.n0_c.first  = true;\n                  rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));\n                  rp.cache.first = rp.n0_c.second;\n               }\n\n               free_node(node_allocator_,r0);\n\n               if (r0_value < T(0))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR097 - Range lower bound less than zero! Constraint: r0 >= 0\",\n                                exprtk_error_location));\n\n                  return false;\n               }\n            }\n            else\n            {\n               rp.n0_e.first  = true;\n               rp.n0_e.second = r0;\n            }\n\n            if (!token_is(token_t::e_colon))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR098 - Expected ':' for break  in range\",\n                             exprtk_error_location));\n\n               rp.free();\n\n               return false;\n            }\n         }\n\n         if (token_is(token_t::e_rsqrbracket))\n         {\n            rp.n1_c.first  = true;\n            rp.n1_c.second = std::numeric_limits<std::size_t>::max();\n         }\n         else\n         {\n            expression_node_ptr r1 = parse_expression();\n\n            if (0 == r1)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR099 - Failed parse end section of range\",\n                             exprtk_error_location));\n\n               rp.free();\n\n               return false;\n\n            }\n            else if (is_constant_node(r1))\n            {\n               const T r1_value = r1->value();\n\n               if (r1_value >= T(0))\n               {\n                  rp.n1_c.first   = true;\n                  rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));\n                  rp.cache.second = rp.n1_c.second;\n               }\n\n               free_node(node_allocator_,r1);\n\n               if (r1_value < T(0))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR100 - Range upper bound less than zero! Constraint: r1 >= 0\",\n                                exprtk_error_location));\n\n                  return false;\n               }\n            }\n            else\n            {\n               rp.n1_e.first  = true;\n               rp.n1_e.second = r1;\n            }\n\n            if (!token_is(token_t::e_rsqrbracket))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR101 - Expected ']' for start of range\",\n                             exprtk_error_location));\n\n               rp.free();\n\n               return false;\n            }\n         }\n\n         if (rp.const_range())\n         {\n            std::size_t r0 = 0;\n            std::size_t r1 = 0;\n\n            const bool rp_result = rp(r0,r1);\n\n            if (!rp_result || (r0 > r1))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR102 - Invalid range, Constraint: r0 <= r1\",\n                             exprtk_error_location));\n\n               return false;\n            }\n         }\n\n         return true;\n      }\n\n      inline void lodge_symbol(const std::string& symbol,\n                               const symbol_type st)\n      {\n         dec_.add_symbol(symbol,st);\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline expression_node_ptr parse_string()\n      {\n         const std::string symbol = current_token().value;\n\n         typedef details::stringvar_node<T>* strvar_node_t;\n\n         expression_node_ptr result   = error_node();\n         strvar_node_t const_str_node = static_cast<strvar_node_t>(0);\n\n         scope_element& se = sem_.get_active_element(symbol);\n\n         if (scope_element::e_string == se.type)\n         {\n            se.active = true;\n            result    = se.str_node;\n            lodge_symbol(symbol,e_st_local_string);\n         }\n         else\n         {\n            if (!symtab_store_.is_conststr_stringvar(symbol))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR103 - Unknown string symbol\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            result = symtab_store_.get_stringvar(symbol);\n\n            if (symtab_store_.is_constant_string(symbol))\n            {\n               const_str_node = static_cast<strvar_node_t>(result);\n               result = expression_generator_(const_str_node->str());\n            }\n\n            lodge_symbol(symbol,e_st_string);\n         }\n\n         if (peek_token_is(token_t::e_lsqrbracket))\n         {\n            next_token();\n\n            if (peek_token_is(token_t::e_rsqrbracket))\n            {\n               next_token();\n               next_token();\n\n               if (const_str_node)\n               {\n                  free_node(node_allocator_,result);\n\n                  return expression_generator_(T(const_str_node->size()));\n               }\n               else\n                  return node_allocator_.allocate<details::stringvar_size_node<T> >\n                            (static_cast<details::stringvar_node<T>*>(result)->ref());\n            }\n\n            range_t rp;\n\n            if (!parse_range(rp))\n            {\n               free_node(node_allocator_,result);\n\n               return error_node();\n            }\n            else if (const_str_node)\n            {\n               free_node(node_allocator_,result);\n               result = expression_generator_(const_str_node->ref(),rp);\n            }\n            else\n               result = expression_generator_(static_cast<details::stringvar_node<T>*>\n                           (result)->ref(), rp);\n\n            if (result)\n               rp.clear();\n         }\n         else\n            next_token();\n\n         return result;\n      }\n      #else\n      inline expression_node_ptr parse_string()\n      {\n         return error_node();\n      }\n      #endif\n\n      #ifndef exprtk_disable_string_capabilities\n      inline expression_node_ptr parse_const_string()\n      {\n         const std::string   const_str = current_token().value;\n         expression_node_ptr result    = expression_generator_(const_str);\n\n         if (peek_token_is(token_t::e_lsqrbracket))\n         {\n            next_token();\n\n            if (peek_token_is(token_t::e_rsqrbracket))\n            {\n               next_token();\n               next_token();\n\n               free_node(node_allocator_,result);\n\n               return expression_generator_(T(const_str.size()));\n            }\n\n            range_t rp;\n\n            if (!parse_range(rp))\n            {\n               free_node(node_allocator_,result);\n\n               return error_node();\n            }\n\n            free_node(node_allocator_,result);\n\n            if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))\n            {\n               rp.n1_c.second  = const_str.size() - 1;\n               rp.cache.second = rp.n1_c.second;\n            }\n\n            if (\n                 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||\n                 (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))\n               )\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR104 - Overflow in range for string: '\" + const_str + \"'[\" +\n                             (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : \"?\") + \":\" +\n                             (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : \"?\") + \"]\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            result = expression_generator_(const_str,rp);\n\n            if (result)\n               rp.clear();\n         }\n         else\n            next_token();\n\n         return result;\n      }\n      #else\n      inline expression_node_ptr parse_const_string()\n      {\n         return error_node();\n      }\n      #endif\n\n      inline expression_node_ptr parse_vector()\n      {\n         const std::string symbol = current_token().value;\n\n         vector_holder_ptr vec = vector_holder_ptr(0);\n\n         const scope_element& se = sem_.get_active_element(symbol);\n\n         if (\n              !details::imatch(se.name, symbol) ||\n              (se.depth > state_.scope_depth)   ||\n              (scope_element::e_vector != se.type)\n            )\n         {\n            if (0 == (vec = symtab_store_.get_vector(symbol)))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR105 - Symbol '\" + symbol+ \" not a vector\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n         else\n            vec = se.vec_node;\n\n         expression_node_ptr index_expr = error_node();\n\n         next_token();\n\n         if (!token_is(token_t::e_lsqrbracket))\n         {\n            return node_allocator_.allocate<vector_node_t>(vec);\n         }\n         else if (token_is(token_t::e_rsqrbracket))\n         {\n            return expression_generator_(T(vec->size()));\n         }\n         else if (0 == (index_expr = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR106 - Failed to parse index for vector: '\" + symbol + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_rsqrbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR107 - Expected ']' for index of vector: '\" + symbol + \"'\",\n                          exprtk_error_location));\n\n            free_node(node_allocator_,index_expr);\n\n            return error_node();\n         }\n\n         // Perform compile-time range check\n         if (details::is_constant_node(index_expr))\n         {\n            const std::size_t index    = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));\n            const std::size_t vec_size = vec->size();\n\n            if (index >= vec_size)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR108 - Index of \" + details::to_str(index) + \" out of range for \"\n                             \"vector '\" + symbol + \"' of size \" + details::to_str(vec_size),\n                             exprtk_error_location));\n\n               free_node(node_allocator_,index_expr);\n\n               return error_node();\n            }\n         }\n\n         return expression_generator_.vector_element(symbol,vec,index_expr);\n      }\n\n      inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)\n      {\n         std::vector<expression_node_ptr> arg_list;\n\n         expression_node_ptr result = error_node();\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         next_token();\n\n         if (token_is(token_t::e_lbracket))\n         {\n            if (token_is(token_t::e_rbracket))\n            {\n               if (!vararg_function->allow_zero_parameters())\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR109 - Zero parameter call to vararg function: \"\n                                + vararg_function_name + \" not allowed\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n            else\n            {\n               for ( ; ; )\n               {\n                  expression_node_ptr arg = parse_expression();\n\n                  if (0 == arg)\n                     return error_node();\n                  else\n                     arg_list.push_back(arg);\n\n                  if (token_is(token_t::e_rbracket))\n                     break;\n                  else if (!token_is(token_t::e_comma))\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR110 - Expected ',' for call to vararg function: \"\n                                   + vararg_function_name,\n                                   exprtk_error_location));\n\n                     return error_node();\n                  }\n               }\n            }\n         }\n         else if (!vararg_function->allow_zero_parameters())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR111 - Zero parameter call to vararg function: \"\n                          + vararg_function_name + \" not allowed\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         if (arg_list.size() < vararg_function->min_num_args())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR112 - Invalid number of parameters to call to vararg function: \"\n                          + vararg_function_name + \", require at least \"\n                          + details::to_str(static_cast<int>(vararg_function->min_num_args())) + \" parameters\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (arg_list.size() > vararg_function->max_num_args())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR113 - Invalid number of parameters to call to vararg function: \"\n                          + vararg_function_name + \", require no more than \"\n                          + details::to_str(static_cast<int>(vararg_function->max_num_args())) + \" parameters\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         result = expression_generator_.vararg_function_call(vararg_function,arg_list);\n\n         sdd.delete_ptr = (0 == result);\n\n         return result;\n      }\n\n      class type_checker\n      {\n      public:\n\n         typedef parser<T> parser_t;\n         typedef std::vector<std::string> param_seq_list_t;\n\n         type_checker(parser_t& p,\n                      const std::string& func_name,\n                      const std::string& param_seq)\n         : invalid_state_(true),\n           parser_(p),\n           function_name_(func_name)\n         {\n            split(param_seq);\n         }\n\n         bool verify(const std::string& param_seq, std::size_t& pseq_index)\n         {\n            if (param_seq_list_.empty())\n               return true;\n\n            std::vector<std::pair<std::size_t,char> > error_list;\n\n            for (std::size_t i = 0; i < param_seq_list_.size(); ++i)\n            {\n               details::char_t diff_value = 0;\n               std::size_t     diff_index = 0;\n\n               bool result = details::sequence_match(param_seq_list_[i],\n                                                     param_seq,\n                                                     diff_index,diff_value);\n\n              if (result)\n              {\n                 pseq_index = i;\n                 return true;\n              }\n              else\n                 error_list.push_back(std::make_pair(diff_index,diff_value));\n            }\n\n            if (1 == error_list.size())\n            {\n               parser_.\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                parser_.current_token(),\n                                \"ERR114 - Failed parameter type check for function '\" + function_name_ + \"', \"\n                                \"Expected '\" + param_seq_list_[0] + \"'  call set: '\" + param_seq +\"'\",\n                                exprtk_error_location));\n            }\n            else\n            {\n               // find first with largest diff_index;\n               std::size_t max_diff_index = 0;\n\n               for (std::size_t i = 1; i < error_list.size(); ++i)\n               {\n                  if (error_list[i].first > error_list[max_diff_index].first)\n                  {\n                     max_diff_index = i;\n                  }\n               }\n\n               parser_.\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                parser_.current_token(),\n                                \"ERR115 - Failed parameter type check for function '\" + function_name_ + \"', \"\n                                \"Best match: '\" + param_seq_list_[max_diff_index] + \"'  call set: '\" + param_seq +\"'\",\n                                exprtk_error_location));\n            }\n\n            return false;\n         }\n\n         std::size_t paramseq_count() const\n         {\n            return param_seq_list_.size();\n         }\n\n         std::string paramseq(const std::size_t& index) const\n         {\n            return param_seq_list_[index];\n         }\n\n         bool invalid() const\n         {\n            return !invalid_state_;\n         }\n\n         bool allow_zero_parameters() const\n         {\n            return\n               param_seq_list_.end() != std::find(param_seq_list_.begin(),\n                                                  param_seq_list_.end(),\n                                                  \"Z\");\n         }\n\n      private:\n\n         void split(const std::string& s)\n         {\n            if (s.empty())\n               return;\n\n            std::size_t start = 0;\n            std::size_t end   = 0;\n\n            param_seq_list_t param_seq_list;\n\n            struct token_validator\n            {\n               static inline bool process(const std::string& str,\n                                          std::size_t s, std::size_t e,\n                                          param_seq_list_t& psl)\n               {\n                  if (\n                       (e - s) &&\n                       (std::string::npos == str.find(\"?*\")) &&\n                       (std::string::npos == str.find(\"**\"))\n                     )\n                  {\n                     const std::string curr_str = str.substr(s, e - s);\n\n                     if (\"Z\" == curr_str)\n                     {\n                        psl.push_back(curr_str);\n                        return true;\n                     }\n                     else if (std::string::npos == curr_str.find_first_not_of(\"STV*?|\"))\n                     {\n                        psl.push_back(curr_str);\n                        return true;\n                     }\n                  }\n\n                  return false;\n               }\n            };\n\n            while (std::string::npos != (end = s.find('|',start)))\n            {\n               if (!token_validator::process(s, start, end, param_seq_list))\n               {\n                  invalid_state_ = false;\n\n                  const std::string err_param_seq = s.substr(start, end - start);\n\n                  parser_.\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   parser_.current_token(),\n                                   \"ERR116 - Invalid parameter sequence of '\" + err_param_seq +\n                                   \"'  for function: \" + function_name_,\n                                   exprtk_error_location));\n\n                  return;\n               }\n               else\n                  start = end + 1;\n            }\n\n            if (start < s.size())\n            {\n               if (token_validator::process(s, start, s.size(), param_seq_list))\n                  param_seq_list_ = param_seq_list;\n               else\n               {\n                  const std::string err_param_seq = s.substr(start, s.size() - start);\n\n                  parser_.\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   parser_.current_token(),\n                                   \"ERR117 - Invalid parameter sequence of '\" + err_param_seq +\n                                   \"'  for function: \" + function_name_,\n                                   exprtk_error_location));\n                  return;\n               }\n            }\n         }\n\n         type_checker(const type_checker&);\n         type_checker& operator=(const type_checker&);\n\n         bool invalid_state_;\n         parser_t& parser_;\n         std::string function_name_;\n         param_seq_list_t param_seq_list_;\n      };\n\n      inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)\n      {\n         std::vector<expression_node_ptr> arg_list;\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         next_token();\n\n         std::string param_type_list;\n\n         type_checker tc((*this), function_name, function->parameter_sequence);\n\n         if (tc.invalid())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR118 - Type checker instantiation failure for generic function: \" + function_name,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         if (\n              !function->parameter_sequence.empty() &&\n              function->allow_zero_parameters    () &&\n              !tc      .allow_zero_parameters    ()\n            )\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR119 - Mismatch in zero parameter condition for generic function: \"\n                          + function_name,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         if (token_is(token_t::e_lbracket))\n         {\n            if (token_is(token_t::e_rbracket))\n            {\n               if (\n                    !function->allow_zero_parameters() &&\n                    !tc       .allow_zero_parameters()\n                  )\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR120 - Zero parameter call to generic function: \"\n                                + function_name + \" not allowed\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n            else\n            {\n               for ( ; ; )\n               {\n                  expression_node_ptr arg = parse_expression();\n\n                  if (0 == arg)\n                     return error_node();\n\n                  if (is_ivector_node(arg))\n                     param_type_list += 'V';\n                  else if (is_generally_string_node(arg))\n                     param_type_list += 'S';\n                  else // Everything else is assumed to be a scalar returning expression\n                     param_type_list += 'T';\n\n                  arg_list.push_back(arg);\n\n                  if (token_is(token_t::e_rbracket))\n                     break;\n                  else if (!token_is(token_t::e_comma))\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR121 - Expected ',' for call to generic function: \" + function_name,\n                                   exprtk_error_location));\n\n                     return error_node();\n                  }\n               }\n            }\n         }\n         else if (\n                   !function->parameter_sequence.empty() &&\n                   function->allow_zero_parameters    () &&\n                   !tc      .allow_zero_parameters    ()\n                 )\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR122 - Zero parameter call to generic function: \"\n                          + function_name + \" not allowed\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         std::size_t param_seq_index = 0;\n\n         if (\n              state_.type_check_enabled &&\n              !tc.verify(param_type_list, param_seq_index)\n            )\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR123 - Expected ',' for call to generic function: \" + function_name,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         expression_node_ptr result = error_node();\n\n         if (tc.paramseq_count() <= 1)\n            result = expression_generator_\n                       .generic_function_call(function, arg_list);\n         else\n            result = expression_generator_\n                       .generic_function_call(function, arg_list, param_seq_index);\n\n         sdd.delete_ptr = (0 == result);\n\n         return result;\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)\n      {\n         std::vector<expression_node_ptr> arg_list;\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         next_token();\n\n         std::string param_type_list;\n\n         type_checker tc((*this), function_name, function->parameter_sequence);\n\n         if (\n              (!function->parameter_sequence.empty()) &&\n              (0 == tc.paramseq_count())\n            )\n         {\n            return error_node();\n         }\n\n         if (token_is(token_t::e_lbracket))\n         {\n            if (!token_is(token_t::e_rbracket))\n            {\n               for ( ; ; )\n               {\n                  expression_node_ptr arg = parse_expression();\n\n                  if (0 == arg)\n                     return error_node();\n\n                  if (is_ivector_node(arg))\n                     param_type_list += 'V';\n                  else if (is_generally_string_node(arg))\n                     param_type_list += 'S';\n                  else // Everything else is a scalar returning expression\n                     param_type_list += 'T';\n\n                  arg_list.push_back(arg);\n\n                  if (token_is(token_t::e_rbracket))\n                     break;\n                  else if (!token_is(token_t::e_comma))\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR124 - Expected ',' for call to string function: \" + function_name,\n                                   exprtk_error_location));\n\n                     return error_node();\n                  }\n               }\n            }\n         }\n\n         std::size_t param_seq_index = 0;\n\n         if (!tc.verify(param_type_list, param_seq_index))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR125 - Expected ',' for call to string function: \" + function_name,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         expression_node_ptr result = error_node();\n\n         if (tc.paramseq_count() <= 1)\n            result = expression_generator_\n                       .string_function_call(function, arg_list);\n         else\n            result = expression_generator_\n                       .string_function_call(function, arg_list, param_seq_index);\n\n         sdd.delete_ptr = (0 == result);\n\n         return result;\n      }\n      #endif\n\n      template <typename Type, std::size_t NumberOfParameters>\n      struct parse_special_function_impl\n      {\n         static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type)\n         {\n            expression_node_ptr branch[NumberOfParameters];\n            expression_node_ptr result  = error_node();\n\n            std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));\n\n            scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);\n\n            p.next_token();\n\n            if (!p.token_is(token_t::e_lbracket))\n            {\n               p.set_error(\n                    make_error(parser_error::e_syntax,\n                               p.current_token(),\n                               \"ERR126 - Expected '(' for special function\",\n                               exprtk_error_location));\n\n               return error_node();\n            }\n\n            for (std::size_t i = 0; i < NumberOfParameters; ++i)\n            {\n               branch[i] = p.parse_expression();\n\n               if (0 == branch[i])\n               {\n                  return p.error_node();\n               }\n               else if (i < (NumberOfParameters - 1))\n               {\n                  if (!p.token_is(token_t::e_comma))\n                  {\n                     p.set_error(\n                          make_error(parser_error::e_syntax,\n                                     p.current_token(),\n                                     \"ERR127 - Expected ',' before next parameter of special function\",\n                                     exprtk_error_location));\n\n                     return p.error_node();\n                  }\n               }\n            }\n\n            if (!p.token_is(token_t::e_rbracket))\n               return p.error_node();\n            else\n               result = p.expression_generator_.special_function(opt_type,branch);\n\n            sd.delete_ptr = (0 == result);\n\n            return result;\n         }\n      };\n\n      inline expression_node_ptr parse_special_function()\n      {\n         // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)\n         if (\n              !details::is_digit(current_token().value[2]) ||\n              !details::is_digit(current_token().value[3])\n            )\n         {\n            set_error(\n               make_error(parser_error::e_token,\n                          current_token(),\n                          \"ERR128 - Invalid special function[1]: \" + current_token().value,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         const int id = (current_token().value[2] - '0') * 10 +\n                        (current_token().value[3] - '0');\n\n         if (id >= details::e_sffinal)\n         {\n            set_error(\n               make_error(parser_error::e_token,\n                          current_token(),\n                          \"ERR129 - Invalid special function[2]: \" + current_token().value,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         const int sf_3_to_4                   = details::e_sf48;\n         const details::operator_type opt_type = details::operator_type(id + 1000);\n         const std::size_t NumberOfParameters  = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;\n\n         switch (NumberOfParameters)\n         {\n            case 3  : return parse_special_function_impl<T,3>::process((*this),opt_type);\n            case 4  : return parse_special_function_impl<T,4>::process((*this),opt_type);\n            default : return error_node();\n         }\n      }\n\n      inline expression_node_ptr parse_null_statement()\n      {\n         next_token();\n         return node_allocator_.allocate<details::null_node<T> >();\n      }\n\n      #ifndef exprtk_disable_break_continue\n      inline expression_node_ptr parse_break_statement()\n      {\n         if (state_.parsing_break_stmt)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR130 - Break call within a break call is not allowed\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         scoped_bool_negator sbn(state_.parsing_break_stmt);\n\n         if (!brkcnt_list_.empty())\n         {\n            next_token();\n\n            brkcnt_list_.front() = true;\n\n            expression_node_ptr return_expr = error_node();\n\n            if (token_is(token_t::e_lsqrbracket))\n            {\n               if (0 == (return_expr = parse_expression()))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR131 - Failed to parse return expression for 'break' statement\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n               else if (!token_is(token_t::e_rsqrbracket))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR132 - Expected ']' at the completion of break's return expression\",\n                                exprtk_error_location));\n\n                  free_node(node_allocator_,return_expr);\n\n                  return error_node();\n               }\n            }\n\n            state_.activate_side_effect(\"parse_break_statement()\");\n\n            return node_allocator_.allocate<details::break_node<T> >(return_expr);\n         }\n         else\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR133 - Invalid use of 'break', allowed only in the scope of a loop\",\n                          exprtk_error_location));\n         }\n\n         return error_node();\n      }\n\n      inline expression_node_ptr parse_continue_statement()\n      {\n         if (!brkcnt_list_.empty())\n         {\n            next_token();\n\n            brkcnt_list_.front() = true;\n            state_.activate_side_effect(\"parse_continue_statement()\");\n\n            return node_allocator_.allocate<details::continue_node<T> >();\n         }\n         else\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR134 - Invalid use of 'continue', allowed only in the scope of a loop\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n      }\n      #endif\n\n      inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)\n      {\n         expression_node_ptr size_expr = error_node();\n\n         if (!token_is(token_t::e_lsqrbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR135 - Expected '[' as part of vector size definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (0 == (size_expr = parse_expression()))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR136 - Failed to determine size of vector '\" + vec_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!is_constant_node(size_expr))\n         {\n            free_node(node_allocator_,size_expr);\n\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR137 - Expected a literal number as size of vector '\" + vec_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         T vector_size = size_expr->value();\n\n         free_node(node_allocator_,size_expr);\n\n         if (\n              (vector_size <= T(0)) ||\n              std::not_equal_to<T>()\n              (T(0),vector_size - details::numeric::trunc(vector_size))\n            )\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR138 - Invalid vector size. Must be an integer greater than zero, size: \" +\n                          details::to_str(details::numeric::to_int32(vector_size)),\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         std::vector<expression_node_ptr> vec_initilizer_list;\n\n         scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);\n\n         bool single_value_initialiser = false;\n         bool vec_to_vec_initialiser   = false;\n         bool null_initialisation      = false;\n\n         if (!token_is(token_t::e_rsqrbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR139 - Expected ']' as part of vector size definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_eof))\n         {\n            if (!token_is(token_t::e_assign))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR140 - Expected ':=' as part of vector definition\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else if (token_is(token_t::e_lsqrbracket))\n            {\n               expression_node_ptr initialiser = parse_expression();\n\n               if (0 == initialiser)\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR141 - Failed to parse single vector initialiser\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               vec_initilizer_list.push_back(initialiser);\n\n               if (!token_is(token_t::e_rsqrbracket))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR142 - Expected ']' to close single value vector initialiser\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               single_value_initialiser = true;\n            }\n            else if (!token_is(token_t::e_lcrlbracket))\n            {\n               expression_node_ptr initialiser = error_node();\n\n               // Is this a vector to vector assignment and initialisation?\n               if (token_t::e_symbol == current_token().type)\n               {\n                  // Is it a locally defined vector?\n                  scope_element& se = sem_.get_active_element(current_token().value);\n\n                  if (scope_element::e_vector == se.type)\n                  {\n                     if (0 != (initialiser = parse_expression()))\n                        vec_initilizer_list.push_back(initialiser);\n                     else\n                        return error_node();\n                  }\n                  // Are we dealing with a user defined vector?\n                  else if (symtab_store_.is_vector(current_token().value))\n                  {\n                     lodge_symbol(current_token().value,e_st_vector);\n\n                     if (0 != (initialiser = parse_expression()))\n                        vec_initilizer_list.push_back(initialiser);\n                     else\n                        return error_node();\n                  }\n                  // Are we dealing with a null initialisation vector definition?\n                  else if (token_is(token_t::e_symbol,\"null\"))\n                     null_initialisation = true;\n               }\n\n               if (!null_initialisation)\n               {\n                  if (0 == initialiser)\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR143 - Expected '{' as part of vector initialiser list\",\n                                   exprtk_error_location));\n\n                     return error_node();\n                  }\n                  else\n                     vec_to_vec_initialiser = true;\n               }\n            }\n            else if (!token_is(token_t::e_rcrlbracket))\n            {\n               for ( ; ; )\n               {\n                  expression_node_ptr initialiser = parse_expression();\n\n                  if (0 == initialiser)\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR144 - Expected '{' as part of vector initialiser list\",\n                                   exprtk_error_location));\n\n                     return error_node();\n                  }\n                  else\n                     vec_initilizer_list.push_back(initialiser);\n\n                  if (token_is(token_t::e_rcrlbracket))\n                     break;\n\n                  bool is_next_close = peek_token_is(token_t::e_rcrlbracket);\n\n                  if (!token_is(token_t::e_comma) && is_next_close)\n                  {\n                     set_error(\n                        make_error(parser_error::e_syntax,\n                                   current_token(),\n                                   \"ERR145 - Expected ',' between vector initialisers\",\n                                   exprtk_error_location));\n\n                     return error_node();\n                  }\n\n                  if (token_is(token_t::e_rcrlbracket))\n                     break;\n               }\n            }\n\n            if (\n                 !token_is(token_t::e_rbracket   ,prsrhlpr_t::e_hold) &&\n                 !token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold) &&\n                 !token_is(token_t::e_rsqrbracket,prsrhlpr_t::e_hold)\n               )\n            {\n               if (!token_is(token_t::e_eof))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR146 - Expected ';' at end of vector definition\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n\n            if (vec_initilizer_list.size() > vector_size)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR147 - Initialiser list larger than the number of elements in the vector: '\" + vec_name + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n\n         typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);\n\n         const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));\n\n         scope_element& se = sem_.get_element(vec_name);\n\n         if (se.name == vec_name)\n         {\n            if (se.active)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR148 - Illegal redefinition of local vector: '\" + vec_name + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else if (\n                      (se.size == vec_size) &&\n                      (scope_element::e_vector == se.type)\n                    )\n            {\n               vec_holder = se.vec_node;\n               se.active  = true;\n               se.depth   = state_.scope_depth;\n               se.ref_count++;\n            }\n         }\n\n         if (0 == vec_holder)\n         {\n            scope_element nse;\n            nse.name      = vec_name;\n            nse.active    = true;\n            nse.ref_count = 1;\n            nse.type      = scope_element::e_vector;\n            nse.depth     = state_.scope_depth;\n            nse.size      = vec_size;\n            nse.data      = new T[vec_size];\n            nse.vec_node  = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);\n\n            if (!sem_.add_element(nse))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR149 - Failed to add new local vector '\" + vec_name + \"' to SEM\",\n                             exprtk_error_location));\n\n               sem_.free_element(nse);\n\n               return error_node();\n            }\n\n            vec_holder = nse.vec_node;\n\n            exprtk_debug((\"parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\\n\",\n                          nse.name.c_str(),\n                          static_cast<int>(nse.size)));\n         }\n\n         state_.activate_side_effect(\"parse_define_vector_statement()\");\n\n         lodge_symbol(vec_name,e_st_local_vector);\n\n         expression_node_ptr result = error_node();\n\n         if (null_initialisation)\n            result = expression_generator_(T(0.0));\n         else if (vec_to_vec_initialiser)\n            result = expression_generator_(\n                        details::e_assign,\n                        node_allocator_.allocate<vector_node_t>(vec_holder),\n                        vec_initilizer_list[0]);\n         else\n            result = node_allocator_\n                        .allocate<details::vector_assignment_node<T> >(\n                           (*vec_holder)[0],\n                           vec_size,\n                           vec_initilizer_list,\n                           single_value_initialiser);\n\n         svd.delete_ptr = (0 == result);\n\n         return result;\n      }\n\n      #ifndef exprtk_disable_string_capabilities\n      inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)\n      {\n         stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);\n\n         scope_element& se = sem_.get_element(str_name);\n\n         if (se.name == str_name)\n         {\n            if (se.active)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR150 - Illegal redefinition of local variable: '\" + str_name + \"'\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_,initialisation_expression);\n\n               return error_node();\n            }\n            else if (scope_element::e_string == se.type)\n            {\n               str_node  = se.str_node;\n               se.active = true;\n               se.depth  = state_.scope_depth;\n               se.ref_count++;\n            }\n         }\n\n         if (0 == str_node)\n         {\n            scope_element nse;\n            nse.name      = str_name;\n            nse.active    = true;\n            nse.ref_count = 1;\n            nse.type      = scope_element::e_string;\n            nse.depth     = state_.scope_depth;\n            nse.data      = new std::string;\n            nse.str_node  = new stringvar_node_t(*(std::string*)(nse.data));\n\n            if (!sem_.add_element(nse))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR151 - Failed to add new local string variable '\" + str_name + \"' to SEM\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_,initialisation_expression);\n\n               sem_.free_element(nse);\n\n               return error_node();\n            }\n\n            str_node = nse.str_node;\n\n            exprtk_debug((\"parse_define_string_statement() - INFO - Added new local string variable: %s\\n\",nse.name.c_str()));\n         }\n\n         lodge_symbol(str_name,e_st_local_string);\n\n         state_.activate_side_effect(\"parse_define_string_statement()\");\n\n         expression_node_ptr branch[2] = {0};\n\n         branch[0] = str_node;\n         branch[1] = initialisation_expression;\n\n         return expression_generator_(details::e_assign,branch);\n      }\n      #else\n      inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)\n      {\n         return error_node();\n      }\n      #endif\n\n      inline bool local_variable_is_shadowed(const std::string& symbol)\n      {\n         const scope_element& se = sem_.get_element(symbol);\n         return (se.name == symbol) && se.active;\n      }\n\n      inline expression_node_ptr parse_define_var_statement()\n      {\n         if (settings_.vardef_disabled())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR152 - Illegal variable definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!details::imatch(current_token().value,\"var\"))\n         {\n            return error_node();\n         }\n         else\n            next_token();\n\n         const std::string var_name = current_token().value;\n\n         expression_node_ptr initialisation_expression = error_node();\n\n         if (!token_is(token_t::e_symbol))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR153 - Expected a symbol for variable definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (details::is_reserved_symbol(var_name))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR154 - Illegal redefinition of reserved keyword: '\" + var_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (symtab_store_.symbol_exists(var_name))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR155 - Illegal redefinition of variable '\" + var_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (local_variable_is_shadowed(var_name))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR156 - Illegal redefinition of local variable: '\" + var_name + \"'\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))\n         {\n            return parse_define_vector_statement(var_name);\n         }\n         else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))\n         {\n            return parse_uninitialised_var_statement(var_name);\n         }\n         else if (token_is(token_t::e_assign))\n         {\n            if (0 == (initialisation_expression = parse_expression()))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR157 - Failed to parse initialisation expression\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n\n         if (\n              !token_is(token_t::e_rbracket   ,prsrhlpr_t::e_hold) &&\n              !token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold) &&\n              !token_is(token_t::e_rsqrbracket,prsrhlpr_t::e_hold)\n            )\n         {\n            if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR158 - Expected ';' after variable definition\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_,initialisation_expression);\n\n               return error_node();\n            }\n         }\n\n         if (\n              (0 != initialisation_expression) &&\n              details::is_generally_string_node(initialisation_expression)\n            )\n         {\n            return parse_define_string_statement(var_name,initialisation_expression);\n         }\n\n         expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);\n\n         scope_element& se = sem_.get_element(var_name);\n\n         if (se.name == var_name)\n         {\n            if (se.active)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR159 - Illegal redefinition of local variable: '\" + var_name + \"'\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_, initialisation_expression);\n\n               return error_node();\n            }\n            else if (scope_element::e_variable == se.type)\n            {\n               var_node  = se.var_node;\n               se.active = true;\n               se.depth  = state_.scope_depth;\n               se.ref_count++;\n            }\n         }\n\n         if (0 == var_node)\n         {\n            scope_element nse;\n            nse.name      = var_name;\n            nse.active    = true;\n            nse.ref_count = 1;\n            nse.type      = scope_element::e_variable;\n            nse.depth     = state_.scope_depth;\n            nse.data      = new T(T(0));\n            nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));\n\n            if (!sem_.add_element(nse))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR160 - Failed to add new local variable '\" + var_name + \"' to SEM\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_, initialisation_expression);\n\n               sem_.free_element(nse);\n\n               return error_node();\n            }\n\n            var_node = nse.var_node;\n\n            exprtk_debug((\"parse_define_var_statement() - INFO - Added new local variable: %s\\n\",nse.name.c_str()));\n         }\n\n         state_.activate_side_effect(\"parse_define_var_statement()\");\n\n         lodge_symbol(var_name,e_st_local_variable);\n\n         expression_node_ptr branch[2] = {0};\n\n         branch[0] = var_node;\n         branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));\n\n         return expression_generator_(details::e_assign,branch);\n      }\n\n      inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)\n      {\n         if (\n              !token_is(token_t::e_lcrlbracket) ||\n              !token_is(token_t::e_rcrlbracket)\n            )\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR161 - Expected a '{}' for uninitialised var definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR162 - Expected ';' after uninitialised variable definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);\n\n         scope_element& se = sem_.get_element(var_name);\n\n         if (se.name == var_name)\n         {\n            if (se.active)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR163 - Illegal redefinition of local variable: '\" + var_name + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else if (scope_element::e_variable == se.type)\n            {\n               var_node  = se.var_node;\n               se.active = true;\n               se.ref_count++;\n            }\n         }\n\n         if (0 == var_node)\n         {\n            scope_element nse;\n            nse.name      = var_name;\n            nse.active    = true;\n            nse.ref_count = 1;\n            nse.type      = scope_element::e_variable;\n            nse.depth     = state_.scope_depth;\n            nse.ip_index  = sem_.next_ip_index();\n            nse.data      = new T(T(0));\n            nse.var_node  = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));\n\n            if (!sem_.add_element(nse))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR164 - Failed to add new local variable '\" + var_name + \"' to SEM\",\n                             exprtk_error_location));\n\n               sem_.free_element(nse);\n\n               return error_node();\n            }\n\n            exprtk_debug((\"parse_uninitialised_var_statement() - INFO - Added new local variable: %s\\n\",\n                          nse.name.c_str()));\n         }\n\n         lodge_symbol(var_name,e_st_local_variable);\n\n         state_.activate_side_effect(\"parse_uninitialised_var_statement()\");\n\n         return expression_generator_(T(0));\n      }\n\n      inline expression_node_ptr parse_swap_statement()\n      {\n         if (!details::imatch(current_token().value,\"swap\"))\n         {\n            return error_node();\n         }\n         else\n            next_token();\n\n         if (!token_is(token_t::e_lbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR165 - Expected '(' at start of swap statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         expression_node_ptr variable0 = error_node();\n         expression_node_ptr variable1 = error_node();\n\n         bool variable0_generated = false;\n         bool variable1_generated = false;\n\n         const std::string var0_name = current_token().value;\n\n         if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR166 - Expected a symbol for variable or vector element definition\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (peek_token_is(token_t::e_lsqrbracket))\n         {\n            if (0 == (variable0 = parse_vector()))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR167 - First parameter to swap is an invalid vector element: '\" + var0_name + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n\n            variable0_generated = true;\n         }\n         else\n         {\n            if (symtab_store_.is_variable(var0_name))\n            {\n               variable0 = symtab_store_.get_variable(var0_name);\n            }\n\n            scope_element& se = sem_.get_element(var0_name);\n\n            if (\n                 (se.active)            &&\n                 (se.name == var0_name) &&\n                 (scope_element::e_variable == se.type)\n               )\n            {\n               variable0 = se.var_node;\n            }\n\n            lodge_symbol(var0_name,e_st_variable);\n\n            if (0 == variable0)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR168 - First parameter to swap is an invalid variable: '\" + var0_name + \"'\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n            else\n               next_token();\n         }\n\n         if (!token_is(token_t::e_comma))\n         {\n            set_error(\n                make_error(parser_error::e_syntax,\n                           current_token(),\n                           \"ERR169 - Expected ',' between parameters to swap\",\n                           exprtk_error_location));\n\n            if (variable0_generated)\n            {\n               free_node(node_allocator_,variable0);\n            }\n\n            return error_node();\n         }\n\n         const std::string var1_name = current_token().value;\n\n         if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR170 - Expected a symbol for variable or vector element definition\",\n                          exprtk_error_location));\n\n            if (variable0_generated)\n            {\n               free_node(node_allocator_,variable0);\n            }\n\n            return error_node();\n         }\n         else if (peek_token_is(token_t::e_lsqrbracket))\n         {\n            if (0 == (variable1 = parse_vector()))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR171 - Second parameter to swap is an invalid vector element: '\" + var1_name + \"'\",\n                             exprtk_error_location));\n\n               if (variable0_generated)\n               {\n                  free_node(node_allocator_,variable0);\n               }\n\n               return error_node();\n            }\n\n            variable1_generated = true;\n         }\n         else\n         {\n            if (symtab_store_.is_variable(var1_name))\n            {\n               variable1 = symtab_store_.get_variable(var1_name);\n            }\n\n            scope_element& se = sem_.get_element(var1_name);\n\n            if (\n                 (se.active) &&\n                 (se.name == var1_name) &&\n                 (scope_element::e_variable == se.type)\n               )\n            {\n               variable1 = se.var_node;\n            }\n\n            lodge_symbol(var1_name,e_st_variable);\n\n            if (0 == variable1)\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR172 - Second parameter to swap is an invalid variable: '\" + var1_name + \"'\",\n                             exprtk_error_location));\n\n               if (variable0_generated)\n               {\n                  free_node(node_allocator_,variable0);\n               }\n\n               return error_node();\n            }\n            else\n               next_token();\n         }\n\n         if (!token_is(token_t::e_rbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR173 - Expected ')' at end of swap statement\",\n                          exprtk_error_location));\n\n            if (variable0_generated)\n            {\n               free_node(node_allocator_,variable0);\n            }\n\n            if (variable1_generated)\n            {\n               free_node(node_allocator_,variable1);\n            }\n\n            return error_node();\n         }\n\n         typedef details::variable_node<T>* variable_node_ptr;\n\n         variable_node_ptr v0 = variable_node_ptr(0);\n         variable_node_ptr v1 = variable_node_ptr(0);\n\n         expression_node_ptr result = error_node();\n\n         if (\n              (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&\n              (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))\n            )\n         {\n            result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);\n\n            if (variable0_generated)\n            {\n               free_node(node_allocator_,variable0);\n            }\n\n            if (variable1_generated)\n            {\n               free_node(node_allocator_,variable1);\n            }\n         }\n         else\n            result = node_allocator_.allocate<details::swap_generic_node<T> >\n                        (variable0, variable1);\n\n         state_.activate_side_effect(\"parse_swap_statement()\");\n\n         return result;\n      }\n\n      #ifndef exprtk_disable_return_statement\n      inline expression_node_ptr parse_return_statement()\n      {\n         if (state_.parsing_return_stmt)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR174 - Return call within a return call is not allowed\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         scoped_bool_negator sbn(state_.parsing_return_stmt);\n\n         std::vector<expression_node_ptr> arg_list;\n\n         scoped_vec_delete<expression_node_t> sdd((*this),arg_list);\n\n         if (!details::imatch(current_token().value,\"return\"))\n         {\n            return error_node();\n         }\n         else\n            next_token();\n\n         if (!token_is(token_t::e_lsqrbracket))\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR175 - Expected '[' at start of return statement\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else if (!token_is(token_t::e_rsqrbracket))\n         {\n            for ( ; ; )\n            {\n               expression_node_ptr arg = parse_expression();\n\n               if (0 == arg)\n                  return error_node();\n\n               arg_list.push_back(arg);\n\n               if (token_is(token_t::e_rsqrbracket))\n                  break;\n               else if (!token_is(token_t::e_comma))\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR176 - Expected ',' between values during call to return\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n         }\n         else if (settings_.zero_return_disabled())\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR177 - Zero parameter return statement not allowed\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         lexer::token prev_token = current_token();\n\n         if (token_is(token_t::e_rsqrbracket))\n         {\n            if (!arg_list.empty())\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             prev_token,\n                             \"ERR178 - Invalid ']' found during return call\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n\n         std::string ret_param_type_list;\n\n         for (std::size_t i = 0; i < arg_list.size(); ++i)\n         {\n            if (0 == arg_list[i])\n               return error_node();\n            else if (is_ivector_node(arg_list[i]))\n               ret_param_type_list += 'V';\n            else if (is_generally_string_node(arg_list[i]))\n               ret_param_type_list += 'S';\n            else\n               ret_param_type_list += 'T';\n         }\n\n         dec_.retparam_list_.push_back(ret_param_type_list);\n\n         expression_node_ptr result = expression_generator_.return_call(arg_list);\n\n         sdd.delete_ptr = (0 == result);\n\n         state_.return_stmt_present = true;\n\n         state_.activate_side_effect(\"parse_return_statement()\");\n\n         return result;\n      }\n      #else\n      inline expression_node_ptr parse_return_statement()\n      {\n         return error_node();\n      }\n      #endif\n\n      inline bool post_variable_process(const std::string& symbol)\n      {\n         if (\n              peek_token_is(token_t::e_lbracket   ) ||\n              peek_token_is(token_t::e_lcrlbracket) ||\n              peek_token_is(token_t::e_lsqrbracket)\n            )\n         {\n            if (!settings_.commutative_check_enabled())\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR179 - Invalid sequence of variable '\"+ symbol + \"' and bracket\",\n                             exprtk_error_location));\n\n               return false;\n            }\n\n            lexer().insert_front(token_t::e_mul);\n         }\n\n         return true;\n      }\n\n      inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)\n      {\n         bool implied_mul = false;\n\n         if (is_generally_string_node(branch))\n            return true;\n\n         const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;\n\n         switch (token)\n         {\n            case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||\n                                                        token_is(token_t::e_lcrlbracket,hold) ||\n                                                        token_is(token_t::e_lsqrbracket,hold) ;\n                                          break;\n\n            case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,hold) ||\n                                                        token_is(token_t::e_lcrlbracket,hold) ||\n                                                        token_is(token_t::e_lsqrbracket,hold) ;\n                                          break;\n\n            case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,hold) ||\n                                                        token_is(token_t::e_lcrlbracket,hold) ||\n                                                        token_is(token_t::e_lsqrbracket,hold) ;\n                                          break;\n\n            default                     : return true;\n         }\n\n         if (implied_mul)\n         {\n            if (!settings_.commutative_check_enabled())\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR180 - Invalid sequence of brackets\",\n                             exprtk_error_location));\n\n               return false;\n            }\n            else if (token_t::e_eof != current_token().type)\n            {\n               lexer().insert_front(current_token().type);\n               lexer().insert_front(token_t::e_mul);\n               next_token();\n            }\n         }\n\n         return true;\n      }\n\n      inline expression_node_ptr parse_symtab_symbol()\n      {\n         const std::string symbol = current_token().value;\n\n         // Are we dealing with a variable or a special constant?\n         expression_node_ptr variable = symtab_store_.get_variable(symbol);\n\n         if (variable)\n         {\n            if (symtab_store_.is_constant_node(symbol))\n            {\n               variable = expression_generator_(variable->value());\n            }\n\n            if (!post_variable_process(symbol))\n               return error_node();\n\n            lodge_symbol(symbol,e_st_variable);\n            next_token();\n\n            return variable;\n         }\n\n         // Are we dealing with a locally defined variable, vector or string?\n         if (!sem_.empty())\n         {\n            scope_element& se = sem_.get_active_element(symbol);\n\n            if (se.active && details::imatch(se.name, symbol))\n            {\n               if (scope_element::e_variable == se.type)\n               {\n                  se.active = true;\n                  lodge_symbol(symbol,e_st_local_variable);\n\n                  if (!post_variable_process(symbol))\n                     return error_node();\n\n                  next_token();\n\n                  return se.var_node;\n               }\n               else if (scope_element::e_vector == se.type)\n               {\n                  return parse_vector();\n               }\n               #ifndef exprtk_disable_string_capabilities\n               else if (scope_element::e_string == se.type)\n               {\n                  return parse_string();\n               }\n               #endif\n            }\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         // Are we dealing with a string variable?\n         if (symtab_store_.is_stringvar(symbol))\n         {\n            return parse_string();\n         }\n         #endif\n\n         {\n            // Are we dealing with a function?\n            ifunction<T>* function = symtab_store_.get_function(symbol);\n\n            if (function)\n            {\n               lodge_symbol(symbol,e_st_function);\n\n               expression_node_ptr func_node =\n                                      parse_function_invocation(function,symbol);\n\n               if (func_node)\n                  return func_node;\n               else\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR181 - Failed to generate node for function: '\" + symbol + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n         }\n\n         {\n            // Are we dealing with a vararg function?\n            ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);\n\n            if (vararg_function)\n            {\n               lodge_symbol(symbol,e_st_function);\n\n               expression_node_ptr vararg_func_node =\n                                      parse_vararg_function_call(vararg_function, symbol);\n\n               if (vararg_func_node)\n                  return vararg_func_node;\n               else\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR182 - Failed to generate node for vararg function: '\" + symbol + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n         }\n\n         {\n            // Are we dealing with a vararg generic function?\n            igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);\n\n            if (generic_function)\n            {\n               lodge_symbol(symbol,e_st_function);\n\n               expression_node_ptr genericfunc_node =\n                                      parse_generic_function_call(generic_function, symbol);\n\n               if (genericfunc_node)\n                  return genericfunc_node;\n               else\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR183 - Failed to generate node for generic function: '\" + symbol + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         {\n            // Are we dealing with a vararg string returning function?\n            igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);\n\n            if (string_function)\n            {\n               lodge_symbol(symbol,e_st_function);\n\n               expression_node_ptr stringfunc_node =\n                                      parse_string_function_call(string_function, symbol);\n\n               if (stringfunc_node)\n                  return stringfunc_node;\n               else\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR184 - Failed to generate node for string function: '\" + symbol + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n            }\n         }\n         #endif\n\n         // Are we dealing with a vector?\n         if (symtab_store_.is_vector(symbol))\n         {\n            lodge_symbol(symbol,e_st_vector);\n            return parse_vector();\n         }\n\n         if (details::is_reserved_symbol(symbol))\n         {\n               if (\n                    settings_.function_enabled(symbol) ||\n                    !details::is_base_function(symbol)\n                  )\n               {\n                  set_error(\n                     make_error(parser_error::e_syntax,\n                                current_token(),\n                                \"ERR185 - Invalid use of reserved symbol '\" + symbol + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n         }\n\n         // Should we handle unknown symbols?\n         if (resolve_unknown_symbol_ && unknown_symbol_resolver_)\n         {\n            if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))\n            {\n               symbol_table_t& symtab = symtab_store_.get_symbol_table();\n\n               std::string error_message;\n\n               if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)\n               {\n                  T default_value = T(0);\n\n                  typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;\n\n                  if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))\n                  {\n                     bool create_result = false;\n\n                     switch (usr_symbol_type)\n                     {\n                        case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);\n                                                                            break;\n\n                        case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);\n                                                                            break;\n\n                        default                                           : create_result = false;\n                     }\n\n                     if (create_result)\n                     {\n                        expression_node_ptr var = symtab_store_.get_variable(symbol);\n\n                        if (var)\n                        {\n                           if (symtab_store_.is_constant_node(symbol))\n                           {\n                              var = expression_generator_(var->value());\n                           }\n\n                           lodge_symbol(symbol,e_st_variable);\n\n                           if (!post_variable_process(symbol))\n                              return error_node();\n\n                           next_token();\n\n                           return var;\n                        }\n                     }\n                  }\n\n                  set_error(\n                     make_error(parser_error::e_symtab,\n                                current_token(),\n                                \"ERR186 - Failed to create variable: '\" + symbol + \"'\" +\n                                (error_message.empty() ? \"\" : \" - \" + error_message),\n                                exprtk_error_location));\n\n               }\n               else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)\n               {\n                  if (unknown_symbol_resolver_->process(symbol, symtab, error_message))\n                  {\n                     expression_node_ptr result = parse_symtab_symbol();\n\n                     if (result)\n                     {\n                        return result;\n                     }\n                  }\n\n                  set_error(\n                     make_error(parser_error::e_symtab,\n                                current_token(),\n                                \"ERR187 - Failed to resolve symbol: '\" + symbol + \"'\" +\n                                (error_message.empty() ? \"\" : \" - \" + error_message),\n                                exprtk_error_location));\n               }\n\n               return error_node();\n            }\n         }\n\n         set_error(\n            make_error(parser_error::e_syntax,\n                       current_token(),\n                       \"ERR188 - Undefined symbol: '\" + symbol + \"'\",\n                       exprtk_error_location));\n\n         return error_node();\n      }\n\n      inline expression_node_ptr parse_symbol()\n      {\n         static const std::string symbol_if       = \"if\"      ;\n         static const std::string symbol_while    = \"while\"   ;\n         static const std::string symbol_repeat   = \"repeat\"  ;\n         static const std::string symbol_for      = \"for\"     ;\n         static const std::string symbol_switch   = \"switch\"  ;\n         static const std::string symbol_null     = \"null\"    ;\n         static const std::string symbol_break    = \"break\"   ;\n         static const std::string symbol_continue = \"continue\";\n         static const std::string symbol_var      = \"var\"     ;\n         static const std::string symbol_swap     = \"swap\"    ;\n         static const std::string symbol_return   = \"return\"  ;\n\n         if (valid_vararg_operation(current_token().value))\n         {\n            return parse_vararg_function();\n         }\n         else if (valid_base_operation(current_token().value))\n         {\n            return parse_base_operation();\n         }\n         else if (\n                   details::imatch(current_token().value, symbol_if) &&\n                   settings_.control_struct_enabled(current_token().value)\n                 )\n         {\n            return parse_conditional_statement();\n         }\n         else if (\n                   details::imatch(current_token().value, symbol_while) &&\n                   settings_.control_struct_enabled(current_token().value)\n                 )\n         {\n            return parse_while_loop();\n         }\n         else if (\n                   details::imatch(current_token().value, symbol_repeat) &&\n                   settings_.control_struct_enabled(current_token().value)\n                 )\n         {\n            return parse_repeat_until_loop();\n         }\n         else if (\n                   details::imatch(current_token().value, symbol_for) &&\n                   settings_.control_struct_enabled(current_token().value)\n                 )\n         {\n            return parse_for_loop();\n         }\n         else if (\n                   details::imatch(current_token().value, symbol_switch) &&\n                   settings_.control_struct_enabled(current_token().value)\n                 )\n         {\n            return parse_switch_statement();\n         }\n         else if (details::is_valid_sf_symbol(current_token().value))\n         {\n            return parse_special_function();\n         }\n         else if (details::imatch(current_token().value, symbol_null))\n         {\n            return parse_null_statement();\n         }\n         #ifndef exprtk_disable_break_continue\n         else if (details::imatch(current_token().value, symbol_break))\n         {\n            return parse_break_statement();\n         }\n         else if (details::imatch(current_token().value, symbol_continue))\n         {\n            return parse_continue_statement();\n         }\n         #endif\n         else if (details::imatch(current_token().value, symbol_var))\n         {\n            return parse_define_var_statement();\n         }\n         else if (details::imatch(current_token().value, symbol_swap))\n         {\n            return parse_swap_statement();\n         }\n         #ifndef exprtk_disable_return_statement\n         else if (\n                   details::imatch(current_token().value, symbol_return) &&\n                   settings_.control_struct_enabled(current_token().value)\n                 )\n         {\n            return parse_return_statement();\n         }\n         #endif\n         else if (symtab_store_.valid() || !sem_.empty())\n         {\n            return parse_symtab_symbol();\n         }\n         else\n         {\n            set_error(\n               make_error(parser_error::e_symtab,\n                          current_token(),\n                          \"ERR189 - Variable or function detected, yet symbol-table is invalid, Symbol: \" + current_token().value,\n                          exprtk_error_location));\n\n            return error_node();\n         }\n      }\n\n      inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)\n      {\n         expression_node_ptr branch = error_node();\n\n         if (token_t::e_number == current_token().type)\n         {\n            T numeric_value = T(0);\n\n            if (details::string_to_real(current_token().value, numeric_value))\n            {\n               expression_node_ptr literal_exp = expression_generator_(numeric_value);\n\n               if (0 == literal_exp)\n               {\n                  set_error(\n                     make_error(parser_error::e_numeric,\n                                current_token(),\n                                \"ERR190 - Failed generate node for scalar: '\" + current_token().value + \"'\",\n                                exprtk_error_location));\n\n                  return error_node();\n               }\n\n               next_token();\n               branch = literal_exp;\n            }\n            else\n            {\n               set_error(\n                  make_error(parser_error::e_numeric,\n                             current_token(),\n                             \"ERR191 - Failed to convert '\" + current_token().value + \"' to a number\",\n                             exprtk_error_location));\n\n               return error_node();\n            }\n         }\n         else if (token_t::e_symbol == current_token().type)\n         {\n            branch = parse_symbol();\n         }\n         #ifndef exprtk_disable_string_capabilities\n         else if (token_t::e_string == current_token().type)\n         {\n            branch = parse_const_string();\n         }\n         #endif\n         else if (token_t::e_lbracket == current_token().type)\n         {\n            next_token();\n\n            if (0 == (branch = parse_expression()))\n               return error_node();\n            else if (!token_is(token_t::e_rbracket))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR192 - Expected ')' instead of: '\" + current_token().value + \"'\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_,branch);\n\n               return error_node();\n            }\n            else if (!post_bracket_process(token_t::e_lbracket,branch))\n            {\n               free_node(node_allocator_,branch);\n\n               return error_node();\n            }\n         }\n         else if (token_t::e_lsqrbracket == current_token().type)\n         {\n            next_token();\n\n            if (0 == (branch = parse_expression()))\n               return error_node();\n            else if (!token_is(token_t::e_rsqrbracket))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR193 - Expected ']' instead of: '\" + current_token().value + \"'\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_,branch);\n\n               return error_node();\n            }\n            else if (!post_bracket_process(token_t::e_lsqrbracket,branch))\n            {\n               free_node(node_allocator_,branch);\n\n               return error_node();\n            }\n         }\n         else if (token_t::e_lcrlbracket == current_token().type)\n         {\n            next_token();\n\n            if (0 == (branch = parse_expression()))\n               return error_node();\n            else if (!token_is(token_t::e_rcrlbracket))\n            {\n               set_error(\n                  make_error(parser_error::e_syntax,\n                             current_token(),\n                             \"ERR194 - Expected '}' instead of: '\" + current_token().value + \"'\",\n                             exprtk_error_location));\n\n               free_node(node_allocator_,branch);\n\n               return error_node();\n            }\n            else if (!post_bracket_process(token_t::e_lcrlbracket,branch))\n            {\n               free_node(node_allocator_,branch);\n\n               return error_node();\n            }\n         }\n         else if (token_t::e_sub == current_token().type)\n         {\n            next_token();\n            branch = parse_expression(e_level11);\n\n            if (\n                 branch &&\n                 !(\n                    details::is_neg_unary_node    (branch) &&\n                    simplify_unary_negation_branch(branch)\n                  )\n               )\n            {\n               branch = expression_generator_(details::e_neg,branch);\n            }\n         }\n         else if (token_t::e_add == current_token().type)\n         {\n            next_token();\n            branch = parse_expression(e_level13);\n         }\n         else if (token_t::e_eof == current_token().type)\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR195 - Premature end of expression[1]\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n         else\n         {\n            set_error(\n               make_error(parser_error::e_syntax,\n                          current_token(),\n                          \"ERR196 - Premature end of expression[2]\",\n                          exprtk_error_location));\n\n            return error_node();\n         }\n\n         if (\n              branch                    &&\n              (e_level00 == precedence) &&\n              token_is(token_t::e_ternary,prsrhlpr_t::e_hold)\n            )\n         {\n            branch = parse_ternary_conditional_statement(branch);\n         }\n\n         parse_pending_string_rangesize(branch);\n\n         return branch;\n      }\n\n      template <typename Type>\n      class expression_generator\n      {\n      public:\n\n         typedef details::expression_node<Type>* expression_node_ptr;\n         typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);\n         typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;\n         typedef typename exprtk::parser<Type> parser_t;\n         typedef const Type& vtype;\n         typedef const Type  ctype;\n\n         inline void init_synthesize_map()\n         {\n            #ifndef exprtk_disable_enhanced_features\n            synthesize_map_[\"(v)o(v)\"] = synthesize_vov_expression::process;\n            synthesize_map_[\"(c)o(v)\"] = synthesize_cov_expression::process;\n            synthesize_map_[\"(v)o(c)\"] = synthesize_voc_expression::process;\n\n            #define register_synthezier(S)                      \\\n            synthesize_map_[S ::node_type::id()] = S ::process; \\\n\n            register_synthezier(synthesize_vovov_expression0)\n            register_synthezier(synthesize_vovov_expression1)\n            register_synthezier(synthesize_vovoc_expression0)\n            register_synthezier(synthesize_vovoc_expression1)\n            register_synthezier(synthesize_vocov_expression0)\n            register_synthezier(synthesize_vocov_expression1)\n            register_synthezier(synthesize_covov_expression0)\n            register_synthezier(synthesize_covov_expression1)\n            register_synthezier(synthesize_covoc_expression0)\n            register_synthezier(synthesize_covoc_expression1)\n            register_synthezier(synthesize_cocov_expression1)\n            register_synthezier(synthesize_vococ_expression0)\n\n            register_synthezier(synthesize_vovovov_expression0)\n            register_synthezier(synthesize_vovovoc_expression0)\n            register_synthezier(synthesize_vovocov_expression0)\n            register_synthezier(synthesize_vocovov_expression0)\n            register_synthezier(synthesize_covovov_expression0)\n            register_synthezier(synthesize_covocov_expression0)\n            register_synthezier(synthesize_vocovoc_expression0)\n            register_synthezier(synthesize_covovoc_expression0)\n            register_synthezier(synthesize_vococov_expression0)\n\n            register_synthezier(synthesize_vovovov_expression1)\n            register_synthezier(synthesize_vovovoc_expression1)\n            register_synthezier(synthesize_vovocov_expression1)\n            register_synthezier(synthesize_vocovov_expression1)\n            register_synthezier(synthesize_covovov_expression1)\n            register_synthezier(synthesize_covocov_expression1)\n            register_synthezier(synthesize_vocovoc_expression1)\n            register_synthezier(synthesize_covovoc_expression1)\n            register_synthezier(synthesize_vococov_expression1)\n\n            register_synthezier(synthesize_vovovov_expression2)\n            register_synthezier(synthesize_vovovoc_expression2)\n            register_synthezier(synthesize_vovocov_expression2)\n            register_synthezier(synthesize_vocovov_expression2)\n            register_synthezier(synthesize_covovov_expression2)\n            register_synthezier(synthesize_covocov_expression2)\n            register_synthezier(synthesize_vocovoc_expression2)\n            register_synthezier(synthesize_covovoc_expression2)\n\n            register_synthezier(synthesize_vovovov_expression3)\n            register_synthezier(synthesize_vovovoc_expression3)\n            register_synthezier(synthesize_vovocov_expression3)\n            register_synthezier(synthesize_vocovov_expression3)\n            register_synthezier(synthesize_covovov_expression3)\n            register_synthezier(synthesize_covocov_expression3)\n            register_synthezier(synthesize_vocovoc_expression3)\n            register_synthezier(synthesize_covovoc_expression3)\n            register_synthezier(synthesize_vococov_expression3)\n\n            register_synthezier(synthesize_vovovov_expression4)\n            register_synthezier(synthesize_vovovoc_expression4)\n            register_synthezier(synthesize_vovocov_expression4)\n            register_synthezier(synthesize_vocovov_expression4)\n            register_synthezier(synthesize_covovov_expression4)\n            register_synthezier(synthesize_covocov_expression4)\n            register_synthezier(synthesize_vocovoc_expression4)\n            register_synthezier(synthesize_covovoc_expression4)\n            #endif\n         }\n\n         inline void set_parser(parser_t& p)\n         {\n            parser_ = &p;\n         }\n\n         inline void set_uom(unary_op_map_t& unary_op_map)\n         {\n            unary_op_map_ = &unary_op_map;\n         }\n\n         inline void set_bom(binary_op_map_t& binary_op_map)\n         {\n            binary_op_map_ = &binary_op_map;\n         }\n\n         inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)\n         {\n            inv_binary_op_map_ = &inv_binary_op_map;\n         }\n\n         inline void set_sf3m(sf3_map_t& sf3_map)\n         {\n            sf3_map_ = &sf3_map;\n         }\n\n         inline void set_sf4m(sf4_map_t& sf4_map)\n         {\n            sf4_map_ = &sf4_map;\n         }\n\n         inline void set_allocator(details::node_allocator& na)\n         {\n            node_allocator_ = &na;\n         }\n\n         inline void set_strength_reduction_state(const bool enabled)\n         {\n            strength_reduction_enabled_ = enabled;\n         }\n\n         inline bool strength_reduction_enabled() const\n         {\n            return strength_reduction_enabled_;\n         }\n\n         inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)\n         {\n            typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);\n\n            if ((*binary_op_map_).end() == bop_itr)\n               return false;\n\n            bop = bop_itr->second;\n\n            return true;\n         }\n\n         inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)\n         {\n            typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);\n\n            if ((*unary_op_map_).end() == uop_itr)\n               return false;\n\n            uop = uop_itr->second;\n\n            return true;\n         }\n\n         inline details::operator_type get_operator(const binary_functor_t& bop)\n         {\n            return (*inv_binary_op_map_).find(bop)->second;\n         }\n\n         inline expression_node_ptr operator() (const Type& v) const\n         {\n            return node_allocator_->allocate<literal_node_t>(v);\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline expression_node_ptr operator() (const std::string& s) const\n         {\n            return node_allocator_->allocate<string_literal_node_t>(s);\n         }\n\n         inline expression_node_ptr operator() (std::string& s, range_t& rp) const\n         {\n            return node_allocator_->allocate_rr<string_range_node_t>(s,rp);\n         }\n\n         inline expression_node_ptr operator() (const std::string& s, range_t& rp) const\n         {\n            return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);\n         }\n\n         inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const\n         {\n            if (is_generally_string_node(branch))\n               return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);\n            else\n               return error_node();\n         }\n         #endif\n\n         inline bool unary_optimisable(const details::operator_type& operation) const\n         {\n            return (details::e_abs   == operation) || (details::e_acos  == operation) ||\n                   (details::e_acosh == operation) || (details::e_asin  == operation) ||\n                   (details::e_asinh == operation) || (details::e_atan  == operation) ||\n                   (details::e_atanh == operation) || (details::e_ceil  == operation) ||\n                   (details::e_cos   == operation) || (details::e_cosh  == operation) ||\n                   (details::e_exp   == operation) || (details::e_expm1 == operation) ||\n                   (details::e_floor == operation) || (details::e_log   == operation) ||\n                   (details::e_log10 == operation) || (details::e_log2  == operation) ||\n                   (details::e_log1p == operation) || (details::e_neg   == operation) ||\n                   (details::e_pos   == operation) || (details::e_round == operation) ||\n                   (details::e_sin   == operation) || (details::e_sinc  == operation) ||\n                   (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||\n                   (details::e_tan   == operation) || (details::e_tanh  == operation) ||\n                   (details::e_cot   == operation) || (details::e_sec   == operation) ||\n                   (details::e_csc   == operation) || (details::e_r2d   == operation) ||\n                   (details::e_d2r   == operation) || (details::e_d2g   == operation) ||\n                   (details::e_g2d   == operation) || (details::e_notl  == operation) ||\n                   (details::e_sgn   == operation) || (details::e_erf   == operation) ||\n                   (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||\n                   (details::e_frac  == operation) || (details::e_trunc == operation) ;\n         }\n\n         inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc)\n         {\n            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);\n\n            if (sf3_map_->end() == itr)\n               return false;\n            else\n               tfunc = itr->second.first;\n\n            return true;\n         }\n\n         inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc)\n         {\n            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);\n\n            if (sf4_map_->end() == itr)\n               return false;\n            else\n               qfunc = itr->second.first;\n\n            return true;\n         }\n\n         inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation)\n         {\n            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);\n\n            if (sf3_map_->end() == itr)\n               return false;\n            else\n               operation = itr->second.second;\n\n            return true;\n         }\n\n         inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation)\n         {\n            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);\n\n            if (sf4_map_->end() == itr)\n               return false;\n            else\n               operation = itr->second.second;\n\n            return true;\n         }\n\n         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])\n         {\n            if (0 == branch[0])\n            {\n               return error_node();\n            }\n            else if (details::is_null_node(branch[0]))\n            {\n               return branch[0];\n            }\n            else if (details::is_break_node(branch[0]))\n            {\n               return error_node();\n            }\n            else if (details::is_continue_node(branch[0]))\n            {\n               return error_node();\n            }\n            else if (details::is_constant_node(branch[0]))\n            {\n               return synthesize_expression<unary_node_t,1>(operation,branch);\n            }\n            else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))\n            {\n               return synthesize_uv_expression(operation,branch);\n            }\n            else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))\n            {\n               return synthesize_uvec_expression(operation,branch);\n            }\n            else\n               return synthesize_unary_expression(operation,branch);\n         }\n\n         inline bool is_assignment_operation(const details::operator_type& operation) const\n         {\n            return (\n                     (details::e_addass == operation) ||\n                     (details::e_subass == operation) ||\n                     (details::e_mulass == operation) ||\n                     (details::e_divass == operation) ||\n                     (details::e_modass == operation)\n                   ) &&\n                   parser_->settings_.assignment_enabled(operation);\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline bool valid_string_operation(const details::operator_type& operation) const\n         {\n            return (details::e_add    == operation) ||\n                   (details::e_lt     == operation) ||\n                   (details::e_lte    == operation) ||\n                   (details::e_gt     == operation) ||\n                   (details::e_gte    == operation) ||\n                   (details::e_eq     == operation) ||\n                   (details::e_ne     == operation) ||\n                   (details::e_in     == operation) ||\n                   (details::e_like   == operation) ||\n                   (details::e_ilike  == operation) ||\n                   (details::e_assign == operation) ||\n                   (details::e_addass == operation) ||\n                   (details::e_swap   == operation) ;\n         }\n         #else\n         inline bool valid_string_operation(const details::operator_type&) const\n         {\n            return false;\n         }\n         #endif\n\n         inline std::string to_str(const details::operator_type& operation) const\n         {\n            switch (operation)\n            {\n               case details::e_add  : return \"+\"      ;\n               case details::e_sub  : return \"-\"      ;\n               case details::e_mul  : return \"*\"      ;\n               case details::e_div  : return \"/\"      ;\n               case details::e_mod  : return \"%\"      ;\n               case details::e_pow  : return \"^\"      ;\n               case details::e_lt   : return \"<\"      ;\n               case details::e_lte  : return \"<=\"     ;\n               case details::e_gt   : return \">\"      ;\n               case details::e_gte  : return \">=\"     ;\n               case details::e_eq   : return \"==\"     ;\n               case details::e_ne   : return \"!=\"     ;\n               case details::e_and  : return \"and\"    ;\n               case details::e_nand : return \"nand\"   ;\n               case details::e_or   : return \"or\"     ;\n               case details::e_nor  : return \"nor\"    ;\n               case details::e_xor  : return \"xor\"    ;\n               case details::e_xnor : return \"xnor\"   ;\n               default              : return \"UNKNOWN\";\n            }\n         }\n\n         inline bool operation_optimisable(const details::operator_type& operation) const\n         {\n            return (details::e_add  == operation) ||\n                   (details::e_sub  == operation) ||\n                   (details::e_mul  == operation) ||\n                   (details::e_div  == operation) ||\n                   (details::e_mod  == operation) ||\n                   (details::e_pow  == operation) ||\n                   (details::e_lt   == operation) ||\n                   (details::e_lte  == operation) ||\n                   (details::e_gt   == operation) ||\n                   (details::e_gte  == operation) ||\n                   (details::e_eq   == operation) ||\n                   (details::e_ne   == operation) ||\n                   (details::e_and  == operation) ||\n                   (details::e_nand == operation) ||\n                   (details::e_or   == operation) ||\n                   (details::e_nor  == operation) ||\n                   (details::e_xor  == operation) ||\n                   (details::e_xnor == operation) ;\n         }\n\n         inline std::string branch_to_id(expression_node_ptr branch)\n         {\n            static const std::string null_str   (\"(null)\" );\n            static const std::string const_str  (\"(c)\"    );\n            static const std::string var_str    (\"(v)\"    );\n            static const std::string vov_str    (\"(vov)\"  );\n            static const std::string cov_str    (\"(cov)\"  );\n            static const std::string voc_str    (\"(voc)\"  );\n            static const std::string str_str    (\"(s)\"    );\n            static const std::string strrng_str (\"(rngs)\" );\n            static const std::string cs_str     (\"(cs)\"   );\n            static const std::string cstrrng_str(\"(crngs)\");\n\n            if (details::is_null_node(branch))\n               return null_str;\n            else if (details::is_constant_node(branch))\n               return const_str;\n            else if (details::is_variable_node(branch))\n               return var_str;\n            else if (details::is_vov_node(branch))\n               return vov_str;\n            else if (details::is_cov_node(branch))\n               return cov_str;\n            else if (details::is_voc_node(branch))\n               return voc_str;\n            else if (details::is_string_node(branch))\n               return str_str;\n            else if (details::is_const_string_node(branch))\n               return cs_str;\n            else if (details::is_string_range_node(branch))\n               return strrng_str;\n            else if (details::is_const_string_range_node(branch))\n               return cstrrng_str;\n            else if (details::is_t0ot1ot2_node(branch))\n               return \"(\" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + \")\";\n            else if (details::is_t0ot1ot2ot3_node(branch))\n               return \"(\" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + \")\";\n            else\n               return \"ERROR\";\n         }\n\n         inline std::string branch_to_id(expression_node_ptr (&branch)[2])\n         {\n            return branch_to_id(branch[0]) + std::string(\"o\") + branch_to_id(branch[1]);\n         }\n\n         inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return details::is_constant_node(branch[0]) &&\n                      details::is_variable_node(branch[1]) ;\n         }\n\n         inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return details::is_variable_node(branch[0]) &&\n                      details::is_constant_node(branch[1]) ;\n         }\n\n         inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return details::is_variable_node(branch[0]) &&\n                      details::is_variable_node(branch[1]) ;\n         }\n\n         inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return details::is_constant_node(branch[0]) &&\n                     !details::is_constant_node(branch[1]) ;\n         }\n\n         inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return !details::is_constant_node(branch[0]) &&\n                       details::is_constant_node(branch[1]) ;\n         }\n\n         inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (\n                 (details::e_add == operation) ||\n                 (details::e_sub == operation) ||\n                 (details::e_mul == operation) ||\n                 (details::e_div == operation)\n               )\n            {\n               return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||\n                      (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;\n            }\n            else\n               return false;\n         }\n\n         inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (\n                 (details::e_add == operation) ||\n                 (details::e_sub == operation) ||\n                 (details::e_mul == operation) ||\n                 (details::e_div == operation)\n               )\n            {\n               return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||\n                      (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;\n            }\n            else\n               return false;\n         }\n\n         inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return details::is_uv_node(branch[0]) &&\n                      details::is_uv_node(branch[1]) ;\n         }\n\n         inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return details::is_variable_node(branch[0]) &&\n                     !details::is_variable_node(branch[1]) ;\n         }\n\n         inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return !details::is_variable_node(branch[0]) &&\n                       details::is_variable_node(branch[1]) ;\n         }\n\n         inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const\n         {\n            if (!operation_optimisable(operation))\n               return false;\n            else\n               return !details::is_constant_node(branch[0]) ||\n                      !details::is_constant_node(branch[1]) ;\n         }\n\n         inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            if (is_assignment_operation(operation))\n            {\n               const bool b1_is_genstring = details::is_generally_string_node(branch[1]);\n\n               if (details::is_string_node(branch[0]))\n                  return !b1_is_genstring;\n               else\n                  return (\n                           !details::is_variable_node          (branch[0]) &&\n                           !details::is_vector_elem_node       (branch[0]) &&\n                           !details::is_rebasevector_elem_node (branch[0]) &&\n                           !details::is_rebasevector_celem_node(branch[0]) &&\n                           !details::is_vector_node            (branch[0])\n                         )\n                         || b1_is_genstring;\n            }\n            else\n               return false;\n         }\n\n         inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2])\n         {\n            if (\n                 !is_constant_node(branch[1]) ||\n                  is_constant_node(branch[0]) ||\n                  is_variable_node(branch[0]) ||\n                  is_vector_node  (branch[0]) ||\n                  is_generally_string_node(branch[0])\n               )\n               return false;\n\n            const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n\n            return cardinal_pow_optimisable(operation, c);\n         }\n\n         inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])\n         {\n            return (\n                     details::is_break_node   (branch[0]) ||\n                     details::is_break_node   (branch[1]) ||\n                     details::is_continue_node(branch[0]) ||\n                     details::is_continue_node(branch[1])\n                   );\n         }\n\n         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            const bool b0_string = is_generally_string_node(branch[0]);\n            const bool b1_string = is_generally_string_node(branch[1]);\n\n            bool result = false;\n\n            if (b0_string != b1_string)\n               result = true;\n            else if (!valid_string_operation(operation) && b0_string && b1_string)\n               result = true;\n\n            if (result)\n            {\n               parser_->set_synthesis_error(\"Invalid string operation\");\n            }\n\n            return result;\n         }\n\n         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])\n         {\n            const bool b0_string = is_generally_string_node(branch[0]);\n            const bool b1_string = is_generally_string_node(branch[1]);\n            const bool b2_string = is_generally_string_node(branch[2]);\n\n            bool result = false;\n\n            if ((b0_string != b1_string) || (b1_string != b2_string))\n               result = true;\n            else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)\n               result = true;\n\n            if (result)\n            {\n               parser_->set_synthesis_error(\"Invalid string operation\");\n            }\n\n            return result;\n         }\n\n         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            const bool b0_string = is_generally_string_node(branch[0]);\n            const bool b1_string = is_generally_string_node(branch[1]);\n\n            return (b0_string && b1_string && valid_string_operation(operation));\n         }\n\n         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])\n         {\n            const bool b0_string = is_generally_string_node(branch[0]);\n            const bool b1_string = is_generally_string_node(branch[1]);\n            const bool b2_string = is_generally_string_node(branch[2]);\n\n            return (b0_string && b1_string && b2_string && (details::e_inrange == operation));\n         }\n\n         #ifndef exprtk_disable_sc_andor\n         inline bool is_shortcircuit_expression(const details::operator_type& operation)\n         {\n            return (\n                     (details::e_scand == operation) ||\n                     (details::e_scor  == operation)\n                   );\n         }\n         #else\n         inline bool is_shortcircuit_expression(const details::operator_type&)\n         {\n            return false;\n         }\n         #endif\n\n         inline bool is_null_present(expression_node_ptr (&branch)[2])\n         {\n            return (\n                     details::is_null_node(branch[0]) ||\n                     details::is_null_node(branch[1])\n                   );\n         }\n\n         inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))\n               return false;\n            else\n               return (\n                        (details::e_lt     == operation) ||\n                        (details::e_lte    == operation) ||\n                        (details::e_gt     == operation) ||\n                        (details::e_gte    == operation) ||\n                        (details::e_eq     == operation) ||\n                        (details::e_ne     == operation) ||\n                        (details::e_equal  == operation) ||\n                        (details::e_and    == operation) ||\n                        (details::e_nand   == operation) ||\n                        (details::  e_or   == operation) ||\n                        (details:: e_nor   == operation) ||\n                        (details:: e_xor   == operation) ||\n                        (details::e_xnor   == operation)\n                      );\n         }\n\n         inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))\n               return false;\n            else\n               return (\n                        (details::e_add == operation) ||\n                        (details::e_sub == operation) ||\n                        (details::e_mul == operation) ||\n                        (details::e_div == operation) ||\n                        (details::e_pow == operation)\n                      );\n         }\n\n         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            if ((0 == branch[0]) || (0 == branch[1]))\n            {\n               return error_node();\n            }\n            else if (is_invalid_string_op(operation,branch))\n            {\n               return error_node();\n            }\n            else if (is_invalid_assignment_op(operation,branch))\n            {\n               return error_node();\n            }\n            else if (is_invalid_break_continue_op(branch))\n            {\n               return error_node();\n            }\n            else if (details::e_assign == operation)\n            {\n               return synthesize_assignment_expression(operation, branch);\n            }\n            else if (details::e_swap == operation)\n            {\n               return synthesize_swap_expression(branch);\n            }\n            else if (is_assignment_operation(operation))\n            {\n               return synthesize_assignment_operation_expression(operation, branch);\n            }\n            else if (is_vector_eqineq_logic_operation(operation, branch))\n            {\n               return synthesize_veceqineqlogic_operation_expression(operation, branch);\n            }\n            else if (is_vector_arithmetic_operation(operation, branch))\n            {\n               return synthesize_vecarithmetic_operation_expression(operation, branch);\n            }\n            else if (is_shortcircuit_expression(operation))\n            {\n               return synthesize_shortcircuit_expression(operation, branch);\n            }\n            else if (is_string_operation(operation, branch))\n            {\n               return synthesize_string_expression(operation, branch);\n            }\n            else if (is_null_present(branch))\n            {\n               return synthesize_null_expression(operation, branch);\n            }\n            #ifndef exprtk_disable_cardinal_pow_optimisation\n            else if (is_constpow_operation(operation, branch))\n            {\n               return cardinal_pow_optimisation(branch);\n            }\n            #endif\n\n            expression_node_ptr result = error_node();\n\n            #ifndef exprtk_disable_enhanced_features\n            if (synthesize_expression(operation, branch, result))\n            {\n               return result;\n            }\n            else\n            #endif\n\n            {\n               /*\n                  Possible reductions:\n                  1. c o cob -> cob\n                  2. cob o c -> cob\n                  3. c o boc -> boc\n                  4. boc o c -> boc\n               */\n               result = error_node();\n\n               if (cocob_optimisable(operation, branch))\n               {\n                  result = synthesize_cocob_expression::process((*this), operation, branch);\n               }\n               else if (coboc_optimisable(operation, branch) && (0 == result))\n               {\n                  result = synthesize_coboc_expression::process((*this), operation, branch);\n               }\n\n               if (result)\n                  return result;\n            }\n\n            if (uvouv_optimisable(operation, branch))\n            {\n               return synthesize_uvouv_expression(operation, branch);\n            }\n            else if (vob_optimisable(operation, branch))\n            {\n               return synthesize_vob_expression::process((*this), operation, branch);\n            }\n            else if (bov_optimisable(operation, branch))\n            {\n               return synthesize_bov_expression::process((*this), operation, branch);\n            }\n            else if (cob_optimisable(operation, branch))\n            {\n               return synthesize_cob_expression::process((*this), operation, branch);\n            }\n            else if (boc_optimisable(operation, branch))\n            {\n               return synthesize_boc_expression::process((*this), operation, branch);\n            }\n            #ifndef exprtk_disable_enhanced_features\n            else if (cov_optimisable(operation, branch))\n            {\n               return synthesize_cov_expression::process((*this), operation, branch);\n            }\n            #endif\n            else if (binext_optimisable(operation, branch))\n            {\n               return synthesize_binary_ext_expression::process((*this), operation, branch);\n            }\n            else\n               return synthesize_expression<binary_node_t,2>(operation, branch);\n         }\n\n         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])\n         {\n            if (\n                 (0 == branch[0]) ||\n                 (0 == branch[1]) ||\n                 (0 == branch[2])\n               )\n            {\n               details::free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n            else if (is_invalid_string_op(operation, branch))\n            {\n               return error_node();\n            }\n            else if (is_string_operation(operation, branch))\n            {\n               return synthesize_string_expression(operation, branch);\n            }\n            else\n               return synthesize_expression<trinary_node_t,3>(operation, branch);\n         }\n\n         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])\n         {\n            return synthesize_expression<quaternary_node_t,4>(operation,branch);\n         }\n\n         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)\n         {\n            expression_node_ptr branch[1] = { b0 };\n            return (*this)(operation,branch);\n         }\n\n         inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)\n         {\n            if ((0 == b0) || (0 == b1))\n               return error_node();\n            else\n            {\n               expression_node_ptr branch[2] = { b0, b1 };\n               return expression_generator<Type>::operator()(operation,branch);\n            }\n         }\n\n         inline expression_node_ptr conditional(expression_node_ptr condition,\n                                                expression_node_ptr consequent,\n                                                expression_node_ptr alternative) const\n         {\n            if ((0 == condition) || (0 == consequent))\n            {\n               free_node(*node_allocator_, condition  );\n               free_node(*node_allocator_, consequent );\n               free_node(*node_allocator_, alternative);\n\n               return error_node();\n            }\n            // Can the condition be immediately evaluated? if so optimise.\n            else if (details::is_constant_node(condition))\n            {\n               // True branch\n               if (details::is_true(condition))\n               {\n                  free_node(*node_allocator_, condition  );\n                  free_node(*node_allocator_, alternative);\n\n                  return consequent;\n               }\n               // False branch\n               else\n               {\n                  free_node(*node_allocator_, condition );\n                  free_node(*node_allocator_, consequent);\n\n                  if (alternative)\n                     return alternative;\n                  else\n                     return node_allocator_->allocate<details::null_node<T> >();\n               }\n            }\n            else if ((0 != consequent) && (0 != alternative))\n            {\n               return node_allocator_->\n                        allocate<conditional_node_t>(condition,consequent,alternative);\n            }\n            else\n               return node_allocator_->\n                        allocate<cons_conditional_node_t>(condition,consequent);\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline expression_node_ptr conditional_string(expression_node_ptr condition,\n                                                       expression_node_ptr consequent,\n                                                       expression_node_ptr alternative) const\n         {\n            if ((0 == condition) || (0 == consequent))\n            {\n               free_node(*node_allocator_, condition  );\n               free_node(*node_allocator_, consequent );\n               free_node(*node_allocator_, alternative);\n\n               return error_node();\n            }\n            // Can the condition be immediately evaluated? if so optimise.\n            else if (details::is_constant_node(condition))\n            {\n               // True branch\n               if (details::is_true(condition))\n               {\n                  free_node(*node_allocator_, condition  );\n                  free_node(*node_allocator_, alternative);\n\n                  return consequent;\n               }\n               // False branch\n               else\n               {\n                  free_node(*node_allocator_, condition );\n                  free_node(*node_allocator_, consequent);\n\n                  if (alternative)\n                     return alternative;\n                  else\n                     return node_allocator_->\n                              allocate_c<details::string_literal_node<Type> >(\"\");\n               }\n            }\n            else if ((0 != consequent) && (0 != alternative))\n               return node_allocator_->\n                        allocate<conditional_string_node_t>(condition,consequent,alternative);\n            else\n               return error_node();\n         }\n         #else\n         inline expression_node_ptr conditional_string(expression_node_ptr,\n                                                       expression_node_ptr,\n                                                       expression_node_ptr) const\n         {\n            return error_node();\n         }\n         #endif\n\n         inline expression_node_ptr while_loop(expression_node_ptr& condition,\n                                               expression_node_ptr& branch,\n                                               const bool brkcont = false) const\n         {\n            if (!brkcont && details::is_constant_node(condition))\n            {\n               expression_node_ptr result = error_node();\n               if (details::is_true(condition))\n                  // Infinite loops are not allowed.\n                  result = error_node();\n               else\n                  result = node_allocator_->allocate<details::null_node<Type> >();\n\n               free_node(*node_allocator_, condition);\n               free_node(*node_allocator_, branch   );\n\n               return result;\n            }\n            else if (details::is_null_node(condition))\n            {\n               free_node(*node_allocator_,condition);\n\n               return branch;\n            }\n            else if (!brkcont)\n               return node_allocator_->allocate<while_loop_node_t>(condition,branch);\n            #ifndef exprtk_disable_break_continue\n            else\n               return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);\n            #else\n               return error_node();\n            #endif\n         }\n\n         inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,\n                                                      expression_node_ptr& branch,\n                                                      const bool brkcont = false) const\n         {\n            if (!brkcont && details::is_constant_node(condition))\n            {\n               if (\n                    details::is_true(condition) &&\n                    details::is_constant_node(branch)\n                  )\n               {\n                  free_node(*node_allocator_,condition);\n\n                  return branch;\n               }\n\n               free_node(*node_allocator_, condition);\n               free_node(*node_allocator_, branch   );\n\n               return error_node();\n            }\n            else if (details::is_null_node(condition))\n            {\n               free_node(*node_allocator_,condition);\n\n               return branch;\n            }\n            else if (!brkcont)\n               return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);\n            #ifndef exprtk_disable_break_continue\n            else\n               return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);\n            #else\n               return error_node();\n            #endif\n         }\n\n         inline expression_node_ptr for_loop(expression_node_ptr& initialiser,\n                                             expression_node_ptr& condition,\n                                             expression_node_ptr& incrementor,\n                                             expression_node_ptr& loop_body,\n                                             bool brkcont = false) const\n         {\n            if (!brkcont && details::is_constant_node(condition))\n            {\n               expression_node_ptr result = error_node();\n\n               if (details::is_true(condition))\n                  // Infinite loops are not allowed.\n                  result = error_node();\n               else\n                  result = node_allocator_->allocate<details::null_node<Type> >();\n\n               free_node(*node_allocator_, initialiser);\n               free_node(*node_allocator_, condition  );\n               free_node(*node_allocator_, incrementor);\n               free_node(*node_allocator_, loop_body  );\n\n               return result;\n            }\n            else if (details::is_null_node(condition))\n            {\n               free_node(*node_allocator_, initialiser);\n               free_node(*node_allocator_, condition  );\n               free_node(*node_allocator_, incrementor);\n\n               return loop_body;\n            }\n            else if (!brkcont)\n               return node_allocator_->allocate<for_loop_node_t>\n                                       (\n                                         initialiser,\n                                         condition,\n                                         incrementor,\n                                         loop_body\n                                       );\n\n            #ifndef exprtk_disable_break_continue\n            else\n               return node_allocator_->allocate<for_loop_bc_node_t>\n                                       (\n                                         initialiser,\n                                         condition,\n                                         incrementor,\n                                         loop_body\n                                       );\n            #else\n            return error_node();\n            #endif\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            expression_node_ptr result = error_node();\n\n            for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)\n            {\n               expression_node_ptr condition  = arg_list[(2 * i)    ];\n               expression_node_ptr consequent = arg_list[(2 * i) + 1];\n\n               if ((0 == result) && details::is_true(condition))\n               {\n                  result = consequent;\n                  break;\n               }\n            }\n\n            if (0 == result)\n            {\n               result = arg_list.back();\n            }\n\n            for (std::size_t i = 0; i < arg_list.size(); ++i)\n            {\n               expression_node_ptr current_expr = arg_list[i];\n\n               if (current_expr && (current_expr != result))\n               {\n                  free_node(*node_allocator_,current_expr);\n               }\n            }\n\n            return result;\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            expression_node_ptr result = error_node();\n\n            for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)\n            {\n               expression_node_ptr condition  = arg_list[(2 * i)    ];\n               expression_node_ptr consequent = arg_list[(2 * i) + 1];\n\n               if (details::is_true(condition))\n               {\n                  result = consequent;\n               }\n            }\n\n            if (0 == result)\n            {\n               T zero = T(0);\n               result = node_allocator_->allocate<literal_node_t>(zero);\n            }\n\n            for (std::size_t i = 0; i < arg_list.size(); ++i)\n            {\n               expression_node_ptr& current_expr = arg_list[i];\n\n               if (current_expr && (current_expr != result))\n               {\n                  free_node(*node_allocator_,current_expr);\n               }\n            }\n\n            return result;\n         }\n\n         struct switch_nodes\n         {\n            typedef std::vector<expression_node_ptr> arg_list_t;\n\n            #define case_stmt(N)                                             \\\n            if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \\\n\n            struct switch_1\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0)\n\n                  return arg.back()->value();\n               }\n            };\n\n            struct switch_2\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0) case_stmt(1)\n\n                  return arg.back()->value();\n               }\n            };\n\n            struct switch_3\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0) case_stmt(1)\n                  case_stmt(2)\n\n                  return arg.back()->value();\n               }\n            };\n\n            struct switch_4\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0) case_stmt(1)\n                  case_stmt(2) case_stmt(3)\n\n                  return arg.back()->value();\n               }\n            };\n\n            struct switch_5\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0) case_stmt(1)\n                  case_stmt(2) case_stmt(3)\n                  case_stmt(4)\n\n                  return arg.back()->value();\n               }\n            };\n\n            struct switch_6\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0) case_stmt(1)\n                  case_stmt(2) case_stmt(3)\n                  case_stmt(4) case_stmt(5)\n\n                  return arg.back()->value();\n               }\n            };\n\n            struct switch_7\n            {\n               static inline T process(const arg_list_t& arg)\n               {\n                  case_stmt(0) case_stmt(1)\n                  case_stmt(2) case_stmt(3)\n                  case_stmt(4) case_stmt(5)\n                  case_stmt(6)\n\n                  return arg.back()->value();\n               }\n            };\n\n            #undef case_stmt\n         };\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            if (arg_list.empty())\n               return error_node();\n            else if (\n                      !all_nodes_valid(arg_list)   ||\n                      (arg_list.size() < 3)        ||\n                      ((arg_list.size() % 2) != 1)\n                    )\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n\n               return error_node();\n            }\n            else if (is_constant_foldable(arg_list))\n               return const_optimise_switch(arg_list);\n\n            switch ((arg_list.size() - 1) / 2)\n            {\n               #define case_stmt(N)                                                 \\\n               case N :                                                             \\\n                  return node_allocator_->                                          \\\n                            allocate<details::switch_n_node                         \\\n                              <Type,typename switch_nodes::switch_##N> >(arg_list); \\\n\n               case_stmt(1)\n               case_stmt(2)\n               case_stmt(3)\n               case_stmt(4)\n               case_stmt(5)\n               case_stmt(6)\n               case_stmt(7)\n               #undef case_stmt\n\n               default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);\n            }\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            if (!all_nodes_valid(arg_list))\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n\n               return error_node();\n            }\n            else if (is_constant_foldable(arg_list))\n               return const_optimise_mswitch(arg_list);\n            else\n               return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);\n         }\n\n         #define unary_opr_switch_statements            \\\n         case_stmt(details::  e_abs, details::  abs_op) \\\n         case_stmt(details:: e_acos, details:: acos_op) \\\n         case_stmt(details::e_acosh, details::acosh_op) \\\n         case_stmt(details:: e_asin, details:: asin_op) \\\n         case_stmt(details::e_asinh, details::asinh_op) \\\n         case_stmt(details:: e_atan, details:: atan_op) \\\n         case_stmt(details::e_atanh, details::atanh_op) \\\n         case_stmt(details:: e_ceil, details:: ceil_op) \\\n         case_stmt(details::  e_cos, details::  cos_op) \\\n         case_stmt(details:: e_cosh, details:: cosh_op) \\\n         case_stmt(details::  e_exp, details::  exp_op) \\\n         case_stmt(details::e_expm1, details::expm1_op) \\\n         case_stmt(details::e_floor, details::floor_op) \\\n         case_stmt(details::  e_log, details::  log_op) \\\n         case_stmt(details::e_log10, details::log10_op) \\\n         case_stmt(details:: e_log2, details:: log2_op) \\\n         case_stmt(details::e_log1p, details::log1p_op) \\\n         case_stmt(details::  e_neg, details::  neg_op) \\\n         case_stmt(details::  e_pos, details::  pos_op) \\\n         case_stmt(details::e_round, details::round_op) \\\n         case_stmt(details::  e_sin, details::  sin_op) \\\n         case_stmt(details:: e_sinc, details:: sinc_op) \\\n         case_stmt(details:: e_sinh, details:: sinh_op) \\\n         case_stmt(details:: e_sqrt, details:: sqrt_op) \\\n         case_stmt(details::  e_tan, details::  tan_op) \\\n         case_stmt(details:: e_tanh, details:: tanh_op) \\\n         case_stmt(details::  e_cot, details::  cot_op) \\\n         case_stmt(details::  e_sec, details::  sec_op) \\\n         case_stmt(details::  e_csc, details::  csc_op) \\\n         case_stmt(details::  e_r2d, details::  r2d_op) \\\n         case_stmt(details::  e_d2r, details::  d2r_op) \\\n         case_stmt(details::  e_d2g, details::  d2g_op) \\\n         case_stmt(details::  e_g2d, details::  g2d_op) \\\n         case_stmt(details:: e_notl, details:: notl_op) \\\n         case_stmt(details::  e_sgn, details::  sgn_op) \\\n         case_stmt(details::  e_erf, details::  erf_op) \\\n         case_stmt(details:: e_erfc, details:: erfc_op) \\\n         case_stmt(details:: e_ncdf, details:: ncdf_op) \\\n         case_stmt(details:: e_frac, details:: frac_op) \\\n         case_stmt(details::e_trunc, details::trunc_op) \\\n\n         inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,\n                                                             expression_node_ptr (&branch)[1])\n         {\n            T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();\n\n            switch (operation)\n            {\n               #define case_stmt(op0,op1)                                                          \\\n               case op0 : return node_allocator_->                                                 \\\n                             allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \\\n\n               unary_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,\n                                                               expression_node_ptr (&branch)[1])\n         {\n            switch (operation)\n            {\n               #define case_stmt(op0,op1)                                                    \\\n               case op0 : return node_allocator_->                                           \\\n                             allocate<typename details::unary_vector_node<Type,op1<Type> > > \\\n                                (operation, branch[0]);                                      \\\n\n               unary_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,\n                                                                expression_node_ptr (&branch)[1])\n         {\n            switch (operation)\n            {\n               #define case_stmt(op0,op1)                                                                \\\n               case op0 : return node_allocator_->                                                       \\\n                             allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \\\n\n               unary_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,\n                                                       expression_node_ptr (&branch)[3])\n         {\n            expression_node_ptr temp_node = error_node();\n\n            switch (operation)\n            {\n               #define case_stmt(op)                                                        \\\n               case details::e_sf##op : temp_node = node_allocator_->                       \\\n                             allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \\\n                                (operation, branch);                                        \\\n                             break;                                                         \\\n\n               case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)\n               case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)\n               case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)\n               case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)\n               case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)\n               case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)\n               case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)\n               case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)\n               case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)\n               case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)\n               case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)\n               case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)\n               #undef case_stmt\n               default : return error_node();\n            }\n\n            const T v = temp_node->value();\n\n            details::free_node(*node_allocator_,temp_node);\n\n            return node_allocator_->allocate<literal_node_t>(v);\n         }\n\n         inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])\n         {\n            typedef details::variable_node<Type>* variable_ptr;\n\n            const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();\n            const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();\n            const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();\n\n            switch (operation)\n            {\n               #define case_stmt(op)                                                                \\\n               case details::e_sf##op : return node_allocator_->                                    \\\n                             allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \\\n                                (v0, v1, v2);                                                       \\\n\n               case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)\n               case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)\n               case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)\n               case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)\n               case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)\n               case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)\n               case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)\n               case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)\n               case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)\n               case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)\n               case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)\n               case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])\n         {\n            if (!all_nodes_valid(branch))\n               return error_node();\n            else if (is_constant_foldable(branch))\n               return const_optimise_sf3(operation,branch);\n            else if (all_nodes_variables(branch))\n               return varnode_optimise_sf3(operation,branch);\n            else\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op)                                                        \\\n                  case details::e_sf##op : return node_allocator_->                            \\\n                                allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \\\n                                   (operation, branch);                                        \\\n\n                  case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)\n                  case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)\n                  case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)\n                  case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)\n                  case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)\n                  case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)\n                  case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)\n                  case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)\n                  case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)\n                  case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)\n                  case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)\n                  case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         }\n\n         inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])\n         {\n            expression_node_ptr temp_node = error_node();\n\n            switch (operation)\n            {\n               #define case_stmt(op)                                                                    \\\n               case details::e_sf##op : temp_node = node_allocator_->                                   \\\n                                         allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \\\n                                            (operation, branch);                                        \\\n                                        break;                                                          \\\n\n               case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)\n               case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)\n               case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)\n               case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)\n               case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)\n               case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)\n               case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)\n               case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)\n               case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)\n               case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)\n               case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)\n               case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)\n               case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)\n               #undef case_stmt\n               default : return error_node();\n            }\n\n            const T v = temp_node->value();\n\n            details::free_node(*node_allocator_,temp_node);\n\n            return node_allocator_->allocate<literal_node_t>(v);\n         }\n\n         inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])\n         {\n            typedef details::variable_node<Type>* variable_ptr;\n\n            const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();\n            const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();\n            const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();\n            const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();\n\n            switch (operation)\n            {\n               #define case_stmt(op)                                                                 \\\n               case details::e_sf##op : return node_allocator_->                                     \\\n                             allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \\\n                                (v0, v1, v2, v3);                                                    \\\n\n               case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)\n               case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)\n               case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)\n               case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)\n               case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)\n               case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)\n               case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)\n               case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)\n               case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)\n               case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)\n               case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)\n               case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)\n               case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])\n         {\n            if (!all_nodes_valid(branch))\n               return error_node();\n            else if (is_constant_foldable(branch))\n               return const_optimise_sf4(operation,branch);\n            else if (all_nodes_variables(branch))\n               return varnode_optimise_sf4(operation,branch);\n            switch (operation)\n            {\n               #define case_stmt(op)                                                        \\\n               case details::e_sf##op : return node_allocator_->                            \\\n                             allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \\\n                                (operation, branch);                                        \\\n\n               case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)\n               case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)\n               case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)\n               case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)\n               case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)\n               case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)\n               case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)\n               case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)\n               case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)\n               case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)\n               case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)\n               case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)\n               case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            expression_node_ptr temp_node = error_node();\n\n            switch (operation)\n            {\n               #define case_stmt(op0,op1)                                                 \\\n               case op0 : temp_node = node_allocator_->                                   \\\n                                         allocate<details::vararg_node<Type,op1<Type> > > \\\n                                            (arg_list);                                   \\\n                          break;                                                          \\\n\n               case_stmt(details::e_sum   , details::vararg_add_op  )\n               case_stmt(details::e_prod  , details::vararg_mul_op  )\n               case_stmt(details::e_avg   , details::vararg_avg_op  )\n               case_stmt(details::e_min   , details::vararg_min_op  )\n               case_stmt(details::e_max   , details::vararg_max_op  )\n               case_stmt(details::e_mand  , details::vararg_mand_op )\n               case_stmt(details::e_mor   , details::vararg_mor_op  )\n               case_stmt(details::e_multi , details::vararg_multi_op)\n               #undef case_stmt\n               default : return error_node();\n            }\n\n            const T v = temp_node->value();\n\n            details::free_node(*node_allocator_,temp_node);\n\n            return node_allocator_->allocate<literal_node_t>(v);\n         }\n\n         inline bool special_one_parameter_vararg(const details::operator_type& operation)\n         {\n            return (\n                     (details::e_sum  == operation) ||\n                     (details::e_prod == operation) ||\n                     (details::e_avg  == operation) ||\n                     (details::e_min  == operation) ||\n                     (details::e_max  == operation)\n                   );\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            switch (operation)\n            {\n               #define case_stmt(op0,op1)                                                   \\\n               case op0 : return node_allocator_->                                          \\\n                             allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \\\n\n               case_stmt(details::e_sum   , details::vararg_add_op  )\n               case_stmt(details::e_prod  , details::vararg_mul_op  )\n               case_stmt(details::e_avg   , details::vararg_avg_op  )\n               case_stmt(details::e_min   , details::vararg_min_op  )\n               case_stmt(details::e_max   , details::vararg_max_op  )\n               case_stmt(details::e_mand  , details::vararg_mand_op )\n               case_stmt(details::e_mor   , details::vararg_mor_op  )\n               case_stmt(details::e_multi , details::vararg_multi_op)\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            if (1 == arg_list.size())\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                      \\\n                  case op0 : return node_allocator_->                                             \\\n                                allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \\\n\n                  case_stmt(details::e_sum  , details::vec_add_op)\n                  case_stmt(details::e_prod , details::vec_mul_op)\n                  case_stmt(details::e_avg  , details::vec_avg_op)\n                  case_stmt(details::e_min  , details::vec_min_op)\n                  case_stmt(details::e_max  , details::vec_max_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else\n               return error_node();\n         }\n\n         template <typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)\n         {\n            if (!all_nodes_valid(arg_list))\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n\n               return error_node();\n            }\n            else if (is_constant_foldable(arg_list))\n               return const_optimise_varargfunc(operation,arg_list);\n            else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))\n               return vectorize_func(operation,arg_list);\n            else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))\n               return arg_list[0];\n            else if (all_nodes_variables(arg_list))\n               return varnode_optimise_varargfunc(operation,arg_list);\n\n            #ifndef exprtk_disable_string_capabilities\n            if (details::e_smulti == operation)\n            {\n               return node_allocator_->\n                 allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);\n            }\n            else\n            #endif\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                \\\n                  case op0 : return node_allocator_->                                       \\\n                                allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \\\n\n                  case_stmt(details::e_sum   , details::vararg_add_op  )\n                  case_stmt(details::e_prod  , details::vararg_mul_op  )\n                  case_stmt(details::e_avg   , details::vararg_avg_op  )\n                  case_stmt(details::e_min   , details::vararg_min_op  )\n                  case_stmt(details::e_max   , details::vararg_max_op  )\n                  case_stmt(details::e_mand  , details::vararg_mand_op )\n                  case_stmt(details::e_mor   , details::vararg_mor_op  )\n                  case_stmt(details::e_multi , details::vararg_multi_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         }\n\n         template <std::size_t N>\n         inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])\n         {\n            typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;\n            expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);\n\n            if (0 == result)\n               return error_node();\n            else\n            {\n               // Can the function call be completely optimised?\n               if (details::is_constant_node(result))\n                  return result;\n               else if (!all_nodes_valid(b))\n                  return error_node();\n               else if (N != f->param_count)\n               {\n                  details::free_all_nodes(*node_allocator_,b);\n\n                  return error_node();\n               }\n\n               function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);\n\n               if (func_node_ptr->init_branches(b))\n                  return result;\n               else\n               {\n                  details::free_all_nodes(*node_allocator_,b);\n\n                  return error_node();\n               }\n            }\n         }\n\n         inline expression_node_ptr function(ifunction_t* f)\n         {\n            typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;\n            return node_allocator_->allocate<function_N_node_t>(f);\n         }\n\n         inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,\n                                                         std::vector<expression_node_ptr>& arg_list)\n         {\n            if (!all_nodes_valid(arg_list))\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n\n               return error_node();\n            }\n\n            typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;\n\n            expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);\n\n            if (\n                 !arg_list.empty()        &&\n                 !vaf->has_side_effects() &&\n                 is_constant_foldable(arg_list)\n               )\n            {\n               const Type v = result->value();\n               details::free_node(*node_allocator_,result);\n               result = node_allocator_->allocate<literal_node_t>(v);\n            }\n\n            parser_->state_.activate_side_effect(\"vararg_function_call()\");\n\n            return result;\n         }\n\n         inline expression_node_ptr generic_function_call(igeneric_function_t* gf,\n                                                          std::vector<expression_node_ptr>& arg_list,\n                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())\n         {\n            if (!all_nodes_valid(arg_list))\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n               return error_node();\n            }\n\n            typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;\n            typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;\n\n            const std::size_t no_psi = std::numeric_limits<std::size_t>::max();\n\n            expression_node_ptr result = error_node();\n\n            if (no_psi == param_seq_index)\n               result = node_allocator_->allocate<alloc_type1>(arg_list,gf);\n            else\n               result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);\n\n            alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);\n\n            if (\n                 !arg_list.empty()                  &&\n                 !gf->has_side_effects()            &&\n                 parser_->state_.type_check_enabled &&\n                 is_constant_foldable(arg_list)\n               )\n            {\n               genfunc_node_ptr->init_branches();\n\n               const Type v = result->value();\n\n               details::free_node(*node_allocator_,result);\n\n               return node_allocator_->allocate<literal_node_t>(v);\n            }\n            else if (genfunc_node_ptr->init_branches())\n            {\n               parser_->state_.activate_side_effect(\"generic_function_call()\");\n\n               return result;\n            }\n            else\n            {\n               details::free_node(*node_allocator_, result);\n               details::free_all_nodes(*node_allocator_, arg_list);\n\n               return error_node();\n            }\n         }\n\n         #ifndef exprtk_disable_string_capabilities\n         inline expression_node_ptr string_function_call(igeneric_function_t* gf,\n                                                         std::vector<expression_node_ptr>& arg_list,\n                                                         const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())\n         {\n            if (!all_nodes_valid(arg_list))\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n               return error_node();\n            }\n\n            typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;\n            typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;\n\n            const std::size_t no_psi = std::numeric_limits<std::size_t>::max();\n\n            expression_node_ptr result = error_node();\n\n            if (no_psi == param_seq_index)\n               result = node_allocator_->allocate<alloc_type1>(gf,arg_list);\n            else\n               result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);\n\n            alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);\n\n            if (\n                 !arg_list.empty()       &&\n                 !gf->has_side_effects() &&\n                 is_constant_foldable(arg_list)\n               )\n            {\n               strfunc_node_ptr->init_branches();\n\n               const Type v = result->value();\n\n               details::free_node(*node_allocator_,result);\n\n               return node_allocator_->allocate<literal_node_t>(v);\n            }\n            else if (strfunc_node_ptr->init_branches())\n            {\n               parser_->state_.activate_side_effect(\"string_function_call()\");\n\n               return result;\n            }\n            else\n            {\n               details::free_node     (*node_allocator_,result  );\n               details::free_all_nodes(*node_allocator_,arg_list);\n\n               return error_node();\n            }\n         }\n         #endif\n\n         #ifndef exprtk_disable_return_statement\n         inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)\n         {\n            if (!all_nodes_valid(arg_list))\n            {\n               details::free_all_nodes(*node_allocator_,arg_list);\n               return error_node();\n            }\n\n            typedef details::return_node<Type> alloc_type;\n\n            expression_node_ptr result = node_allocator_->\n                                            allocate_rr<alloc_type>(arg_list,parser_->results_ctx());\n\n            alloc_type* return_node_ptr = static_cast<alloc_type*>(result);\n\n            if (return_node_ptr->init_branches())\n            {\n               parser_->state_.activate_side_effect(\"return_call()\");\n\n               return result;\n            }\n            else\n            {\n               details::free_node     (*node_allocator_,result  );\n               details::free_all_nodes(*node_allocator_,arg_list);\n\n               return error_node();\n            }\n         }\n\n         inline expression_node_ptr return_envelope(expression_node_ptr body,\n                                                    results_context_t* rc,\n                                                    bool*& return_invoked)\n         {\n            typedef details::return_envelope_node<Type> alloc_type;\n\n            expression_node_ptr result = node_allocator_->\n                                            allocate_cr<alloc_type>(body,(*rc));\n\n            return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();\n\n            return result;\n         }\n         #else\n         inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)\n         {\n            return error_node();\n         }\n\n         inline expression_node_ptr return_envelope(expression_node_ptr,\n                                                    results_context_t*,\n                                                    bool*&)\n         {\n            return error_node();\n         }\n         #endif\n\n         inline expression_node_ptr vector_element(const std::string& symbol,\n                                                   vector_holder_ptr vector_base,\n                                                   expression_node_ptr index)\n         {\n            expression_node_ptr result = error_node();\n\n            if (details::is_constant_node(index))\n            {\n               std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));\n\n               details::free_node(*node_allocator_,index);\n\n               if (vector_base->rebaseable())\n               {\n                  return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);\n               }\n\n               scope_element& se = parser_->sem_.get_element(symbol,i);\n\n               if (se.index == i)\n               {\n                  result = se.var_node;\n               }\n               else\n               {\n                  scope_element nse;\n                  nse.name      = symbol;\n                  nse.active    = true;\n                  nse.ref_count = 1;\n                  nse.type      = scope_element::e_vecelem;\n                  nse.index     = i;\n                  nse.depth     = parser_->state_.scope_depth;\n                  nse.data      = 0;\n                  nse.var_node  = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));\n\n                  if (!parser_->sem_.add_element(nse))\n                  {\n                     parser_->set_synthesis_error(\"Failed to add new local vector element to SEM [1]\");\n\n                     parser_->sem_.free_element(nse);\n\n                     result = error_node();\n                  }\n\n                  exprtk_debug((\"vector_element() - INFO - Added new local vector element: %s\\n\",nse.name.c_str()));\n\n                  parser_->state_.activate_side_effect(\"vector_element()\");\n\n                  result = nse.var_node;\n               }\n            }\n            else if (vector_base->rebaseable())\n               result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);\n            else\n               result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);\n\n            return result;\n         }\n\n      private:\n\n         template <std::size_t N, typename NodePtr>\n         inline bool is_constant_foldable(NodePtr (&b)[N]) const\n         {\n            for (std::size_t i = 0; i < N; ++i)\n            {\n               if (0 == b[i])\n                  return false;\n               else if (!details::is_constant_node(b[i]))\n                  return false;\n            }\n\n            return true;\n         }\n\n         template <typename NodePtr,\n                   typename Allocator,\n                   template <typename,typename> class Sequence>\n         inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const\n         {\n            for (std::size_t i = 0; i < b.size(); ++i)\n            {\n               if (0 == b[i])\n                  return false;\n               else if (!details::is_constant_node(b[i]))\n                  return false;\n            }\n\n            return true;\n         }\n\n         void lodge_assignment(symbol_type cst, expression_node_ptr node)\n         {\n            parser_->state_.activate_side_effect(\"lodge_assignment()\");\n\n            if (!parser_->dec_.collect_assignments())\n               return;\n\n            std::string symbol_name;\n\n            switch (cst)\n            {\n               case e_st_variable : symbol_name = parser_->symtab_store_\n                                                     .get_variable_name(node);\n                                    break;\n\n               #ifndef exprtk_disable_string_capabilities\n               case e_st_string   : symbol_name = parser_->symtab_store_\n                                                     .get_stringvar_name(node);\n                                    break;\n               #endif\n\n               case e_st_vector   : {\n                                       typedef details::vector_holder<T> vector_holder_t;\n\n                                       vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();\n\n                                       symbol_name = parser_->symtab_store_.get_vector_name(&vh);\n                                    }\n                                    break;\n\n               case e_st_vecelem  : {\n                                       typedef details::vector_holder<T> vector_holder_t;\n\n                                       vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();\n\n                                       symbol_name = parser_->symtab_store_.get_vector_name(&vh);\n\n                                       cst = e_st_vector;\n                                    }\n                                    break;\n\n               default            : return;\n            }\n\n            if (!symbol_name.empty())\n            {\n               parser_->dec_.add_assignment(symbol_name,cst);\n            }\n         }\n\n         inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            if (details::is_variable_node(branch[0]))\n            {\n               lodge_assignment(e_st_variable,branch[0]);\n\n               return synthesize_expression<assignment_node_t,2>(operation,branch);\n            }\n            else if (details::is_vector_elem_node(branch[0]))\n            {\n               lodge_assignment(e_st_vecelem,branch[0]);\n\n               return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);\n            }\n            else if (details::is_rebasevector_elem_node(branch[0]))\n            {\n               lodge_assignment(e_st_vecelem,branch[0]);\n\n               return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);\n            }\n            else if (details::is_rebasevector_celem_node(branch[0]))\n            {\n               lodge_assignment(e_st_vecelem,branch[0]);\n\n               return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);\n            }\n            #ifndef exprtk_disable_string_capabilities\n            else if (details::is_string_node(branch[0]))\n            {\n               lodge_assignment(e_st_string,branch[0]);\n\n               return synthesize_expression<assignment_string_node_t,2>(operation, branch);\n            }\n            else if (details::is_string_range_node(branch[0]))\n            {\n               lodge_assignment(e_st_string,branch[0]);\n\n               return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);\n            }\n            #endif\n            else if (details::is_vector_node(branch[0]))\n            {\n               lodge_assignment(e_st_vector,branch[0]);\n\n               if (details::is_ivector_node(branch[1]))\n                  return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);\n              else\n                  return synthesize_expression<assignment_vec_node_t,2>(operation, branch);\n            }\n            else\n            {\n               parser_->set_synthesis_error(\"Invalid assignment operation.[1]\");\n\n               return error_node();\n            }\n         }\n\n         inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,\n                                                                               expression_node_ptr (&branch)[2])\n         {\n            if (details::is_variable_node(branch[0]))\n            {\n               lodge_assignment(e_st_variable,branch[0]);\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                  \\\n                  case op0 : return node_allocator_->                                                         \\\n                                template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                         \\\n\n                  case_stmt(details::e_addass,details::add_op)\n                  case_stmt(details::e_subass,details::sub_op)\n                  case_stmt(details::e_mulass,details::mul_op)\n                  case_stmt(details::e_divass,details::div_op)\n                  case_stmt(details::e_modass,details::mod_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (details::is_vector_elem_node(branch[0]))\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                            \\\n                  case op0 : return node_allocator_->                                                                   \\\n                                 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \\\n                                    (operation, branch[0], branch[1]);                                                  \\\n\n                  case_stmt(details::e_addass,details::add_op)\n                  case_stmt(details::e_subass,details::sub_op)\n                  case_stmt(details::e_mulass,details::mul_op)\n                  case_stmt(details::e_divass,details::div_op)\n                  case_stmt(details::e_modass,details::mod_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (details::is_rebasevector_elem_node(branch[0]))\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                                  \\\n                  case op0 : return node_allocator_->                                                                         \\\n                                 template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \\\n                                    (operation, branch[0], branch[1]);                                                        \\\n\n                  case_stmt(details::e_addass,details::add_op)\n                  case_stmt(details::e_subass,details::sub_op)\n                  case_stmt(details::e_mulass,details::mul_op)\n                  case_stmt(details::e_divass,details::div_op)\n                  case_stmt(details::e_modass,details::mod_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (details::is_rebasevector_celem_node(branch[0]))\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                                   \\\n                  case op0 : return node_allocator_->                                                                          \\\n                                 template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \\\n                                    (operation, branch[0], branch[1]);                                                         \\\n\n                  case_stmt(details::e_addass,details::add_op)\n                  case_stmt(details::e_subass,details::sub_op)\n                  case_stmt(details::e_mulass,details::mul_op)\n                  case_stmt(details::e_divass,details::div_op)\n                  case_stmt(details::e_modass,details::mod_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (details::is_vector_node(branch[0]))\n            {\n               lodge_assignment(e_st_vector,branch[0]);\n\n               if (details::is_ivector_node(branch[1]))\n               {\n                  switch (operation)\n                  {\n                     #define case_stmt(op0,op1)                                                                         \\\n                     case op0 : return node_allocator_->                                                                \\\n                                   template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \\\n                                      (operation, branch[0], branch[1]);                                                \\\n\n                     case_stmt(details::e_addass,details::add_op)\n                     case_stmt(details::e_subass,details::sub_op)\n                     case_stmt(details::e_mulass,details::mul_op)\n                     case_stmt(details::e_divass,details::div_op)\n                     case_stmt(details::e_modass,details::mod_op)\n                     #undef case_stmt\n                     default : return error_node();\n                  }\n               }\n               else\n               {\n                  switch (operation)\n                  {\n                     #define case_stmt(op0,op1)                                                                      \\\n                     case op0 : return node_allocator_->                                                             \\\n                                   template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \\\n                                      (operation, branch[0], branch[1]);                                             \\\n\n                     case_stmt(details::e_addass,details::add_op)\n                     case_stmt(details::e_subass,details::sub_op)\n                     case_stmt(details::e_mulass,details::mul_op)\n                     case_stmt(details::e_divass,details::div_op)\n                     case_stmt(details::e_modass,details::mod_op)\n                     #undef case_stmt\n                     default : return error_node();\n                  }\n               }\n            }\n            #ifndef exprtk_disable_string_capabilities\n            else if (\n                      (details::e_addass == operation) &&\n                      details::is_string_node(branch[0])\n                    )\n            {\n               typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;\n\n               lodge_assignment(e_st_string,branch[0]);\n\n               return synthesize_expression<addass_t,2>(operation,branch);\n            }\n            #endif\n            else\n            {\n               parser_->set_synthesis_error(\"Invalid assignment operation[2]\");\n\n               return error_node();\n            }\n         }\n\n         inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation,\n                                                                                   expression_node_ptr (&branch)[2])\n         {\n            const bool is_b0_ivec = details::is_ivector_node(branch[0]);\n            const bool is_b1_ivec = details::is_ivector_node(branch[1]);\n\n            #define batch_eqineq_logic_case                \\\n            case_stmt(details::   e_lt, details::   lt_op) \\\n            case_stmt(details::  e_lte, details::  lte_op) \\\n            case_stmt(details::   e_gt, details::   gt_op) \\\n            case_stmt(details::  e_gte, details::  gte_op) \\\n            case_stmt(details::   e_eq, details::   eq_op) \\\n            case_stmt(details::   e_ne, details::   ne_op) \\\n            case_stmt(details::e_equal, details::equal_op) \\\n            case_stmt(details::  e_and, details::  and_op) \\\n            case_stmt(details:: e_nand, details:: nand_op) \\\n            case_stmt(details::   e_or, details::   or_op) \\\n            case_stmt(details::  e_nor, details::  nor_op) \\\n            case_stmt(details::  e_xor, details::  xor_op) \\\n            case_stmt(details:: e_xnor, details:: xnor_op) \\\n\n            if (is_b0_ivec && is_b1_ivec)\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                     \\\n                  case op0 : return node_allocator_->                                                            \\\n                                template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                            \\\n\n                  batch_eqineq_logic_case\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (is_b0_ivec && !is_b1_ivec)\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                     \\\n                  case op0 : return node_allocator_->                                                            \\\n                                template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                            \\\n\n                  batch_eqineq_logic_case\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (!is_b0_ivec && is_b1_ivec)\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                     \\\n                  case op0 : return node_allocator_->                                                            \\\n                                template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                            \\\n\n                  batch_eqineq_logic_case\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else\n               return error_node();\n\n            #undef batch_eqineq_logic_case\n         }\n\n         inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,\n                                                                                  expression_node_ptr (&branch)[2])\n         {\n            const bool is_b0_ivec = details::is_ivector_node(branch[0]);\n            const bool is_b1_ivec = details::is_ivector_node(branch[1]);\n\n            #define vector_ops                        \\\n            case_stmt(details::e_add,details::add_op) \\\n            case_stmt(details::e_sub,details::sub_op) \\\n            case_stmt(details::e_mul,details::mul_op) \\\n            case_stmt(details::e_div,details::div_op) \\\n            case_stmt(details::e_mod,details::mod_op) \\\n\n            if (is_b0_ivec && is_b1_ivec)\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                     \\\n                  case op0 : return node_allocator_->                                                            \\\n                                template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                            \\\n\n                  vector_ops\n                  case_stmt(details::e_pow,details:: pow_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (is_b0_ivec && !is_b1_ivec)\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                     \\\n                  case op0 : return node_allocator_->                                                            \\\n                                template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                            \\\n\n                  vector_ops\n                  case_stmt(details::e_pow,details:: pow_op)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else if (!is_b0_ivec && is_b1_ivec)\n            {\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                                     \\\n                  case op0 : return node_allocator_->                                                            \\\n                                template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \\\n                                   (operation, branch[0], branch[1]);                                            \\\n\n                  vector_ops\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n            else\n               return error_node();\n\n            #undef vector_ops\n         }\n\n         inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])\n         {\n            const bool v0_is_ivar = details::is_ivariable_node(branch[0]);\n            const bool v1_is_ivar = details::is_ivariable_node(branch[1]);\n\n            const bool v0_is_ivec = details::is_ivector_node  (branch[0]);\n            const bool v1_is_ivec = details::is_ivector_node  (branch[1]);\n\n            #ifndef exprtk_disable_string_capabilities\n            const bool v0_is_str = details::is_generally_string_node(branch[0]);\n            const bool v1_is_str = details::is_generally_string_node(branch[1]);\n            #endif\n\n            expression_node_ptr result = error_node();\n\n            if (v0_is_ivar && v1_is_ivar)\n            {\n               typedef details::variable_node<T>* variable_node_ptr;\n\n               variable_node_ptr v0 = variable_node_ptr(0);\n               variable_node_ptr v1 = variable_node_ptr(0);\n\n               if (\n                    (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&\n                    (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))\n                  )\n               {\n                  result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);\n               }\n               else\n                  result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);\n            }\n            else if (v0_is_ivec && v1_is_ivec)\n            {\n               result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);\n            }\n            #ifndef exprtk_disable_string_capabilities\n            else if (v0_is_str && v1_is_str)\n            {\n               if (is_string_node(branch[0]) && is_string_node(branch[1]))\n                  result = node_allocator_->allocate<details::swap_string_node<T> >\n                                               (branch[0], branch[1]);\n               else\n                  result = node_allocator_->allocate<details::swap_genstrings_node<T> >\n                                               (branch[0], branch[1]);\n            }\n            #endif\n            else\n            {\n               parser_->set_synthesis_error(\"Only variables, strings, vectors or vector elements can be swapped\");\n\n               return error_node();\n            }\n\n            parser_->state_.activate_side_effect(\"synthesize_swap_expression()\");\n\n            return result;\n         }\n\n         #ifndef exprtk_disable_sc_andor\n         inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            expression_node_ptr result = error_node();\n\n            if (details::is_constant_node(branch[0]))\n            {\n               if (\n                    (details::e_scand == operation) &&\n                    std::equal_to<T>()(T(0),branch[0]->value())\n                  )\n                  result = node_allocator_->allocate_c<literal_node_t>(T(0));\n               else if (\n                         (details::e_scor == operation) &&\n                         std::not_equal_to<T>()(T(0),branch[0]->value())\n                       )\n                  result = node_allocator_->allocate_c<literal_node_t>(T(1));\n            }\n\n            if (details::is_constant_node(branch[1]) && (0 == result))\n            {\n               if (\n                    (details::e_scand == operation) &&\n                    std::equal_to<T>()(T(0),branch[1]->value())\n                  )\n                  result = node_allocator_->allocate_c<literal_node_t>(T(0));\n               else if (\n                         (details::e_scor == operation) &&\n                         std::not_equal_to<T>()(T(0),branch[1]->value())\n                       )\n                  result = node_allocator_->allocate_c<literal_node_t>(T(1));\n            }\n\n            if (result)\n            {\n               free_node(*node_allocator_, branch[0]);\n               free_node(*node_allocator_, branch[1]);\n\n               return result;\n            }\n            else if (details::e_scand == operation)\n            {\n               return synthesize_expression<scand_node_t,2>(operation, branch);\n            }\n            else if (details::e_scor == operation)\n            {\n               return synthesize_expression<scor_node_t,2>(operation, branch);\n            }\n            else\n               return error_node();\n         }\n         #else\n         inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])\n         {\n            return error_node();\n         }\n         #endif\n\n         #define basic_opr_switch_statements        \\\n         case_stmt(details::e_add, details::add_op) \\\n         case_stmt(details::e_sub, details::sub_op) \\\n         case_stmt(details::e_mul, details::mul_op) \\\n         case_stmt(details::e_div, details::div_op) \\\n         case_stmt(details::e_mod, details::mod_op) \\\n         case_stmt(details::e_pow, details::pow_op) \\\n\n         #define extended_opr_switch_statements       \\\n         case_stmt(details::  e_lt, details::  lt_op) \\\n         case_stmt(details:: e_lte, details:: lte_op) \\\n         case_stmt(details::  e_gt, details::  gt_op) \\\n         case_stmt(details:: e_gte, details:: gte_op) \\\n         case_stmt(details::  e_eq, details::  eq_op) \\\n         case_stmt(details::  e_ne, details::  ne_op) \\\n         case_stmt(details:: e_and, details:: and_op) \\\n         case_stmt(details::e_nand, details::nand_op) \\\n         case_stmt(details::  e_or, details::  or_op) \\\n         case_stmt(details:: e_nor, details:: nor_op) \\\n         case_stmt(details:: e_xor, details:: xor_op) \\\n         case_stmt(details::e_xnor, details::xnor_op) \\\n\n         #ifndef exprtk_disable_cardinal_pow_optimisation\n         template <typename TType, template <typename,typename> class IPowNode>\n         inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)\n         {\n            switch (p)\n            {\n               #define case_stmt(cp)                                                     \\\n               case cp : return node_allocator_->                                        \\\n                            allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \\\n\n               case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)\n               case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)\n               case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)\n               case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)\n               case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)\n               case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)\n               case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)\n               case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)\n               case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)\n               case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)\n               case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)\n               case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)\n               case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)\n               case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)\n               case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)\n         {\n            const bool not_recipricol = (c >= T(0));\n            const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));\n\n            if (0 == p)\n               return node_allocator_->allocate_c<literal_node_t>(T(1));\n            else if (std::equal_to<T>()(T(2),c))\n            {\n               return node_allocator_->\n                  template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);\n            }\n            else\n            {\n               if (not_recipricol)\n                  return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);\n               else\n                  return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);\n            }\n         }\n\n         inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c)\n         {\n            return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);\n         }\n\n         inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])\n         {\n            const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n            const bool not_recipricol = (c >= T(0));\n            const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));\n\n            node_allocator_->free(branch[1]);\n\n            if (0 == p)\n            {\n               details::free_all_nodes(*node_allocator_, branch);\n\n               return node_allocator_->allocate_c<literal_node_t>(T(1));\n            }\n            else if (not_recipricol)\n               return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);\n            else\n               return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);\n         }\n         #else\n         inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)\n         {\n            return error_node();\n         }\n\n         inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)\n         {\n            return false;\n         }\n\n         inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])\n         {\n            return error_node();\n         }\n         #endif\n\n         struct synthesize_binary_ext_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const bool left_neg  = is_neg_unary_node(branch[0]);\n               const bool right_neg = is_neg_unary_node(branch[1]);\n\n               if (left_neg && right_neg)\n               {\n                  if (\n                       (details::e_add == operation) ||\n                       (details::e_sub == operation) ||\n                       (details::e_mul == operation) ||\n                       (details::e_div == operation)\n                     )\n                  {\n                     if (\n                          !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||\n                          !expr_gen.parser_->simplify_unary_negation_branch(branch[1])\n                        )\n                     {\n                        details::free_all_nodes(*expr_gen.node_allocator_,branch);\n\n                        return error_node();\n                     }\n                  }\n\n                  switch (operation)\n                  {\n                                           // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))\n                     case details::e_add : return expr_gen(details::e_neg,\n                                              expr_gen.node_allocator_->\n                                                 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >\n                                                    (branch[0],branch[1]));\n\n                                           // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)\n                     case details::e_sub : return expr_gen.node_allocator_->\n                                              template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >\n                                                 (branch[1],branch[0]);\n\n                     default             : break;\n                  }\n               }\n               else if (left_neg && !right_neg)\n               {\n                  if (\n                       (details::e_add == operation) ||\n                       (details::e_sub == operation) ||\n                       (details::e_mul == operation) ||\n                       (details::e_div == operation)\n                     )\n                  {\n                     if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))\n                     {\n                        details::free_all_nodes(*expr_gen.node_allocator_,branch);\n\n                        return error_node();\n                     }\n\n                     switch (operation)\n                     {\n                                              // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)\n                        case details::e_add : return expr_gen.node_allocator_->\n                                                 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >\n                                                   (branch[1], branch[0]);\n\n                                              // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))\n                        case details::e_sub : return expr_gen(details::e_neg,\n                                                 expr_gen.node_allocator_->\n                                                    template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >\n                                                       (branch[0], branch[1]));\n\n                                              // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))\n                        case details::e_mul : return expr_gen(details::e_neg,\n                                                 expr_gen.node_allocator_->\n                                                    template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >\n                                                       (branch[0], branch[1]));\n\n                                              // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))\n                        case details::e_div : return expr_gen(details::e_neg,\n                                                 expr_gen.node_allocator_->\n                                                    template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >\n                                                       (branch[0], branch[1]));\n\n                        default             : return error_node();\n                     }\n                  }\n               }\n               else if (!left_neg && right_neg)\n               {\n                  if (\n                       (details::e_add == operation) ||\n                       (details::e_sub == operation) ||\n                       (details::e_mul == operation) ||\n                       (details::e_div == operation)\n                     )\n                  {\n                     if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))\n                     {\n                        details::free_all_nodes(*expr_gen.node_allocator_,branch);\n\n                        return error_node();\n                     }\n\n                     switch (operation)\n                     {\n                                              // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)\n                        case details::e_add : return expr_gen.node_allocator_->\n                                                 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >\n                                                   (branch[0], branch[1]);\n\n                                              // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)\n                        case details::e_sub : return expr_gen.node_allocator_->\n                                                 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >\n                                                   (branch[0], branch[1]);\n\n                                              // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))\n                        case details::e_mul : return expr_gen(details::e_neg,\n                                                 expr_gen.node_allocator_->\n                                                    template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >\n                                                       (branch[0], branch[1]));\n\n                                              // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))\n                        case details::e_div : return expr_gen(details::e_neg,\n                                                 expr_gen.node_allocator_->\n                                                    template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >\n                                                       (branch[0], branch[1]));\n\n                        default             : return error_node();\n                     }\n                  }\n               }\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                           \\\n                  case op0 : return expr_gen.node_allocator_->                                         \\\n                                template allocate<typename details::binary_ext_node<Type,op1<Type> > > \\\n                                   (branch[0], branch[1]);                                             \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_vob_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n\n               #ifndef exprtk_disable_enhanced_features\n               if (details::is_sf3ext_node(branch[1]))\n               {\n                  expression_node_ptr result = error_node();\n\n                  const bool synthesis_result = synthesize_sf4ext_expression::template compile_right<vtype>\n                                                  (expr_gen, v, operation, branch[1], result);\n\n                  if (synthesis_result)\n                  {\n                     free_node(*expr_gen.node_allocator_,branch[1]);\n                     return result;\n                  }\n               }\n               #endif\n\n               if (\n                    (details::e_mul == operation) ||\n                    (details::e_div == operation)\n                  )\n               {\n                  if (details::is_uv_node(branch[1]))\n                  {\n                     typedef details::uv_base_node<Type>* uvbn_ptr_t;\n\n                     details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();\n\n                     if (details::e_neg == o)\n                     {\n                        const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n\n                        switch (operation)\n                        {\n                           case details::e_mul : return expr_gen(details::e_neg,\n                                                    expr_gen.node_allocator_->\n                                                       template allocate_rr<typename details::\n                                                          vov_node<Type,details::mul_op<Type> > >(v,v1));\n\n                           case details::e_div : return expr_gen(details::e_neg,\n                                                    expr_gen.node_allocator_->\n                                                       template allocate_rr<typename details::\n                                                          vov_node<Type,details::div_op<Type> > >(v,v1));\n\n                           default             : break;\n                        }\n                     }\n                  }\n               }\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_rc<typename details::vob_node<Type,op1<Type> > > \\\n                                   (v, branch[1]);                                                 \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_bov_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n\n               #ifndef exprtk_disable_enhanced_features\n               if (details::is_sf3ext_node(branch[0]))\n               {\n                  expression_node_ptr result = error_node();\n\n                  const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<vtype>\n                                                   (expr_gen, v, operation, branch[0], result);\n\n                  if (synthesis_result)\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n\n                     return result;\n                  }\n               }\n               #endif\n\n               if (\n                    (details::e_add == operation) ||\n                    (details::e_sub == operation) ||\n                    (details::e_mul == operation) ||\n                    (details::e_div == operation)\n                  )\n               {\n                  if (details::is_uv_node(branch[0]))\n                  {\n                     typedef details::uv_base_node<Type>* uvbn_ptr_t;\n\n                     details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();\n\n                     if (details::e_neg == o)\n                     {\n                        const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();\n\n                        free_node(*expr_gen.node_allocator_,branch[0]);\n\n                        switch (operation)\n                        {\n                           case details::e_add : return expr_gen.node_allocator_->\n                                                    template allocate_rr<typename details::\n                                                       vov_node<Type,details::sub_op<Type> > >(v,v0);\n\n                           case details::e_sub : return expr_gen(details::e_neg,\n                                                    expr_gen.node_allocator_->\n                                                       template allocate_rr<typename details::\n                                                          vov_node<Type,details::add_op<Type> > >(v0,v));\n\n                           case details::e_mul : return expr_gen(details::e_neg,\n                                                    expr_gen.node_allocator_->\n                                                       template allocate_rr<typename details::\n                                                          vov_node<Type,details::mul_op<Type> > >(v0,v));\n\n                           case details::e_div : return expr_gen(details::e_neg,\n                                                    expr_gen.node_allocator_->\n                                                       template allocate_rr<typename details::\n                                                          vov_node<Type,details::div_op<Type> > >(v0,v));\n                           default : break;\n                        }\n                     }\n                  }\n               }\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_cr<typename details::bov_node<Type,op1<Type> > > \\\n                                   (branch[0], v);                                                 \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_cob_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();\n\n               free_node(*expr_gen.node_allocator_,branch[0]);\n\n               if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))\n               {\n                  free_node(*expr_gen.node_allocator_,branch[1]);\n\n                  return expr_gen(T(0));\n               }\n               else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))\n               {\n                  free_node(*expr_gen.node_allocator_, branch[1]);\n\n                  return expr_gen(T(0));\n               }\n               else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))\n                  return branch[1];\n               else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))\n                  return branch[1];\n\n               if (details::is_cob_node(branch[1]))\n               {\n                  // Simplify expressions of the form:\n                  // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)\n                  // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x\n                  if (\n                       (operation == details::e_mul) ||\n                       (operation == details::e_add)\n                     )\n                  {\n                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);\n\n                     if (operation == cobnode->operation())\n                     {\n                        switch (operation)\n                        {\n                           case details::e_add : cobnode->set_c(c + cobnode->c()); break;\n                           case details::e_mul : cobnode->set_c(c * cobnode->c()); break;\n                           default             : return error_node();\n                        }\n\n                        return cobnode;\n                     }\n                  }\n\n                  if (operation == details::e_mul)\n                  {\n                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);\n                     details::operator_type cob_opr = cobnode->operation();\n\n                     if (\n                          (details::e_div == cob_opr) ||\n                          (details::e_mul == cob_opr)\n                        )\n                     {\n                        switch (cob_opr)\n                        {\n                           case details::e_div : cobnode->set_c(c * cobnode->c()); break;\n                           case details::e_mul : cobnode->set_c(cobnode->c() / c); break;\n                           default             : return error_node();\n                        }\n\n                        return cobnode;\n                     }\n                  }\n                  else if (operation == details::e_div)\n                  {\n                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);\n                     details::operator_type cob_opr = cobnode->operation();\n\n                     if (\n                          (details::e_div == cob_opr) ||\n                          (details::e_mul == cob_opr)\n                        )\n                     {\n                        details::expression_node<Type>* new_cobnode = error_node();\n\n                        switch (cob_opr)\n                        {\n                           case details::e_div : new_cobnode = expr_gen.node_allocator_->\n                                                    template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >\n                                                       (c / cobnode->c(),cobnode->move_branch(0));\n                                                 break;\n\n                           case details::e_mul : new_cobnode = expr_gen.node_allocator_->\n                                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >\n                                                       (c / cobnode->c(),cobnode->move_branch(0));\n                                                 break;\n\n                           default             : return error_node();\n                        }\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n\n                        return new_cobnode;\n                     }\n                  }\n               }\n               #ifndef exprtk_disable_enhanced_features\n               else if (details::is_sf3ext_node(branch[1]))\n               {\n                  expression_node_ptr result = error_node();\n\n                  if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))\n                  {\n                     free_node(*expr_gen.node_allocator_,branch[1]);\n\n                     return result;\n                  }\n               }\n               #endif\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_tt<typename details::cob_node<Type,op1<Type> > > \\\n                                   (c,  branch[1]);                                                \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_boc_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))\n               {\n                  free_node(*expr_gen.node_allocator_,branch[0]);\n\n                  return expr_gen(T(0));\n               }\n               else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))\n               {\n                  free_node(*expr_gen.node_allocator_, branch[0]);\n\n                  return expr_gen(std::numeric_limits<T>::quiet_NaN());\n               }\n               else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))\n                  return branch[0];\n               else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))\n                  return branch[0];\n\n               if (details::is_boc_node(branch[0]))\n               {\n                  // Simplify expressions of the form:\n                  // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320\n                  // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45\n                  if (\n                       (operation == details::e_mul) ||\n                       (operation == details::e_add)\n                     )\n                  {\n                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);\n\n                     if (operation == bocnode->operation())\n                     {\n                        switch (operation)\n                        {\n                           case details::e_add : bocnode->set_c(c + bocnode->c()); break;\n                           case details::e_mul : bocnode->set_c(c * bocnode->c()); break;\n                           default             : return error_node();\n                        }\n\n                        return bocnode;\n                     }\n                  }\n                  else if (operation == details::e_div)\n                  {\n                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);\n                     details::operator_type        boc_opr = bocnode->operation();\n\n                     if (\n                          (details::e_div == boc_opr) ||\n                          (details::e_mul == boc_opr)\n                        )\n                     {\n                        switch (boc_opr)\n                        {\n                           case details::e_div : bocnode->set_c(c * bocnode->c()); break;\n                           case details::e_mul : bocnode->set_c(bocnode->c() / c); break;\n                           default             : return error_node();\n                        }\n\n                        return bocnode;\n                     }\n                  }\n                  else if (operation == details::e_pow)\n                  {\n                     // (v ^ c0) ^ c1 --> v ^(c0 * c1)\n                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);\n                     details::operator_type        boc_opr = bocnode->operation();\n\n                     if (details::e_pow == boc_opr)\n                     {\n                        bocnode->set_c(bocnode->c() * c);\n\n                        return bocnode;\n                     }\n                  }\n               }\n\n               #ifndef exprtk_disable_enhanced_features\n               if (details::is_sf3ext_node(branch[0]))\n               {\n                  expression_node_ptr result = error_node();\n\n                  const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<ctype>\n                                                   (expr_gen, c, operation, branch[0], result);\n\n                  if (synthesis_result)\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n\n                     return result;\n                  }\n               }\n               #endif\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_cr<typename details::boc_node<Type,op1<Type> > > \\\n                                   (branch[0], c);                                                 \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_cocob_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               expression_node_ptr result = error_node();\n\n               // (cob) o c --> cob\n               if (details::is_cob_node(branch[0]))\n               {\n                  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);\n\n                  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n\n                  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return expr_gen(T(0));\n                  }\n                  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));\n                  }\n                  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return branch[0];\n                  }\n                  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return branch[0];\n                  }\n                  else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return branch[0];\n                  }\n\n                  const bool op_addsub = (details::e_add == cobnode->operation()) ||\n                                         (details::e_sub == cobnode->operation()) ;\n\n                  if (op_addsub)\n                  {\n                     switch (operation)\n                     {\n                        case details::e_add : cobnode->set_c(cobnode->c() + c); break;\n                        case details::e_sub : cobnode->set_c(cobnode->c() - c); break;\n                        default             : return error_node();\n                     }\n\n                     result = cobnode;\n                  }\n                  else if (details::e_mul == cobnode->operation())\n                  {\n                     switch (operation)\n                     {\n                        case details::e_mul : cobnode->set_c(cobnode->c() * c); break;\n                        case details::e_div : cobnode->set_c(cobnode->c() / c); break;\n                        default             : return error_node();\n                     }\n\n                     result = cobnode;\n                  }\n                  else if (details::e_div == cobnode->operation())\n                  {\n                     if (details::e_mul == operation)\n                     {\n                        cobnode->set_c(cobnode->c() * c);\n                        result = cobnode;\n                     }\n                     else if (details::e_div == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >\n                                       (cobnode->c() / c, cobnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_, branch[0]);\n                     }\n                  }\n\n                  if (result)\n                  {\n                     free_node(*expr_gen.node_allocator_,branch[1]);\n                  }\n               }\n\n               // c o (cob) --> cob\n               else if (details::is_cob_node(branch[1]))\n               {\n                  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);\n\n                  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();\n\n                  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return expr_gen(T(0));\n                  }\n                  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n\n                     return expr_gen(T(0));\n                  }\n                  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n\n                     return branch[1];\n                  }\n                  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[0]);\n\n                     return branch[1];\n                  }\n\n                  if (details::e_add == cobnode->operation())\n                  {\n                     if (details::e_add == operation)\n                     {\n                        cobnode->set_c(c + cobnode->c());\n                        result = cobnode;\n                     }\n                     else if (details::e_sub == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >\n                                       (c - cobnode->c(), cobnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n                  else if (details::e_sub == cobnode->operation())\n                  {\n                     if (details::e_add == operation)\n                     {\n                        cobnode->set_c(c + cobnode->c());\n                        result = cobnode;\n                     }\n                     else if (details::e_sub == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >\n                                       (c - cobnode->c(), cobnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n                  else if (details::e_mul == cobnode->operation())\n                  {\n                     if (details::e_mul == operation)\n                     {\n                        cobnode->set_c(c * cobnode->c());\n                        result = cobnode;\n                     }\n                     else if (details::e_div == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >\n                                       (c / cobnode->c(), cobnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n                  else if (details::e_div == cobnode->operation())\n                  {\n                     if (details::e_mul == operation)\n                     {\n                        cobnode->set_c(c * cobnode->c());\n                        result = cobnode;\n                     }\n                     else if (details::e_div == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >\n                                       (c / cobnode->c(), cobnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n\n                  if (result)\n                  {\n                     free_node(*expr_gen.node_allocator_,branch[0]);\n                  }\n               }\n\n               return result;\n            }\n         };\n\n         struct synthesize_coboc_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               expression_node_ptr result = error_node();\n\n               // (boc) o c --> boc\n               if (details::is_boc_node(branch[0]))\n               {\n                  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);\n\n                  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n\n                  if (details::e_add == bocnode->operation())\n                  {\n                     switch (operation)\n                     {\n                        case details::e_add : bocnode->set_c(bocnode->c() + c); break;\n                        case details::e_sub : bocnode->set_c(bocnode->c() - c); break;\n                        default             : return error_node();\n                     }\n\n                     result = bocnode;\n                  }\n                  else if (details::e_mul == bocnode->operation())\n                  {\n                     switch (operation)\n                     {\n                        case details::e_mul : bocnode->set_c(bocnode->c() * c); break;\n                        case details::e_div : bocnode->set_c(bocnode->c() / c); break;\n                        default             : return error_node();\n                     }\n\n                     result = bocnode;\n                  }\n                  else if (details::e_sub == bocnode->operation())\n                  {\n                     if (details::e_add == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >\n                                       (bocnode->move_branch(0), c - bocnode->c());\n\n                        free_node(*expr_gen.node_allocator_,branch[0]);\n                     }\n                     else if (details::e_sub == operation)\n                     {\n                        bocnode->set_c(bocnode->c() + c);\n                        result = bocnode;\n                     }\n                  }\n                  else if (details::e_div == bocnode->operation())\n                  {\n                     switch (operation)\n                     {\n                        case details::e_div : bocnode->set_c(bocnode->c() * c); break;\n                        case details::e_mul : bocnode->set_c(bocnode->c() / c); break;\n                        default             : return error_node();\n                     }\n\n                     result = bocnode;\n                  }\n\n                  if (result)\n                  {\n                     free_node(*expr_gen.node_allocator_, branch[1]);\n                  }\n               }\n\n               // c o (boc) --> boc\n               else if (details::is_boc_node(branch[1]))\n               {\n                  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);\n\n                  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();\n\n                  if (details::e_add == bocnode->operation())\n                  {\n                     if (details::e_add == operation)\n                     {\n                        bocnode->set_c(c + bocnode->c());\n                        result = bocnode;\n                     }\n                     else if (details::e_sub == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >\n                                       (c - bocnode->c(), bocnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n                  else if (details::e_sub == bocnode->operation())\n                  {\n                     if (details::e_add == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >\n                                       (bocnode->move_branch(0), c - bocnode->c());\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                     else if (details::e_sub == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >\n                                       (c + bocnode->c(), bocnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n                  else if (details::e_mul == bocnode->operation())\n                  {\n                     if (details::e_mul == operation)\n                     {\n                        bocnode->set_c(c * bocnode->c());\n                        result = bocnode;\n                     }\n                     else if (details::e_div == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >\n                                       (c / bocnode->c(), bocnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n                  else if (details::e_div == bocnode->operation())\n                  {\n                     if (details::e_mul == operation)\n                     {\n                        bocnode->set_c(bocnode->c() / c);\n                        result = bocnode;\n                     }\n                     else if (details::e_div == operation)\n                     {\n                        result = expr_gen.node_allocator_->\n                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >\n                                       (c * bocnode->c(), bocnode->move_branch(0));\n\n                        free_node(*expr_gen.node_allocator_,branch[1]);\n                     }\n                  }\n\n                  if (result)\n                  {\n                     free_node(*expr_gen.node_allocator_,branch[0]);\n                  }\n               }\n\n               return result;\n            }\n         };\n\n         #ifndef exprtk_disable_enhanced_features\n         inline bool synthesize_expression(const details::operator_type& operation,\n                                           expression_node_ptr (&branch)[2],\n                                           expression_node_ptr& result)\n         {\n            result = error_node();\n\n            if (!operation_optimisable(operation))\n               return false;\n\n            const std::string node_id = branch_to_id(branch);\n\n            const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);\n\n            if (synthesize_map_.end() != itr)\n            {\n               result = itr->second((*this), operation, branch);\n\n               return true;\n            }\n            else\n               return false;\n         }\n\n         struct synthesize_vov_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_rr<typename details::vov_node<Type,op1<Type> > > \\\n                                   (v1, v2);                                                       \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_cov_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();\n               const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref  ();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))\n                  return expr_gen(T(0));\n               else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))\n                  return expr_gen(T(0));\n               else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))\n                  return static_cast<details::variable_node<Type>*>(branch[1]);\n               else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))\n                  return static_cast<details::variable_node<Type>*>(branch[1]);\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_cr<typename details::cov_node<Type,op1<Type> > > \\\n                                   (c, v);                                                         \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_voc_expression\n         {\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref  ();\n               const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();\n\n               details::free_node(*(expr_gen.node_allocator_), branch[1]);\n\n               if (expr_gen.cardinal_pow_optimisable(operation,c))\n               {\n                  if (std::equal_to<T>()(T(1),c))\n                     return branch[0];\n                  else\n                     return expr_gen.cardinal_pow_optimisation(v,c);\n               }\n               else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))\n                  return expr_gen(T(0));\n               else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))\n                  return expr_gen(std::numeric_limits<T>::quiet_NaN());\n               else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))\n                  return static_cast<details::variable_node<Type>*>(branch[0]);\n               else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))\n                  return static_cast<details::variable_node<Type>*>(branch[0]);\n               else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))\n                  return static_cast<details::variable_node<Type>*>(branch[0]);\n\n               switch (operation)\n               {\n                  #define case_stmt(op0,op1)                                                       \\\n                  case op0 : return expr_gen.node_allocator_->                                     \\\n                                template allocate_rc<typename details::voc_node<Type,op1<Type> > > \\\n                                   (v, c);                                                         \\\n\n                  basic_opr_switch_statements\n                  extended_opr_switch_statements\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n         };\n\n         struct synthesize_sf3ext_expression\n         {\n            template <typename T0, typename T1, typename T2>\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& sf3opr,\n                                                      T0 t0, T1 t1, T2 t2)\n            {\n               switch (sf3opr)\n               {\n                  #define case_stmt(op)                                                                              \\\n                  case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \\\n                                allocate(*(expr_gen.node_allocator_), t0, t1, t2);                                   \\\n\n                  case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)\n                  case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)\n                  case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)\n                  case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)\n                  case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)\n                  case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)\n                  case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)\n                  case_stmt(28) case_stmt(29) case_stmt(30)\n                  #undef case_stmt\n                  default : return error_node();\n               }\n            }\n\n            template <typename T0, typename T1, typename T2>\n            static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,\n                                       T0 t0, T1 t1, T2 t2,\n                                       expression_node_ptr& result)\n            {\n               details::operator_type sf3opr;\n\n               if (!expr_gen.sf3_optimisable(id,sf3opr))\n                  return false;\n               else\n                  result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);\n\n               return true;\n            }\n         };\n\n         struct synthesize_sf4ext_expression\n         {\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& sf4opr,\n                                                      T0 t0, T1 t1, T2 t2, T3 t3)\n            {\n               switch (sf4opr)\n               {\n                  #define case_stmt0(op)                                                                                      \\\n                  case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \\\n                                allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                        \\\n\n\n                  #define case_stmt1(op)                                                                                             \\\n                  case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \\\n                                allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3);                                               \\\n\n                  case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)\n                  case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)\n                  case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)\n                  case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)\n                  case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)\n                  case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)\n                  case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)\n                  case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)\n                  case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)\n\n                  case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)\n                  case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)\n                  case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)\n                  case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)\n                  case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)\n                  case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)\n                  case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)\n                  case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)\n                  case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)\n                  case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)\n                  case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)\n                  case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)\n                  case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)\n                  case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)\n                  case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)\n                  case_stmt1(60) case_stmt1(61)\n\n                  #undef case_stmt0\n                  #undef case_stmt1\n                  default : return error_node();\n               }\n            }\n\n            template <typename T0, typename T1, typename T2, typename T3>\n            static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,\n                                       T0 t0, T1 t1, T2 t2, T3 t3,\n                                       expression_node_ptr& result)\n            {\n               details::operator_type sf4opr;\n\n               if (!expr_gen.sf4_optimisable(id,sf4opr))\n                  return false;\n               else\n                  result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>\n                              (expr_gen, sf4opr, t0, t1, t2, t3);\n\n               return true;\n            }\n\n            // T o (sf3ext)\n            template <typename ExternalType>\n            static inline bool compile_right(expression_generator<Type>& expr_gen,\n                                             ExternalType t,\n                                             const details::operator_type& operation,\n                                             expression_node_ptr& sf3node,\n                                             expression_node_ptr& result)\n            {\n               if (!details::is_sf3ext_node(sf3node))\n                  return false;\n\n               typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;\n\n               sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);\n               std::string id = \"t\" + expr_gen.to_str(operation) + \"(\" + n->type_id() + \")\";\n\n               switch (n->type())\n               {\n                  case details::expression_node<Type>::e_covoc : return compile_right_impl\n                                                                    <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_covov : return compile_right_impl\n                                                                    <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_vocov : return compile_right_impl\n                                                                    <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_vovoc : return compile_right_impl\n                                                                    <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_vovov : return compile_right_impl\n                                                                    <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  default                                      : return false;\n               }\n            }\n\n            // (sf3ext) o T\n            template <typename ExternalType>\n            static inline bool compile_left(expression_generator<Type>& expr_gen,\n                                            ExternalType t,\n                                            const details::operator_type& operation,\n                                            expression_node_ptr& sf3node,\n                                            expression_node_ptr& result)\n            {\n               if (!details::is_sf3ext_node(sf3node))\n                  return false;\n\n               typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;\n\n               sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);\n\n               std::string id = \"(\" + n->type_id() + \")\" + expr_gen.to_str(operation) + \"t\";\n\n               switch (n->type())\n               {\n                  case details::expression_node<Type>::e_covoc : return compile_left_impl\n                                                                    <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_covov : return compile_left_impl\n                                                                    <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_vocov : return compile_left_impl\n                                                                    <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_vovoc : return compile_left_impl\n                                                                    <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  case details::expression_node<Type>::e_vovov : return compile_left_impl\n                                                                    <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>\n                                                                       (expr_gen, id, t, sf3node, result);\n\n                  default                                      : return false;\n               }\n            }\n\n            template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>\n            static inline bool compile_right_impl(expression_generator<Type>& expr_gen,\n                                                  const std::string& id,\n                                                  ExternalType t,\n                                                  expression_node_ptr& node,\n                                                  expression_node_ptr& result)\n            {\n               SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);\n\n               if (n)\n               {\n                  T0 t0 = n->t0();\n                  T1 t1 = n->t1();\n                  T2 t2 = n->t2();\n\n                  return synthesize_sf4ext_expression::template compile<ExternalType,T0,T1,T2>\n                            (expr_gen, id, t, t0, t1, t2, result);\n               }\n               else\n                  return false;\n            }\n\n            template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>\n            static inline bool compile_left_impl(expression_generator<Type>& expr_gen,\n                                                 const std::string& id,\n                                                 ExternalType t,\n                                                 expression_node_ptr& node,\n                                                 expression_node_ptr& result)\n            {\n               SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);\n\n               if (n)\n               {\n                  T0 t0 = n->t0();\n                  T1 t1 = n->t1();\n                  T2 t2 = n->t2();\n\n                  return synthesize_sf4ext_expression::template compile<T0,T1,T2,ExternalType>\n                            (expr_gen, id, t0, t1, t2, t, result);\n               }\n               else\n                  return false;\n            }\n         };\n\n         struct synthesize_vovov_expression0\n         {\n            typedef typename vovov_t::type0 node_type;\n            typedef typename vovov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 v1) o1 (v2)\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);\n               const Type& v0 = vov->v0();\n               const Type& v1 = vov->v1();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = vov->operation();\n               const details::operator_type o1 = operation;\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,vtype>(expr_gen, \"t/(t*t)\", v0, v1, v2, result);\n\n                     exprtk_debug((\"(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t\");\n            }\n         };\n\n         struct synthesize_vovov_expression1\n         {\n            typedef typename vovov_t::type1 node_type;\n            typedef typename vovov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0) o0 (v1 o1 v2)\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vov->v0();\n               const Type& v2 = vov->v1();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = vov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,vtype>(expr_gen, \"(t*t)/t\", v0, v2, v1, result);\n\n                     exprtk_debug((\"v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\");\n            }\n         };\n\n         struct synthesize_vovoc_expression0\n         {\n            typedef typename vovoc_t::type0 node_type;\n            typedef typename vovoc_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 v1) o1 (c)\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);\n               const Type& v0 = vov->v0();\n               const Type& v1 = vov->v1();\n               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = vov->operation();\n               const details::operator_type o1 = operation;\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,ctype>(expr_gen, \"t/(t*t)\", v0, v1, c, result);\n\n                     exprtk_debug((\"(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>\n                     (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t\");\n            }\n         };\n\n         struct synthesize_vovoc_expression1\n         {\n            typedef typename vovoc_t::type1 node_type;\n            typedef typename vovoc_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0) o0 (v1 o1 c)\n               const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = voc->v();\n               const Type   c = voc->c();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = voc->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,ctype,vtype>(expr_gen, \"(t*t)/t\", v0, c, v1, result);\n\n                     exprtk_debug((\"v0 / (v1 / c) --> (vocov) (v0 * c) / v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>\n                     (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\");\n            }\n         };\n\n         struct synthesize_vocov_expression0\n         {\n            typedef typename vocov_t::type0 node_type;\n            typedef typename vocov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 c) o1 (v1)\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);\n               const Type& v0 = voc->v();\n               const Type   c = voc->c();\n               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = voc->operation();\n               const details::operator_type o1 = operation;\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,ctype>(expr_gen, \"t/(t*t)\", v0, v1, c, result);\n\n                     exprtk_debug((\"(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t\");\n            }\n         };\n\n         struct synthesize_vocov_expression1\n         {\n            typedef typename vocov_t::type1 node_type;\n            typedef typename vocov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0) o0 (c o1 v1)\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type   c = cov->c();\n               const Type& v1 = cov->v();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = cov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype, vtype, ctype>(expr_gen, \"(t*t)/t\", v0, v1, c, result);\n\n                     exprtk_debug((\"v0 / (c / v1) --> (vovoc) (v0 * v1) / c\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\");\n            }\n         };\n\n         struct synthesize_covov_expression0\n         {\n            typedef typename covov_t::type0 node_type;\n            typedef typename covov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c o0 v0) o1 (v1)\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);\n               const Type   c = cov->c();\n               const Type& v0 = cov->v();\n               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = cov->operation();\n               const details::operator_type o1 = operation;\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c / v0) / v1 --> (covov) c / (v0 * v1)\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype, vtype, vtype>(expr_gen, \"t/(t*t)\", c, v0, v1, result);\n\n                     exprtk_debug((\"(c / v0) / v1 --> (covov) c / (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t\");\n            }\n         };\n\n         struct synthesize_covov_expression1\n         {\n            typedef typename covov_t::type1 node_type;\n            typedef typename covov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c) o0 (v0 o1 v1)\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);\n               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vov->v0();\n               const Type& v1 = vov->v1();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = vov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // c / (v0 / v1) --> (covov) (c * v1) / v0\n                  if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype, vtype, vtype>(expr_gen, \"(t*t)/t\", c, v1, v0, result);\n\n                     exprtk_debug((\"c / (v0 / v1) --> (covov) (c * v1) / v0\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\");\n            }\n         };\n\n         struct synthesize_covoc_expression0\n         {\n            typedef typename covoc_t::type0 node_type;\n            typedef typename covoc_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c0 o0 v) o1 (c1)\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);\n               const Type  c0 = cov->c();\n               const Type&  v = cov->v();\n               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = cov->operation();\n               const details::operator_type o1 = operation;\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c0 + v) + c1 --> (cov) (c0 + c1) + v\n                  if ((details::e_add == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(c0 + v) + c1 --> (cov) (c0 + c1) + v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);\n                  }\n                  // (c0 + v) - c1 --> (cov) (c0 - c1) + v\n                  else if ((details::e_add == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(c0 + v) - c1 --> (cov) (c0 - c1) + v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);\n                  }\n                  // (c0 - v) + c1 --> (cov) (c0 + c1) - v\n                  else if ((details::e_sub == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(c0 - v) + c1 --> (cov) (c0 + c1) - v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);\n                  }\n                  // (c0 - v) - c1 --> (cov) (c0 - c1) - v\n                  else if ((details::e_sub == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(c0 - v) - c1 --> (cov) (c0 - c1) - v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);\n                  }\n                  // (c0 * v) * c1 --> (cov) (c0 * c1) * v\n                  else if ((details::e_mul == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(c0 * v) * c1 --> (cov) (c0 * c1) * v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);\n                  }\n                  // (c0 * v) / c1 --> (cov) (c0 / c1) * v\n                  else if ((details::e_mul == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(c0 * v) / c1 --> (cov) (c0 / c1) * v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);\n                  }\n                  // (c0 / v) * c1 --> (cov) (c0 * c1) / v\n                  else if ((details::e_div == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(c0 / v) * c1 --> (cov) (c0 * c1) / v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);\n                  }\n                  // (c0 / v) / c1 --> (cov) (c0 / c1) / v\n                  else if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(c0 / v) / c1 --> (cov) (c0 / c1) / v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>\n                     (expr_gen, id(expr_gen, o0, o1), c0, v, c1,result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t\");\n            }\n         };\n\n         struct synthesize_covoc_expression1\n         {\n            typedef typename covoc_t::type1 node_type;\n            typedef typename covoc_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c0) o0 (v o1 c1)\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);\n               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type&  v = voc->v();\n               const Type  c1 = voc->c();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = voc->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c0) + (v + c1) --> (cov) (c0 + c1) + v\n                  if ((details::e_add == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(c0) + (v + c1) --> (cov) (c0 + c1) + v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);\n                  }\n                  // (c0) + (v - c1) --> (cov) (c0 - c1) + v\n                  else if ((details::e_add == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(c0) + (v - c1) --> (cov) (c0 - c1) + v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);\n                  }\n                  // (c0) - (v + c1) --> (cov) (c0 - c1) - v\n                  else if ((details::e_sub == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(c0) - (v + c1) --> (cov) (c0 - c1) - v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);\n                  }\n                  // (c0) - (v - c1) --> (cov) (c0 + c1) - v\n                  else if ((details::e_sub == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(c0) - (v - c1) --> (cov) (c0 + c1) - v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);\n                  }\n                  // (c0) * (v * c1) --> (voc) v * (c0 * c1)\n                  else if ((details::e_mul == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(c0) * (v * c1) --> (voc) v * (c0 * c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);\n                  }\n                  // (c0) * (v / c1) --> (cov) (c0 / c1) * v\n                  else if ((details::e_mul == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(c0) * (v / c1) --> (cov) (c0 / c1) * v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);\n                  }\n                  // (c0) / (v * c1) --> (cov) (c0 / c1) / v\n                  else if ((details::e_div == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(c0) / (v * c1) --> (cov) (c0 / c1) / v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);\n                  }\n                  // (c0) / (v / c1) --> (cov) (c0 * c1) / v\n                  else if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(c0) / (v / c1) --> (cov) (c0 * c1) / v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>\n                     (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\");\n            }\n         };\n\n         struct synthesize_cocov_expression0\n         {\n            typedef typename cocov_t::type0 node_type;\n            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])\n            {\n               // (c0 o0 c1) o1 (v) - Not possible.\n               return error_node();\n            }\n         };\n\n         struct synthesize_cocov_expression1\n         {\n            typedef typename cocov_t::type1 node_type;\n            typedef typename cocov_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c0) o0 (c1 o1 v)\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);\n               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type  c1 = cov->c();\n               const Type&  v = cov->v();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = cov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c0) + (c1 + v) --> (cov) (c0 + c1) + v\n                  if ((details::e_add == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(c0) + (c1 + v) --> (cov) (c0 + c1) + v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);\n                  }\n                  // (c0) + (c1 - v) --> (cov) (c0 + c1) - v\n                  else if ((details::e_add == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(c0) + (c1 - v) --> (cov) (c0 + c1) - v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);\n                  }\n                  // (c0) - (c1 + v) --> (cov) (c0 - c1) - v\n                  else if ((details::e_sub == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(c0) - (c1 + v) --> (cov) (c0 - c1) - v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);\n                  }\n                  // (c0) - (c1 - v) --> (cov) (c0 - c1) + v\n                  else if ((details::e_sub == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(c0) - (c1 - v) --> (cov) (c0 - c1) + v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);\n                  }\n                  // (c0) * (c1 * v) --> (cov) (c0 * c1) * v\n                  else if ((details::e_mul == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(c0) * (c1 * v) --> (cov) (c0 * c1) * v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);\n                  }\n                  // (c0) * (c1 / v) --> (cov) (c0 * c1) / v\n                  else if ((details::e_mul == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(c0) * (c1 / v) --> (cov) (c0 * c1) / v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);\n                  }\n                  // (c0) / (c1 * v) --> (cov) (c0 / c1) / v\n                  else if ((details::e_div == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(c0) / (c1 * v) --> (cov) (c0 / c1) / v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);\n                  }\n                  // (c0) / (c1 / v) --> (cov) (c0 / c1) * v\n                  else if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(c0) / (c1 / v) --> (cov) (c0 / c1) * v\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>\n                     (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\");\n            }\n         };\n\n         struct synthesize_vococ_expression0\n         {\n            typedef typename vococ_t::type0 node_type;\n            typedef typename vococ_t::sf3_type sf3_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v o0 c0) o1 (c1)\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);\n               const Type&  v = voc->v();\n               const Type& c0 = voc->c();\n               const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = voc->operation();\n               const details::operator_type o1 = operation;\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v + c0) + c1 --> (voc) v + (c0 + c1)\n                  if ((details::e_add == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(v + c0) + c1 --> (voc) v + (c0 + c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);\n                  }\n                  // (v + c0) - c1 --> (voc) v + (c0 - c1)\n                  else if ((details::e_add == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(v + c0) - c1 --> (voc) v + (c0 - c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);\n                  }\n                  // (v - c0) + c1 --> (voc) v - (c0 + c1)\n                  else if ((details::e_sub == o0) && (details::e_add == o1))\n                  {\n                     exprtk_debug((\"(v - c0) + c1 --> (voc) v - (c0 + c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);\n                  }\n                  // (v - c0) - c1 --> (voc) v - (c0 + c1)\n                  else if ((details::e_sub == o0) && (details::e_sub == o1))\n                  {\n                     exprtk_debug((\"(v - c0) - c1 --> (voc) v - (c0 + c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);\n                  }\n                  // (v * c0) * c1 --> (voc) v * (c0 * c1)\n                  else if ((details::e_mul == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(v * c0) * c1 --> (voc) v * (c0 * c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);\n                  }\n                  // (v * c0) / c1 --> (voc) v * (c0 / c1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(v * c0) / c1 --> (voc) v * (c0 / c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);\n                  }\n                  // (v / c0) * c1 --> (voc) v * (c1 / c0)\n                  else if ((details::e_div == o0) && (details::e_mul == o1))\n                  {\n                     exprtk_debug((\"(v / c0) * c1 --> (voc) v * (c1 / c0)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);\n                  }\n                  // (v / c0) / c1 --> (voc) v / (c0 * c1)\n                  else if ((details::e_div == o0) && (details::e_div == o1))\n                  {\n                     exprtk_debug((\"(v / c0) / c1 --> (voc) v / (c0 * c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);\n                  }\n                  // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n                  else if ((details::e_pow == o0) && (details::e_pow == o1))\n                  {\n                     exprtk_debug((\"(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\\n\"));\n\n                     return expr_gen.node_allocator_->\n                               template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>\n                     (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0, const details::operator_type o1)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t\");\n            }\n         };\n\n         struct synthesize_vococ_expression1\n         {\n            typedef typename vococ_t::type0 node_type;\n\n            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])\n            {\n               // (v) o0 (c0 o1 c1) - Not possible.\n               exprtk_debug((\"(v) o0 (c0 o1 c1) - Not possible.\\n\"));\n               return error_node();\n            }\n         };\n\n         struct synthesize_vovovov_expression0\n         {\n            typedef typename vovovov_t::type0 node_type;\n            typedef typename vovovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 v1) o1 (v2 o2 v3)\n               const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);\n               const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);\n               const Type& v0 = vov0->v0();\n               const Type& v1 = vov0->v1();\n               const Type& v2 = vov1->v0();\n               const Type& v3 = vov1->v1();\n               const details::operator_type o0 = vov0->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = vov1->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,vtype>(expr_gen, \"(t*t)/(t*t)\", v0, v2, v1, v3, result);\n\n                     exprtk_debug((\"(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,vtype>(expr_gen, \"(t*t)/(t*t)\", v0, v3, v1, v2, result);\n\n                     exprtk_debug((\"(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n                  else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,vtype>(expr_gen, \"(t+t)*(t/t)\", v0, v1, v3, v2, result);\n\n                     exprtk_debug((\"(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n                  else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,vtype>(expr_gen, \"(t-t)*(t/t)\", v0, v1, v3, v2, result);\n\n                     exprtk_debug((\"(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,vtype>(expr_gen, \"((t*t)*t)/t\", v0, v1, v3, v2, result);\n\n                     exprtk_debug((\"(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3,result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vovovoc_expression0\n         {\n            typedef typename vovovoc_t::type0 node_type;\n            typedef typename vovovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 v1) o1 (v2 o2 c)\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);\n               const Type& v0 = vov->v0();\n               const Type& v1 = vov->v1();\n               const Type& v2 = voc->v ();\n               const Type   c = voc->c ();\n               const details::operator_type o0 = vov->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = voc->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,ctype>(expr_gen, \"(t*t)/(t*t)\", v0, v2, v1, c, result);\n\n                     exprtk_debug((\"(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,ctype,vtype,vtype>(expr_gen, \"(t*t)/(t*t)\", v0, c, v1, v2, result);\n\n                     exprtk_debug((\"(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vovocov_expression0\n         {\n            typedef typename vovocov_t::type0 node_type;\n            typedef typename vovocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 v1) o1 (c o2 v2)\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);\n               const Type& v0 = vov->v0();\n               const Type& v1 = vov->v1();\n               const Type& v2 = cov->v ();\n               const Type   c = cov->c ();\n               const details::operator_type o0 = vov->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = cov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,ctype,vtype,vtype>(expr_gen, \"(t*t)/(t*t)\", v0, c, v1, v2, result);\n\n                     exprtk_debug((\"(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,vtype,ctype>(expr_gen, \"(t*t)/(t*t)\", v0, v2, v1, c, result);\n\n                     exprtk_debug((\"(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vocovov_expression0\n         {\n            typedef typename vocovov_t::type0 node_type;\n            typedef typename vocovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 c) o1 (v1 o2 v2)\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);\n               const Type   c = voc->c ();\n               const Type& v0 = voc->v ();\n               const Type& v1 = vov->v0();\n               const Type& v2 = vov->v1();\n               const details::operator_type o0 = voc->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = vov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,ctype,vtype>(expr_gen, \"(t*t)/(t*t)\", v0, v1, c, v2, result);\n\n                     exprtk_debug((\"(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,vtype,ctype,vtype>(expr_gen, \"(t*t)/(t*t)\", v0, v2, c, v1, result);\n\n                     exprtk_debug((\"(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_covovov_expression0\n         {\n            typedef typename covovov_t::type0 node_type;\n            typedef typename covovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c o0 v0) o1 (v1 o2 v2)\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);\n               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);\n               const Type   c = cov->c ();\n               const Type& v0 = cov->v ();\n               const Type& v1 = vov->v0();\n               const Type& v2 = vov->v1();\n               const details::operator_type o0 = cov->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = vov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<ctype,vtype,vtype,vtype>(expr_gen, \"(t*t)/(t*t)\", c, v1, v0, v2, result);\n\n                     exprtk_debug((\"(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<ctype,vtype,vtype,vtype>(expr_gen, \"(t*t)/(t*t)\", c, v2, v0, v1, result);\n\n                     exprtk_debug((\"(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_covocov_expression0\n         {\n            typedef typename covocov_t::type0 node_type;\n            typedef typename covocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c0 o0 v0) o1 (c1 o2 v1)\n               const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);\n               const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);\n               const Type  c0 = cov0->c();\n               const Type& v0 = cov0->v();\n               const Type  c1 = cov1->c();\n               const Type& v1 = cov1->v();\n               const details::operator_type o0 = cov0->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = cov1->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)+t\", (c0 + c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)-t\", (c0 - c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t-t)+t\", (c0 - c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)*t\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t/(t*t)\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c0 / c1), v1, v0, result);\n\n                     exprtk_debug((\"(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t*(t*t)\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t/(t*t)\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n                  else if (\n                            (std::equal_to<T>()(c0,c1)) &&\n                            (details::e_mul == o0)      &&\n                            (details::e_mul == o2)      &&\n                            (\n                              (details::e_add == o1) ||\n                              (details::e_sub == o1)\n                            )\n                          )\n                  {\n                     std::string specfunc;\n\n                     switch (o1)\n                     {\n                        case details::e_add : specfunc = \"t*(t+t)\"; break;\n                        case details::e_sub : specfunc = \"t*(t-t)\"; break;\n                        default             : return error_node();\n                     }\n\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);\n\n                     exprtk_debug((\"(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vocovoc_expression0\n         {\n            typedef typename vocovoc_t::type0 node_type;\n            typedef typename vocovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 c0) o1 (v1 o2 c1)\n               const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);\n               const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);\n               const Type  c0 = voc0->c();\n               const Type& v0 = voc0->v();\n               const Type  c1 = voc1->c();\n               const Type& v1 = voc1->v();\n               const details::operator_type o0 = voc0->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = voc1->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)+t\", (c0 + c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)-t\", (c0 - c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)-t\", (c1 - c0), v0, v1, result);\n\n                     exprtk_debug((\"(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)*t\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)*t\", Type(1) / (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c1 / c0), v0, v1, result);\n\n                     exprtk_debug((\"(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t*(t/t)\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t*(t/t)\", Type(1) / (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,ctype,vtype,ctype>(expr_gen, \"(t*t)*(t+t)\", v0, T(1) / c0, v1, c1, result);\n\n                     exprtk_debug((\"(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf4ext_expression::\n                           template compile<vtype,ctype,vtype,ctype>(expr_gen, \"(t*t)*(t-t)\", v0, T(1) / c0, v1, c1, result);\n\n                     exprtk_debug((\"(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n                  else if (\n                            (std::equal_to<T>()(c0,c1)) &&\n                            (details::e_mul == o0)      &&\n                            (details::e_mul == o2)      &&\n                            (\n                              (details::e_add == o1) ||\n                              (details::e_sub == o1)\n                            )\n                          )\n                  {\n                     std::string specfunc;\n\n                     switch (o1)\n                     {\n                        case details::e_add : specfunc = \"t*(t+t)\"; break;\n                        case details::e_sub : specfunc = \"t*(t-t)\"; break;\n                        default             : return error_node();\n                     }\n\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n                  else if (\n                            (std::equal_to<T>()(c0,c1)) &&\n                            (details::e_div == o0)      &&\n                            (details::e_div == o2)      &&\n                            (\n                              (details::e_add == o1) ||\n                              (details::e_sub == o1)\n                            )\n                          )\n                  {\n                     std::string specfunc;\n\n                     switch (o1)\n                     {\n                        case details::e_add : specfunc = \"(t+t)/t\"; break;\n                        case details::e_sub : specfunc = \"(t-t)/t\"; break;\n                        default             : return error_node();\n                     }\n\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);\n\n                     exprtk_debug((\"(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_covovoc_expression0\n         {\n            typedef typename covovoc_t::type0 node_type;\n            typedef typename covovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (c0 o0 v0) o1 (v1 o2 c1)\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);\n               const Type  c0 = cov->c();\n               const Type& v0 = cov->v();\n               const Type  c1 = voc->c();\n               const Type& v1 = voc->v();\n               const details::operator_type o0 = cov->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = voc->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)+t\", (c0 + c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)-t\", (c0 - c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t-(t+t)\", (c0 + c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)*t\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t*(t/t)\", (c0 / c1), v1, v0, result);\n\n                     exprtk_debug((\"(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t/(t*t)\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"t/(t*t)\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n                  else if (\n                            (std::equal_to<T>()(c0,c1)) &&\n                            (details::e_mul == o0)      &&\n                            (details::e_mul == o2)      &&\n                            (\n                              (details::e_add == o1) ||\n                              (details::e_sub == o1)\n                            )\n                          )\n                  {\n                     std::string specfunc;\n\n                     switch (o1)\n                     {\n                        case details::e_add : specfunc = \"t*(t+t)\"; break;\n                        case details::e_sub : specfunc = \"t*(t-t)\"; break;\n                        default             : return error_node();\n                     }\n\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);\n\n                     exprtk_debug((\"(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vococov_expression0\n         {\n            typedef typename vococov_t::type0 node_type;\n            typedef typename vococov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 c0) o1 (c1 o2 v1)\n               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);\n               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);\n               const Type  c0 = voc->c();\n               const Type& v0 = voc->v();\n               const Type  c1 = cov->c();\n               const Type& v1 = cov->v();\n               const details::operator_type o0 = voc->operation();\n               const details::operator_type o1 = operation;\n               const details::operator_type o2 = cov->operation();\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (expr_gen.parser_->settings_.strength_reduction_enabled())\n               {\n                  // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)+t\", (c0 + c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t+t)-t\", (c0 - c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,ctype>(expr_gen, \"(t+t)-t\", v0, v1, (c1 + c0), result);\n\n                     exprtk_debug((\"(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)*t\", (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", (c1 / c0), v0, v1, result);\n\n                     exprtk_debug((\"(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)*t\", (c0 / c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, \"(t*t)/t\", Type(1) / (c0 * c1), v0, v1, result);\n\n                     exprtk_debug((\"(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))\n                  {\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<vtype,vtype,ctype>(expr_gen, \"(t*t)*t\", v0, v1, Type(1) / (c0 * c1), result);\n\n                     exprtk_debug((\"(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n                  // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n                  else if (\n                            (std::equal_to<T>()(c0,c1)) &&\n                            (details::e_mul == o0)      &&\n                            (details::e_mul == o2)      &&\n                            (\n                              (details::e_add == o1) || (details::e_sub == o1)\n                            )\n                          )\n                  {\n                     std::string specfunc;\n\n                     switch (o1)\n                     {\n                        case details::e_add : specfunc = \"t*(t+t)\"; break;\n                        case details::e_sub : specfunc = \"t*(t-t)\"; break;\n                        default             : return error_node();\n                     }\n\n                     const bool synthesis_result =\n                        synthesize_sf3ext_expression::\n                           template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);\n\n                     exprtk_debug((\"(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\\n\"));\n\n                     return (synthesis_result) ? result : error_node();\n                  }\n               }\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o1,f1))\n                  return error_node();\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n               else\n                  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vovovov_expression1\n         {\n            typedef typename vovovov_t::type1 node_type;\n            typedef typename vovovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 (v1 o1 (v2 o2 v3))\n               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vovov->t0();\n               const Type& v2 = vovov->t1();\n               const Type& v3 = vovov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovov->f0();\n               binary_functor_t f2 = vovov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 (v1 o1 (v2 o2 v3))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_vovovoc_expression1\n         {\n            typedef typename vovovoc_t::type1 node_type;\n            typedef typename vovovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 (v1 o1 (v2 o2 c))\n               typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;\n\n               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vovoc->t0();\n               const Type& v2 = vovoc->t1();\n               const Type   c = vovoc->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovoc->f0();\n               binary_functor_t f2 = vovoc->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 (v1 o1 (v2 o2 c))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_vovocov_expression1\n         {\n            typedef typename vovocov_t::type1 node_type;\n            typedef typename vovocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 (v1 o1 (c o2 v2))\n               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vocov->t0();\n               const Type   c = vocov->t1();\n               const Type& v2 = vocov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vocov->f0();\n               binary_functor_t f2 = vocov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 (v1 o1 (c o2 v2))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_vocovov_expression1\n         {\n            typedef typename vocovov_t::type1 node_type;\n            typedef typename vocovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 (c o1 (v1 o2 v2))\n               typedef typename synthesize_covov_expression1::node_type lcl_covov_t;\n\n               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type   c = covov->t0();\n               const Type& v1 = covov->t1();\n               const Type& v2 = covov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(covov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(covov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = covov->f0();\n               binary_functor_t f2 = covov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 (c o1 (v1 o2 v2))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_covovov_expression1\n         {\n            typedef typename covovov_t::type1 node_type;\n            typedef typename covovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // c o0 (v0 o1 (v1 o2 v2))\n               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);\n               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vovov->t0();\n               const Type& v1 = vovov->t1();\n               const Type& v2 = vovov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovov->f0();\n               binary_functor_t f2 = vovov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"c o0 (v0 o1 (v1 o2 v2))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_covocov_expression1\n         {\n            typedef typename covocov_t::type1 node_type;\n            typedef typename covocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // c0 o0 (v0 o1 (c1 o2 v1))\n               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);\n               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vocov->t0();\n               const Type  c1 = vocov->t1();\n               const Type& v1 = vocov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vocov->f0();\n               binary_functor_t f2 = vocov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"c0 o0 (v0 o1 (c1 o2 v1))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_vocovoc_expression1\n         {\n            typedef typename vocovoc_t::type1 node_type;\n            typedef typename vocovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 (c0 o1 (v1 o2 c2))\n               typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;\n\n               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type  c0 = covoc->t0();\n               const Type& v1 = covoc->t1();\n               const Type  c1 = covoc->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(covoc->f0());\n               const details::operator_type o2 = expr_gen.get_operator(covoc->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = covoc->f0();\n               binary_functor_t f2 = covoc->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 (c0 o1 (v1 o2 c2))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_covovoc_expression1\n         {\n            typedef typename covovoc_t::type1 node_type;\n            typedef typename covovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // c0 o0 (v0 o1 (v1 o2 c1))\n               typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;\n\n               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);\n               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vovoc->t0();\n               const Type& v1 = vovoc->t1();\n               const Type  c1 = vovoc->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovoc->f0();\n               binary_functor_t f2 = vovoc->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"c0 o0 (v0 o1 (v1 o2 c1))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_vococov_expression1\n         {\n            typedef typename vococov_t::type1 node_type;\n            typedef typename vococov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 (c0 o1 (c1 o2 v1))\n               typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;\n\n               const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type  c0 = cocov->t0();\n               const Type  c1 = cocov->t1();\n               const Type& v1 = cocov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(cocov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(cocov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = cocov->f0();\n               binary_functor_t f2 = cocov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 (c0 o1 (c1 o2 v1))\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"(t\" << expr_gen.to_str(o2) << \"t))\");\n            }\n         };\n\n         struct synthesize_vovovov_expression2\n         {\n            typedef typename vovovov_t::type2 node_type;\n            typedef typename vovovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 ((v1 o1 v2) o2 v3)\n               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vovov->t0();\n               const Type& v2 = vovov->t1();\n               const Type& v3 = vovov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovov->f0();\n               binary_functor_t f2 = vovov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 ((v1 o1 v2) o2 v3)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vovovoc_expression2\n         {\n            typedef typename vovovoc_t::type2 node_type;\n            typedef typename vovovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 ((v1 o1 v2) o2 c)\n               typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;\n\n               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vovoc->t0();\n               const Type& v2 = vovoc->t1();\n               const Type   c = vovoc->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovoc->f0();\n               binary_functor_t f2 = vovoc->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 ((v1 o1 v2) o2 c)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vovocov_expression2\n         {\n            typedef typename vovocov_t::type2 node_type;\n            typedef typename vovocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 ((v1 o1 c) o2 v2)\n               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type& v1 = vocov->t0();\n               const Type   c = vocov->t1();\n               const Type& v2 = vocov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vocov->f0();\n               binary_functor_t f2 = vocov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 ((v1 o1 c) o2 v2)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vocovov_expression2\n         {\n            typedef typename vocovov_t::type2 node_type;\n            typedef typename vocovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 ((c o1 v1) o2 v2)\n               typedef typename synthesize_covov_expression0::node_type lcl_covov_t;\n\n               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type   c = covov->t0();\n               const Type& v1 = covov->t1();\n               const Type& v2 = covov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(covov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(covov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = covov->f0();\n               binary_functor_t f2 = covov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 ((c o1 v1) o2 v2)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_covovov_expression2\n         {\n            typedef typename covovov_t::type2 node_type;\n            typedef typename covovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // c o0 ((v1 o1 v2) o2 v3)\n               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);\n               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vovov->t0();\n               const Type& v1 = vovov->t1();\n               const Type& v2 = vovov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovov->f0();\n               binary_functor_t f2 = vovov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"c o0 ((v1 o1 v2) o2 v3)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n        };\n\n         struct synthesize_covocov_expression2\n         {\n            typedef typename covocov_t::type2 node_type;\n            typedef typename covocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // c0 o0 ((v0 o1 c1) o2 v1)\n               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);\n               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vocov->t0();\n               const Type  c1 = vocov->t1();\n               const Type& v1 = vocov->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vocov->f0();\n               binary_functor_t f2 = vocov->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"c0 o0 ((v0 o1 c1) o2 v1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vocovoc_expression2\n         {\n            typedef typename vocovoc_t::type2 node_type;\n            typedef typename vocovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // v0 o0 ((c0 o1 v1) o2 c1)\n               typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;\n\n               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);\n               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();\n               const Type  c0 = covoc->t0();\n               const Type& v1 = covoc->t1();\n               const Type  c1 = covoc->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(covoc->f0());\n               const details::operator_type o2 = expr_gen.get_operator(covoc->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = covoc->f0();\n               binary_functor_t f2 = covoc->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"v0 o0 ((c0 o1 v1) o2 c1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_covovoc_expression2\n         {\n            typedef typename covovoc_t::type2 node_type;\n            typedef typename covovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // c0 o0 ((v0 o1 v1) o2 c1)\n               typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;\n\n               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);\n               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();\n               const Type& v0 = vovoc->t0();\n               const Type& v1 = vovoc->t1();\n               const Type  c1 = vovoc->t2();\n               const details::operator_type o0 = operation;\n               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());\n               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());\n\n               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);\n               binary_functor_t f1 = vovoc->f0();\n               binary_functor_t f2 = vovoc->f1();\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o0,f0))\n                  return error_node();\n\n               exprtk_debug((\"c0 o0 ((v0 o1 v1) o2 c1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"t\" << expr_gen.to_str(o0) << \"((t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t)\");\n            }\n         };\n\n         struct synthesize_vococov_expression2\n         {\n            typedef typename vococov_t::type2 node_type;\n            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])\n            {\n               // v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n               exprtk_debug((\"v0 o0 ((c0 o1 c1) o2 v1) - Not possible\\n\"));\n               return error_node();\n            }\n\n            static inline std::string id(expression_generator<Type>&,\n                                         const details::operator_type, const details::operator_type, const details::operator_type)\n            {\n               return \"INVALID\";\n            }\n         };\n\n         struct synthesize_vovovov_expression3\n         {\n            typedef typename vovovov_t::type3 node_type;\n            typedef typename vovovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 v1) o1 v2) o2 v3\n               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);\n               const Type& v0 = vovov->t0();\n               const Type& v1 = vovov->t1();\n               const Type& v2 = vovov->t2();\n               const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vovov->f0();\n               binary_functor_t f1 = vovov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 v1) o1 v2) o2 v3\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vovovoc_expression3\n         {\n            typedef typename vovovoc_t::type3 node_type;\n            typedef typename vovovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 v1) o1 v2) o2 c\n               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);\n               const Type& v0 = vovov->t0();\n               const Type& v1 = vovov->t1();\n               const Type& v2 = vovov->t2();\n               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vovov->f0();\n               binary_functor_t f1 = vovov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 v1) o1 v2) o2 c\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vovocov_expression3\n         {\n            typedef typename vovocov_t::type3 node_type;\n            typedef typename vovocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 v1) o1 c) o2 v2\n               typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;\n\n               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);\n               const Type& v0 = vovoc->t0();\n               const Type& v1 = vovoc->t1();\n               const Type   c = vovoc->t2();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vovoc->f0();\n               binary_functor_t f1 = vovoc->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 v1) o1 c) o2 v2\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vocovov_expression3\n         {\n            typedef typename vocovov_t::type3 node_type;\n            typedef typename vocovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 c) o1 v1) o2 v2\n               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);\n               const Type& v0 = vocov->t0();\n               const Type   c = vocov->t1();\n               const Type& v1 = vocov->t2();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vocov->f0();\n               binary_functor_t f1 = vocov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 c) o1 v1) o2 v2\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_covovov_expression3\n         {\n            typedef typename covovov_t::type3 node_type;\n            typedef typename covovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((c o0 v0) o1 v1) o2 v2\n               typedef typename synthesize_covov_expression0::node_type lcl_covov_t;\n\n               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);\n               const Type   c = covov->t0();\n               const Type& v0 = covov->t1();\n               const Type& v1 = covov->t2();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(covov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(covov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = covov->f0();\n               binary_functor_t f1 = covov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((c o0 v0) o1 v1) o2 v2\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_covocov_expression3\n         {\n            typedef typename covocov_t::type3 node_type;\n            typedef typename covocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((c0 o0 v0) o1 c1) o2 v1\n               typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;\n\n               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);\n               const Type  c0 = covoc->t0();\n               const Type& v0 = covoc->t1();\n               const Type  c1 = covoc->t2();\n               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(covoc->f0());\n               const details::operator_type o1 = expr_gen.get_operator(covoc->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = covoc->f0();\n               binary_functor_t f1 = covoc->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((c0 o0 v0) o1 c1) o2 v1\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vocovoc_expression3\n         {\n            typedef typename vocovoc_t::type3 node_type;\n            typedef typename vocovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 c0) o1 v1) o2 c1\n               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);\n               const Type& v0 = vocov->t0();\n               const Type  c0 = vocov->t1();\n               const Type& v1 = vocov->t2();\n               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vocov->f0();\n               binary_functor_t f1 = vocov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 c0) o1 v1) o2 c1\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_covovoc_expression3\n         {\n            typedef typename covovoc_t::type3 node_type;\n            typedef typename covovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((c0 o0 v0) o1 v1) o2 c1\n               typedef typename synthesize_covov_expression0::node_type lcl_covov_t;\n\n               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);\n               const Type  c0 = covov->t0();\n               const Type& v0 = covov->t1();\n               const Type& v1 = covov->t2();\n               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = expr_gen.get_operator(covov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(covov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = covov->f0();\n               binary_functor_t f1 = covov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((c0 o0 v0) o1 v1) o2 c1\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vococov_expression3\n         {\n            typedef typename vococov_t::type3 node_type;\n            typedef typename vococov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 c0) o1 c1) o2 v1\n               typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;\n\n               const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);\n               const Type& v0 = vococ->t0();\n               const Type  c0 = vococ->t1();\n               const Type  c1 = vococ->t2();\n               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vococ->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vococ->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vococ->f0();\n               binary_functor_t f1 = vococ->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 c0) o1 c1) o2 v1\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"((t\" << expr_gen.to_str(o0) << \"t)\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vovovov_expression4\n         {\n            typedef typename vovovov_t::type4 node_type;\n            typedef typename vovovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // (v0 o0 (v1 o1 v2)) o2 v3\n               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);\n               const Type& v0 = vovov->t0();\n               const Type& v1 = vovov->t1();\n               const Type& v2 = vovov->t2();\n               const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vovov->f0();\n               binary_functor_t f1 = vovov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"(v0 o0 (v1 o1 v2)) o2 v3\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vovovoc_expression4\n         {\n            typedef typename vovovoc_t::type4 node_type;\n            typedef typename vovovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 (v1 o1 v2)) o2 c)\n               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;\n\n               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);\n               const Type& v0 = vovov->t0();\n               const Type& v1 = vovov->t1();\n               const Type& v2 = vovov->t2();\n               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vovov->f0();\n               binary_functor_t f1 = vovov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 (v1 o1 v2)) o2 c)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vovocov_expression4\n         {\n            typedef typename vovocov_t::type4 node_type;\n            typedef typename vovocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 (v1 o1 c)) o2 v1)\n               typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;\n\n               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);\n               const Type& v0 = vovoc->t0();\n               const Type& v1 = vovoc->t1();\n               const Type   c = vovoc->t2();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vovoc->f0();\n               binary_functor_t f1 = vovoc->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 (v1 o1 c)) o2 v1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vocovov_expression4\n         {\n            typedef typename vocovov_t::type4 node_type;\n            typedef typename vocovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 (c o1 v1)) o2 v2)\n               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);\n               const Type& v0 = vocov->t0();\n               const Type   c = vocov->t1();\n               const Type& v1 = vocov->t2();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vocov->f0();\n               binary_functor_t f1 = vocov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 (c o1 v1)) o2 v2)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_covovov_expression4\n         {\n            typedef typename covovov_t::type4 node_type;\n            typedef typename covovov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((c o0 (v0 o1 v1)) o2 v2)\n               typedef typename synthesize_covov_expression1::node_type lcl_covov_t;\n\n               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);\n               const Type   c = covov->t0();\n               const Type& v0 = covov->t1();\n               const Type& v1 = covov->t2();\n               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(covov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(covov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = covov->f0();\n               binary_functor_t f1 = covov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((c o0 (v0 o1 v1)) o2 v2)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_covocov_expression4\n         {\n            typedef typename covocov_t::type4 node_type;\n            typedef typename covocov_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((c0 o0 (v0 o1 c1)) o2 v1)\n               typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;\n\n               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);\n               const Type  c0 = covoc->t0();\n               const Type& v0 = covoc->t1();\n               const Type  c1 = covoc->t2();\n               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();\n               const details::operator_type o0 = expr_gen.get_operator(covoc->f0());\n               const details::operator_type o1 = expr_gen.get_operator(covoc->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = covoc->f0();\n               binary_functor_t f1 = covoc->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((c0 o0 (v0 o1 c1)) o2 v1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vocovoc_expression4\n         {\n            typedef typename vocovoc_t::type4 node_type;\n            typedef typename vocovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((v0 o0 (c0 o1 v1)) o2 c1)\n               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;\n\n               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);\n               const Type& v0 = vocov->t0();\n               const Type  c0 = vocov->t1();\n               const Type& v1 = vocov->t2();\n               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = vocov->f0();\n               binary_functor_t f1 = vocov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((v0 o0 (c0 o1 v1)) o2 c1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_covovoc_expression4\n         {\n            typedef typename covovoc_t::type4 node_type;\n            typedef typename covovoc_t::sf4_type sf4_type;\n            typedef typename node_type::T0 T0;\n            typedef typename node_type::T1 T1;\n            typedef typename node_type::T2 T2;\n            typedef typename node_type::T3 T3;\n\n            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,\n                                                      const details::operator_type& operation,\n                                                      expression_node_ptr (&branch)[2])\n            {\n               // ((c0 o0 (v0 o1 v1)) o2 c1)\n               typedef typename synthesize_covov_expression1::node_type lcl_covov_t;\n\n               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);\n               const Type  c0 = covov->t0();\n               const Type& v0 = covov->t1();\n               const Type& v1 = covov->t2();\n               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();\n               const details::operator_type o0 = expr_gen.get_operator(covov->f0());\n               const details::operator_type o1 = expr_gen.get_operator(covov->f1());\n               const details::operator_type o2 = operation;\n\n               binary_functor_t f0 = covov->f0();\n               binary_functor_t f1 = covov->f1();\n               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);\n\n               details::free_node(*(expr_gen.node_allocator_),branch[0]);\n               details::free_node(*(expr_gen.node_allocator_),branch[1]);\n\n               expression_node_ptr result = error_node();\n\n               const bool synthesis_result =\n                  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>\n                     (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);\n\n               if (synthesis_result)\n                  return result;\n               else if (!expr_gen.valid_operator(o2,f2))\n                  return error_node();\n\n               exprtk_debug((\"((c0 o0 (v0 o1 v1)) o2 c1)\\n\"));\n\n               return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);\n            }\n\n            static inline std::string id(expression_generator<Type>& expr_gen,\n                                         const details::operator_type o0,\n                                         const details::operator_type o1,\n                                         const details::operator_type o2)\n            {\n               return (details::build_string() << \"(t\" << expr_gen.to_str(o0) << \"(t\" << expr_gen.to_str(o1) << \"t)\" << expr_gen.to_str(o2) << \"t\");\n            }\n         };\n\n         struct synthesize_vococov_expression4\n         {\n            typedef typename vococov_t::type4 node_type;\n            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])\n            {\n               // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n               exprtk_debug((\"((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\\n\"));\n               return error_node();\n            }\n\n            static inline std::string id(expression_generator<Type>&,\n                                         const details::operator_type, const details::operator_type, const details::operator_type)\n            {\n               return \"INVALID\";\n            }\n         };\n         #endif\n\n         inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            // Definition: uv o uv\n            details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();\n            details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();\n            const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();\n            const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();\n            unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);\n            unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);\n            binary_functor_t f = reinterpret_cast<binary_functor_t>(0);\n\n            if (!valid_operator(o0,u0))\n               return error_node();\n            else if (!valid_operator(o1,u1))\n               return error_node();\n            else if (!valid_operator(operation,f))\n               return error_node();\n\n            expression_node_ptr result = error_node();\n\n            if (\n                 (details::e_neg == o0) &&\n                 (details::e_neg == o1)\n               )\n            {\n               switch (operation)\n               {\n                  // (-v0 + -v1) --> -(v0 + v1)\n                  case details::e_add : result = (*this)(details::e_neg,\n                                                    node_allocator_->\n                                                       allocate_rr<typename details::\n                                                          vov_node<Type,details::add_op<Type> > >(v0, v1));\n                                        exprtk_debug((\"(-v0 + -v1) --> -(v0 + v1)\\n\"));\n                                        break;\n\n                  // (-v0 - -v1) --> (v1 - v0)\n                  case details::e_sub : result = node_allocator_->\n                                                    allocate_rr<typename details::\n                                                       vov_node<Type,details::sub_op<Type> > >(v1, v0);\n                                        exprtk_debug((\"(-v0 - -v1) --> (v1 - v0)\\n\"));\n                                        break;\n\n                  // (-v0 * -v1) --> (v0 * v1)\n                  case details::e_mul : result = node_allocator_->\n                                                    allocate_rr<typename details::\n                                                       vov_node<Type,details::mul_op<Type> > >(v0, v1);\n                                        exprtk_debug((\"(-v0 * -v1) --> (v0 * v1)\\n\"));\n                                        break;\n\n                  // (-v0 / -v1) --> (v0 / v1)\n                  case details::e_div : result = node_allocator_->\n                                                    allocate_rr<typename details::\n                                                       vov_node<Type,details::div_op<Type> > >(v0, v1);\n                                        exprtk_debug((\"(-v0 / -v1) --> (v0 / v1)\\n\"));\n                                        break;\n\n                  default             : break;\n               }\n            }\n\n            if (0 == result)\n            {\n               result = node_allocator_->\n                            allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);\n            }\n\n            details::free_all_nodes(*node_allocator_,branch);\n            return result;\n         }\n\n         #undef basic_opr_switch_statements\n         #undef extended_opr_switch_statements\n         #undef unary_opr_switch_statements\n\n         #ifndef exprtk_disable_string_capabilities\n\n         #define string_opr_switch_statements          \\\n         case_stmt(details::  e_lt ,details::   lt_op) \\\n         case_stmt(details:: e_lte ,details::  lte_op) \\\n         case_stmt(details::  e_gt ,details::   gt_op) \\\n         case_stmt(details:: e_gte ,details::  gte_op) \\\n         case_stmt(details::  e_eq ,details::   eq_op) \\\n         case_stmt(details::  e_ne ,details::   ne_op) \\\n         case_stmt(details::e_in   ,details::   in_op) \\\n         case_stmt(details::e_like ,details:: like_op) \\\n         case_stmt(details::e_ilike,details::ilike_op) \\\n\n         template <typename T0, typename T1>\n         inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,\n                                                                        T0 s0, T1 s1,\n                                                                        range_t rp0)\n         {\n            switch (opr)\n            {\n               #define case_stmt(op0,op1)                                                                       \\\n               case op0 : return node_allocator_->                                                              \\\n                             allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \\\n                                (s0, s1, rp0);                                                                  \\\n\n               string_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         template <typename T0, typename T1>\n         inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,\n                                                                        T0 s0, T1 s1,\n                                                                        range_t rp1)\n         {\n            switch (opr)\n            {\n               #define case_stmt(op0,op1)                                                                       \\\n               case op0 : return node_allocator_->                                                              \\\n                             allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \\\n                                (s0, s1, rp1);                                                                  \\\n\n               string_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         template <typename T0, typename T1>\n         inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,\n                                                                         T0 s0, T1 s1,\n                                                                         range_t rp0, range_t rp1)\n         {\n            switch (opr)\n            {\n               #define case_stmt(op0,op1)                                                                         \\\n               case op0 : return node_allocator_->                                                                \\\n                             allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \\\n                                (s0, s1, rp0, rp1);                                                               \\\n\n               string_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         template <typename T0, typename T1>\n         inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)\n         {\n            switch (opr)\n            {\n               #define case_stmt(op0,op1)                                                                  \\\n               case op0 : return node_allocator_->                                                         \\\n                             allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \\\n\n               string_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n\n         inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();\n            std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();\n\n            return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);\n         }\n\n         inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();\n            std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();\n            range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();\n\n            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();\n\n            free_node(*node_allocator_,branch[0]);\n\n            return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);\n         }\n\n         inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();\n            std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();\n            range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();\n\n            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);\n         }\n\n         inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();\n            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();\n            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();\n\n            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);\n         }\n\n         inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();\n            std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();\n            range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();\n            range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();\n\n            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();\n            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            details::free_node(*node_allocator_,branch[0]);\n            details::free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);\n         }\n\n         inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();\n            std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();\n\n            details::free_node(*node_allocator_,branch[1]);\n\n            return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);\n         }\n\n         inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();\n            std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();\n\n            details::free_node(*node_allocator_,branch[0]);\n\n            return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);\n         }\n\n         inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();\n            std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();\n            range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();\n\n            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            details::free_node(*node_allocator_,branch[0]);\n            details::free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);\n         }\n\n         inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();\n            std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();\n            range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();\n\n            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();\n\n            details::free_node(*node_allocator_,branch[0]);\n            details::free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);\n         }\n\n         inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();\n            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();\n            range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();\n            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();\n\n            static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();\n            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            details::free_node(*node_allocator_,branch[0]);\n            details::free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);\n         }\n\n         inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();\n            const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();\n\n            expression_node_ptr result = error_node();\n\n            if (details::e_add == opr)\n               result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);\n            else if (details::e_in == opr)\n               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op   <Type>::process(s0,s1));\n            else if (details::e_like == opr)\n               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));\n            else if (details::e_ilike == opr)\n               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));\n            else\n            {\n               expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);\n\n               const Type v = temp->value();\n\n               details::free_node(*node_allocator_,temp);\n\n               result = node_allocator_->allocate<literal_node_t>(v);\n            }\n\n            details::free_all_nodes(*node_allocator_,branch);\n\n            return result;\n         }\n\n         inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();\n                  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();\n            range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();\n\n            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            free_node(*node_allocator_,branch[0]);\n            free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);\n         }\n\n         inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();\n            std::string&  s1 = static_cast<details::stringvar_node<Type>*>         (branch[1])->ref  ();\n            range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();\n\n            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();\n\n            free_node(*node_allocator_,branch[0]);\n\n            return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);\n         }\n\n         inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();\n                  std::string& s1 = static_cast<details::string_range_node<Type>*>      (branch[1])->ref  ();\n            range_t           rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();\n            range_t           rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();\n\n            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();\n            static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();\n\n            free_node(*node_allocator_,branch[0]);\n            free_node(*node_allocator_,branch[1]);\n\n            return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);\n         }\n\n         inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string       s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();\n            const std::string s1 = static_cast<details::string_literal_node<Type>*>    (branch[1])->str  ();\n            range_t          rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();\n\n            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();\n\n            details::free_all_nodes(*node_allocator_,branch);\n\n            return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);\n         }\n\n         inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();\n            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();\n            range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();\n            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();\n\n            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();\n            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();\n\n            details::free_all_nodes(*node_allocator_,branch);\n\n            return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);\n         }\n\n         inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            switch (opr)\n            {\n               #define case_stmt(op0,op1)                                                       \\\n               case op0 : return node_allocator_->                                              \\\n                             allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \\\n                                (opr, branch[0], branch[1]);                                    \\\n\n               string_opr_switch_statements\n               #undef case_stmt\n               default : return error_node();\n            }\n         }\n         #endif\n\n         #ifndef exprtk_disable_string_capabilities\n         inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])\n         {\n            if ((0 == branch[0]) || (0 == branch[1]))\n            {\n               details::free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n\n            const bool b0_is_s   = details::is_string_node            (branch[0]);\n            const bool b0_is_cs  = details::is_const_string_node      (branch[0]);\n            const bool b0_is_sr  = details::is_string_range_node      (branch[0]);\n            const bool b0_is_csr = details::is_const_string_range_node(branch[0]);\n\n            const bool b1_is_s   = details::is_string_node            (branch[1]);\n            const bool b1_is_cs  = details::is_const_string_node      (branch[1]);\n            const bool b1_is_sr  = details::is_string_range_node      (branch[1]);\n            const bool b1_is_csr = details::is_const_string_range_node(branch[1]);\n\n            const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||\n                                   details::is_genricstring_range_node(branch[0]) ||\n                                   details::is_string_concat_node     (branch[0]) ||\n                                   details::is_string_function_node   (branch[0]) ||\n                                   details::is_string_condition_node  (branch[0]) ||\n                                   details::is_string_ccondition_node (branch[0]) ||\n                                   details::is_string_vararg_node     (branch[0]) ;\n\n            const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||\n                                   details::is_genricstring_range_node(branch[1]) ||\n                                   details::is_string_concat_node     (branch[1]) ||\n                                   details::is_string_function_node   (branch[1]) ||\n                                   details::is_string_condition_node  (branch[1]) ||\n                                   details::is_string_ccondition_node (branch[1]) ||\n                                   details::is_string_vararg_node     (branch[1]) ;\n\n            if (details::e_add == opr)\n            {\n               if (!b0_is_cs || !b1_is_cs)\n               {\n                  return synthesize_expression<string_concat_node_t,2>(opr,branch);\n               }\n            }\n\n            if (b0_is_gen || b1_is_gen)\n            {\n               return synthesize_strogen_expression(opr,branch);\n            }\n            else if (b0_is_s)\n            {\n                    if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);\n               else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);\n               else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);\n               else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);\n            }\n            else if (b0_is_cs)\n            {\n                    if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);\n               else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);\n               else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);\n               else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);\n            }\n            else if (b0_is_sr)\n            {\n                    if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);\n               else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);\n               else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);\n               else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);\n            }\n            else if (b0_is_csr)\n            {\n                    if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);\n               else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);\n               else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);\n               else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);\n            }\n\n            return error_node();\n         }\n         #else\n         inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])\n         {\n            details::free_all_nodes(*node_allocator_,branch);\n            return error_node();\n         }\n         #endif\n\n         #ifndef exprtk_disable_string_capabilities\n         inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])\n         {\n            if (details::e_inrange != opr)\n               return error_node();\n            else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))\n            {\n               details::free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n            else if (\n                      details::is_const_string_node(branch[0]) &&\n                      details::is_const_string_node(branch[1]) &&\n                      details::is_const_string_node(branch[2])\n                    )\n            {\n               const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();\n               const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();\n               const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();\n\n               const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));\n\n               details::free_all_nodes(*node_allocator_,branch);\n\n               return node_allocator_->allocate_c<details::literal_node<Type> >(v);\n            }\n            else if (\n                      details::is_string_node(branch[0]) &&\n                      details::is_string_node(branch[1]) &&\n                      details::is_string_node(branch[2])\n                    )\n            {\n               std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();\n               std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();\n               std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();\n\n               typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;\n\n               return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);\n            }\n            else if (\n                      details::is_const_string_node(branch[0]) &&\n                            details::is_string_node(branch[1]) &&\n                      details::is_const_string_node(branch[2])\n                    )\n            {\n               std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();\n               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();\n               std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();\n\n               typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;\n\n               details::free_node(*node_allocator_,branch[0]);\n               details::free_node(*node_allocator_,branch[2]);\n\n               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);\n            }\n            else if (\n                            details::is_string_node(branch[0]) &&\n                      details::is_const_string_node(branch[1]) &&\n                            details::is_string_node(branch[2])\n                    )\n            {\n               std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();\n               std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();\n               std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();\n\n               typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;\n\n               details::free_node(*node_allocator_,branch[1]);\n\n               return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);\n            }\n            else if (\n                      details::is_string_node(branch[0]) &&\n                      details::is_string_node(branch[1]) &&\n                      details::is_const_string_node(branch[2])\n                    )\n            {\n               std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();\n               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();\n               std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();\n\n               typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;\n\n               details::free_node(*node_allocator_,branch[2]);\n\n               return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);\n            }\n            else if (\n                      details::is_const_string_node(branch[0]) &&\n                      details::      is_string_node(branch[1]) &&\n                      details::      is_string_node(branch[2])\n                    )\n            {\n               std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();\n               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();\n               std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();\n\n               typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;\n\n               details::free_node(*node_allocator_,branch[0]);\n\n               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);\n            }\n            else\n               return error_node();\n         }\n         #else\n         inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])\n         {\n            details::free_all_nodes(*node_allocator_,branch);\n            return error_node();\n         }\n         #endif\n\n         inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])\n         {\n            /*\n             Note: The following are the type promotion rules\n             that relate to operations that include 'null':\n             0. null ==/!=     null --> true false\n             1. null operation null --> null\n             2. x    ==/!=     null --> true/false\n             3. null ==/!=     x    --> true/false\n             4. x   operation  null --> x\n             5. null operation x    --> x\n            */\n\n            typedef typename details::null_eq_node<T> nulleq_node_t;\n\n            bool b0_null = details::is_null_node(branch[0]);\n            bool b1_null = details::is_null_node(branch[1]);\n\n            if (b0_null && b1_null)\n            {\n               expression_node_ptr result = error_node();\n\n               if (details::e_eq == operation)\n                  result = node_allocator_->allocate_c<literal_node_t>(T(1));\n               else if (details::e_ne == operation)\n                  result = node_allocator_->allocate_c<literal_node_t>(T(0));\n\n               if (result)\n               {\n                  details::free_node(*node_allocator_,branch[0]);\n                  details::free_node(*node_allocator_,branch[1]);\n\n                  return result;\n               }\n\n               details::free_node(*node_allocator_,branch[1]);\n\n               return branch[0];\n            }\n            else if (details::e_eq == operation)\n            {\n               expression_node_ptr result = node_allocator_->\n                                                allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);\n\n               details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);\n\n               return result;\n            }\n            else if (details::e_ne == operation)\n            {\n               expression_node_ptr result = node_allocator_->\n                                                allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);\n\n               details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);\n\n               return result;\n            }\n            else if (b0_null)\n            {\n               details::free_node(*node_allocator_,branch[0]);\n               branch[0] = branch[1];\n               branch[1] = error_node();\n            }\n            else if (b1_null)\n            {\n               details::free_node(*node_allocator_,branch[1]);\n               branch[1] = error_node();\n            }\n\n            if (\n                 (details::e_add == operation) || (details::e_sub == operation) ||\n                 (details::e_mul == operation) || (details::e_div == operation) ||\n                 (details::e_mod == operation) || (details::e_pow == operation)\n               )\n            {\n               return branch[0];\n            }\n            else if (\n                      (details::e_lt    == operation) || (details::e_lte  == operation) ||\n                      (details::e_gt    == operation) || (details::e_gte  == operation) ||\n                      (details::e_and   == operation) || (details::e_nand == operation) ||\n                      (details::e_or    == operation) || (details::e_nor  == operation) ||\n                      (details::e_xor   == operation) || (details::e_xnor == operation) ||\n                      (details::e_in    == operation) || (details::e_like == operation) ||\n                      (details::e_ilike == operation)\n                    )\n            {\n               return node_allocator_->allocate_c<literal_node_t>(T(0));\n            }\n\n            details::free_node(*node_allocator_,branch[0]);\n\n            return node_allocator_->allocate<details::null_node<Type> >();\n         }\n\n         template <typename NodeType, std::size_t N>\n         inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])\n         {\n            if (\n                 (details::e_in    == operation) ||\n                 (details::e_like  == operation) ||\n                 (details::e_ilike == operation)\n               )\n            {\n               free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n            else if (!details::all_nodes_valid<N>(branch))\n            {\n               free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n            else if ((details::e_default != operation))\n            {\n               // Attempt simple constant folding optimisation.\n               expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);\n\n               if (is_constant_foldable<N>(branch))\n               {\n                  Type v = expression_point->value();\n                  details::free_node(*node_allocator_,expression_point);\n\n                  return node_allocator_->allocate<literal_node_t>(v);\n               }\n               else\n                  return expression_point;\n            }\n            else\n               return error_node();\n         }\n\n         template <typename NodeType, std::size_t N>\n         inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])\n         {\n            if (!details::all_nodes_valid<N>(branch))\n            {\n               free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n\n            typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;\n\n            // Attempt simple constant folding optimisation.\n\n            expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);\n            function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);\n\n            if (0 == func_node_ptr)\n            {\n               free_all_nodes(*node_allocator_,branch);\n\n               return error_node();\n            }\n            else\n               func_node_ptr->init_branches(branch);\n\n            if (is_constant_foldable<N>(branch) && !f->has_side_effects())\n            {\n               Type v = expression_point->value();\n               details::free_node(*node_allocator_,expression_point);\n\n               return node_allocator_->allocate<literal_node_t>(v);\n            }\n\n            parser_->state_.activate_side_effect(\"synthesize_expression(function<NT,N>)\");\n\n            return expression_point;\n         }\n\n         bool                     strength_reduction_enabled_;\n         details::node_allocator* node_allocator_;\n         synthesize_map_t         synthesize_map_;\n         unary_op_map_t*          unary_op_map_;\n         binary_op_map_t*         binary_op_map_;\n         inv_binary_op_map_t*     inv_binary_op_map_;\n         sf3_map_t*               sf3_map_;\n         sf4_map_t*               sf4_map_;\n         parser_t*                parser_;\n      };\n\n      inline void set_error(const parser_error::type& error_type)\n      {\n         error_list_.push_back(error_type);\n      }\n\n      inline void remove_last_error()\n      {\n         if (!error_list_.empty())\n         {\n            error_list_.pop_back();\n         }\n      }\n\n      inline void set_synthesis_error(const std::string& synthesis_error_message)\n      {\n         if (synthesis_error_.empty())\n         {\n            synthesis_error_ = synthesis_error_message;\n         }\n      }\n\n      inline void register_local_vars(expression<T>& e)\n      {\n         for (std::size_t i = 0; i < sem_.size(); ++i)\n         {\n            scope_element& se = sem_.get_element(i);\n\n            if (\n                 (scope_element::e_variable == se.type) ||\n                 (scope_element::e_vecelem  == se.type)\n               )\n            {\n               if (se.var_node)\n               {\n                  e.register_local_var(se.var_node);\n               }\n\n               if (se.data)\n               {\n                  e.register_local_data(se.data, 1, 0);\n               }\n            }\n            else if (scope_element::e_vector == se.type)\n            {\n               if (se.vec_node)\n               {\n                  e.register_local_var(se.vec_node);\n               }\n\n               if (se.data)\n               {\n                  e.register_local_data(se.data, se.size, 1);\n               }\n            }\n            #ifndef exprtk_disable_string_capabilities\n            else if (scope_element::e_string == se.type)\n            {\n               if (se.str_node)\n               {\n                  e.register_local_var(se.str_node);\n               }\n\n               if (se.data)\n               {\n                  e.register_local_data(se.data, se.size, 2);\n               }\n            }\n            #endif\n\n            se.var_node  = 0;\n            se.vec_node  = 0;\n            #ifndef exprtk_disable_string_capabilities\n            se.str_node  = 0;\n            #endif\n            se.data      = 0;\n            se.ref_count = 0;\n            se.active    = false;\n         }\n      }\n\n      inline void register_return_results(expression<T>& e)\n      {\n         e.register_return_results(results_context_);\n         results_context_ = 0;\n      }\n\n      inline void load_unary_operations_map(unary_op_map_t& m)\n      {\n         #define register_unary_op(Op,UnaryFunctor)             \\\n         m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \\\n\n         register_unary_op(details::  e_abs, details::  abs_op)\n         register_unary_op(details:: e_acos, details:: acos_op)\n         register_unary_op(details::e_acosh, details::acosh_op)\n         register_unary_op(details:: e_asin, details:: asin_op)\n         register_unary_op(details::e_asinh, details::asinh_op)\n         register_unary_op(details::e_atanh, details::atanh_op)\n         register_unary_op(details:: e_ceil, details:: ceil_op)\n         register_unary_op(details::  e_cos, details::  cos_op)\n         register_unary_op(details:: e_cosh, details:: cosh_op)\n         register_unary_op(details::  e_exp, details::  exp_op)\n         register_unary_op(details::e_expm1, details::expm1_op)\n         register_unary_op(details::e_floor, details::floor_op)\n         register_unary_op(details::  e_log, details::  log_op)\n         register_unary_op(details::e_log10, details::log10_op)\n         register_unary_op(details:: e_log2, details:: log2_op)\n         register_unary_op(details::e_log1p, details::log1p_op)\n         register_unary_op(details::  e_neg, details::  neg_op)\n         register_unary_op(details::  e_pos, details::  pos_op)\n         register_unary_op(details::e_round, details::round_op)\n         register_unary_op(details::  e_sin, details::  sin_op)\n         register_unary_op(details:: e_sinc, details:: sinc_op)\n         register_unary_op(details:: e_sinh, details:: sinh_op)\n         register_unary_op(details:: e_sqrt, details:: sqrt_op)\n         register_unary_op(details::  e_tan, details::  tan_op)\n         register_unary_op(details:: e_tanh, details:: tanh_op)\n         register_unary_op(details::  e_cot, details::  cot_op)\n         register_unary_op(details::  e_sec, details::  sec_op)\n         register_unary_op(details::  e_csc, details::  csc_op)\n         register_unary_op(details::  e_r2d, details::  r2d_op)\n         register_unary_op(details::  e_d2r, details::  d2r_op)\n         register_unary_op(details::  e_d2g, details::  d2g_op)\n         register_unary_op(details::  e_g2d, details::  g2d_op)\n         register_unary_op(details:: e_notl, details:: notl_op)\n         register_unary_op(details::  e_sgn, details::  sgn_op)\n         register_unary_op(details::  e_erf, details::  erf_op)\n         register_unary_op(details:: e_erfc, details:: erfc_op)\n         register_unary_op(details:: e_ncdf, details:: ncdf_op)\n         register_unary_op(details:: e_frac, details:: frac_op)\n         register_unary_op(details::e_trunc, details::trunc_op)\n         #undef register_unary_op\n      }\n\n      inline void load_binary_operations_map(binary_op_map_t& m)\n      {\n         typedef typename binary_op_map_t::value_type value_type;\n\n         #define register_binary_op(Op,BinaryFunctor)        \\\n         m.insert(value_type(Op,BinaryFunctor<T>::process)); \\\n\n         register_binary_op(details:: e_add, details:: add_op)\n         register_binary_op(details:: e_sub, details:: sub_op)\n         register_binary_op(details:: e_mul, details:: mul_op)\n         register_binary_op(details:: e_div, details:: div_op)\n         register_binary_op(details:: e_mod, details:: mod_op)\n         register_binary_op(details:: e_pow, details:: pow_op)\n         register_binary_op(details::  e_lt, details::  lt_op)\n         register_binary_op(details:: e_lte, details:: lte_op)\n         register_binary_op(details::  e_gt, details::  gt_op)\n         register_binary_op(details:: e_gte, details:: gte_op)\n         register_binary_op(details::  e_eq, details::  eq_op)\n         register_binary_op(details::  e_ne, details::  ne_op)\n         register_binary_op(details:: e_and, details:: and_op)\n         register_binary_op(details::e_nand, details::nand_op)\n         register_binary_op(details::  e_or, details::  or_op)\n         register_binary_op(details:: e_nor, details:: nor_op)\n         register_binary_op(details:: e_xor, details:: xor_op)\n         register_binary_op(details::e_xnor, details::xnor_op)\n         #undef register_binary_op\n      }\n\n      inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)\n      {\n         typedef typename inv_binary_op_map_t::value_type value_type;\n\n         #define register_binary_op(Op,BinaryFunctor)        \\\n         m.insert(value_type(BinaryFunctor<T>::process,Op)); \\\n\n         register_binary_op(details:: e_add, details:: add_op)\n         register_binary_op(details:: e_sub, details:: sub_op)\n         register_binary_op(details:: e_mul, details:: mul_op)\n         register_binary_op(details:: e_div, details:: div_op)\n         register_binary_op(details:: e_mod, details:: mod_op)\n         register_binary_op(details:: e_pow, details:: pow_op)\n         register_binary_op(details::  e_lt, details::  lt_op)\n         register_binary_op(details:: e_lte, details:: lte_op)\n         register_binary_op(details::  e_gt, details::  gt_op)\n         register_binary_op(details:: e_gte, details:: gte_op)\n         register_binary_op(details::  e_eq, details::  eq_op)\n         register_binary_op(details::  e_ne, details::  ne_op)\n         register_binary_op(details:: e_and, details:: and_op)\n         register_binary_op(details::e_nand, details::nand_op)\n         register_binary_op(details::  e_or, details::  or_op)\n         register_binary_op(details:: e_nor, details:: nor_op)\n         register_binary_op(details:: e_xor, details:: xor_op)\n         register_binary_op(details::e_xnor, details::xnor_op)\n         #undef register_binary_op\n      }\n\n      inline void load_sf3_map(sf3_map_t& sf3_map)\n      {\n         typedef std::pair<trinary_functor_t,details::operator_type> pair_t;\n\n         #define register_sf3(Op)                                                                             \\\n         sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \\\n\n         register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)\n         register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)\n         register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)\n         register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)\n         register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)\n         register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)\n         register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)\n         register_sf3(28) register_sf3(29) register_sf3(30)\n         #undef register_sf3\n\n         #define register_sf3_extid(Id, Op)                                        \\\n         sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \\\n\n         register_sf3_extid(\"(t-t)-t\",23)  // (t-t)-t --> t-(t+t)\n         #undef register_sf3_extid\n      }\n\n      inline void load_sf4_map(sf4_map_t& sf4_map)\n      {\n         typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;\n\n         #define register_sf4(Op)                                                                             \\\n         sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \\\n\n         register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)\n         register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)\n         register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)\n         register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)\n         register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)\n         register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)\n         register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)\n         register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)\n         register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)\n         #undef register_sf4\n\n         #define register_sf4ext(Op)                                                                                    \\\n         sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \\\n\n         register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)\n         register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)\n         register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)\n         register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)\n         register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)\n         register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)\n         register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)\n         register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)\n         register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)\n         register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)\n         register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)\n         register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)\n         register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)\n         register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)\n         register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)\n         register_sf4ext(60) register_sf4ext(61)\n         #undef register_sf4ext\n      }\n\n      inline results_context_t& results_ctx()\n      {\n         if (0 == results_context_)\n         {\n            results_context_ = new results_context_t();\n         }\n\n         return (*results_context_);\n      }\n\n      inline void return_cleanup()\n      {\n         #ifndef exprtk_disable_return_statement\n         if (results_context_)\n         {\n            delete results_context_;\n            results_context_ = 0;\n         }\n\n         state_.return_stmt_present = false;\n         #endif\n      }\n\n   private:\n\n      parser(const parser<T>&);\n      parser<T>& operator=(const parser<T>&);\n\n      settings_store settings_;\n      expression_generator<T> expression_generator_;\n      details::node_allocator node_allocator_;\n      symtab_store symtab_store_;\n      dependent_entity_collector dec_;\n      std::deque<parser_error::type> error_list_;\n      std::deque<bool> brkcnt_list_;\n      parser_state state_;\n      bool resolve_unknown_symbol_;\n      results_context_t* results_context_;\n      unknown_symbol_resolver* unknown_symbol_resolver_;\n      unknown_symbol_resolver default_usr_;\n      base_ops_map_t base_ops_map_;\n      unary_op_map_t unary_op_map_;\n      binary_op_map_t binary_op_map_;\n      inv_binary_op_map_t inv_binary_op_map_;\n      sf3_map_t sf3_map_;\n      sf4_map_t sf4_map_;\n      std::string synthesis_error_;\n      scope_element_manager sem_;\n\n      lexer::helper::helper_assembly helper_assembly_;\n\n      lexer::helper::commutative_inserter commutative_inserter_;\n      lexer::helper::operator_joiner      operator_joiner_2_;\n      lexer::helper::operator_joiner      operator_joiner_3_;\n      lexer::helper::symbol_replacer      symbol_replacer_;\n      lexer::helper::bracket_checker      bracket_checker_;\n      lexer::helper::numeric_checker      numeric_checker_;\n      lexer::helper::sequence_validator   sequence_validator_;\n\n      template <typename ParserType>\n      friend void details::disable_type_checking(ParserType& p);\n   };\n\n   template <typename Allocator,\n             template <typename, typename> class Sequence>\n   inline bool collect_variables(const std::string& expr_str,\n                                 Sequence<std::string, Allocator>& symbol_list)\n   {\n      typedef double T;\n      typedef exprtk::symbol_table<T> symbol_table_t;\n      typedef exprtk::expression<T>     expression_t;\n      typedef exprtk::parser<T>             parser_t;\n      typedef parser_t::dependent_entity_collector::symbol_t symbol_t;\n\n      symbol_table_t symbol_table;\n      expression_t   expression;\n      parser_t       parser;\n\n      expression.register_symbol_table(symbol_table);\n\n      parser.enable_unknown_symbol_resolver();\n      parser.dec().collect_variables() = true;\n\n      if (!parser.compile(expr_str, expression))\n         return false;\n\n      std::deque<symbol_t> symb_list;\n\n      parser.dec().symbols(symb_list);\n\n      for (std::size_t i = 0; i < symb_list.size(); ++i)\n      {\n         symbol_list.push_back(symb_list[i].first);\n      }\n\n      return true;\n   }\n\n   template <typename T,\n             typename Allocator,\n             template <typename, typename> class Sequence>\n   inline bool collect_variables(const std::string& expr_str,\n                                 exprtk::symbol_table<T>& extrnl_symbol_table,\n                                 Sequence<std::string, Allocator>& symbol_list)\n   {\n      typedef exprtk::symbol_table<T> symbol_table_t;\n      typedef exprtk::expression<T>     expression_t;\n      typedef exprtk::parser<T>             parser_t;\n      typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;\n\n      symbol_table_t symbol_table;\n      expression_t   expression;\n      parser_t       parser;\n\n      expression.register_symbol_table(symbol_table);\n      expression.register_symbol_table(extrnl_symbol_table);\n\n      parser.enable_unknown_symbol_resolver();\n      parser.dec().collect_variables() = true;\n\n      details::disable_type_checking(parser);\n\n      if (!parser.compile(expr_str, expression))\n         return false;\n\n      std::deque<symbol_t> symb_list;\n\n      parser.dec().symbols(symb_list);\n\n      for (std::size_t i = 0; i < symb_list.size(); ++i)\n      {\n         symbol_list.push_back(symb_list[i].first);\n      }\n\n      return true;\n   }\n\n   template <typename Allocator,\n             template <typename, typename> class Sequence>\n   inline bool collect_functions(const std::string& expr_str,\n                                 Sequence<std::string, Allocator>& symbol_list)\n   {\n      typedef double T;\n      typedef exprtk::symbol_table<T> symbol_table_t;\n      typedef exprtk::expression<T>     expression_t;\n      typedef exprtk::parser<T>             parser_t;\n      typedef parser_t::dependent_entity_collector::symbol_t symbol_t;\n\n      symbol_table_t symbol_table;\n      expression_t   expression;\n      parser_t       parser;\n\n      expression.register_symbol_table(symbol_table);\n\n      parser.enable_unknown_symbol_resolver();\n      parser.dec().collect_functions() = true;\n\n      if (!parser.compile(expr_str, expression))\n         return false;\n\n      std::deque<symbol_t> symb_list;\n\n      parser.dec().symbols(symb_list);\n\n      for (std::size_t i = 0; i < symb_list.size(); ++i)\n      {\n         symbol_list.push_back(symb_list[i].first);\n      }\n\n      return true;\n   }\n\n   template <typename T,\n             typename Allocator,\n             template <typename, typename> class Sequence>\n   inline bool collect_functions(const std::string& expr_str,\n                                 exprtk::symbol_table<T>& extrnl_symbol_table,\n                                 Sequence<std::string, Allocator>& symbol_list)\n   {\n      typedef exprtk::symbol_table<T> symbol_table_t;\n      typedef exprtk::expression<T>     expression_t;\n      typedef exprtk::parser<T>             parser_t;\n      typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;\n\n      symbol_table_t symbol_table;\n      expression_t   expression;\n      parser_t       parser;\n\n      expression.register_symbol_table(symbol_table);\n      expression.register_symbol_table(extrnl_symbol_table);\n\n      parser.enable_unknown_symbol_resolver();\n      parser.dec().collect_functions() = true;\n\n      details::disable_type_checking(parser);\n\n      if (!parser.compile(expr_str, expression))\n         return false;\n\n      std::deque<symbol_t> symb_list;\n\n      parser.dec().symbols(symb_list);\n\n      for (std::size_t i = 0; i < symb_list.size(); ++i)\n      {\n         symbol_list.push_back(symb_list[i].first);\n      }\n\n      return true;\n   }\n\n   template <typename T>\n   inline T integrate(const expression<T>& e,\n                      T& x,\n                      const T& r0, const T& r1,\n                      const std::size_t number_of_intervals = 1000000)\n   {\n      if (r0 > r1)\n         return T(0);\n\n      const T h = (r1 - r0) / (T(2) * number_of_intervals);\n      T total_area = T(0);\n\n      for (std::size_t i = 0; i < number_of_intervals; ++i)\n      {\n         x = r0 + T(2) * i * h;\n         const T y0 = e.value(); x += h;\n         const T y1 = e.value(); x += h;\n         const T y2 = e.value(); x += h;\n         total_area += h * (y0 + T(4) * y1 + y2) / T(3);\n      }\n\n      return total_area;\n   }\n\n   template <typename T>\n   inline T integrate(const expression<T>& e,\n                      const std::string& variable_name,\n                      const T& r0, const T& r1,\n                      const std::size_t number_of_intervals = 1000000)\n   {\n      const symbol_table<T>& sym_table = e.get_symbol_table();\n\n      if (!sym_table.valid())\n         return std::numeric_limits<T>::quiet_NaN();\n\n      details::variable_node<T>* var = sym_table.get_variable(variable_name);\n\n      if (var)\n      {\n         T& x = var->ref();\n         T  x_original = x;\n         T result = integrate(e,x,r0,r1,number_of_intervals);\n         x = x_original;\n\n         return result;\n      }\n      else\n         return std::numeric_limits<T>::quiet_NaN();\n   }\n\n   template <typename T>\n   inline T derivative(const expression<T>& e,\n                       T& x,\n                       const T& h = T(0.00000001))\n   {\n      const T x_init = x;\n      const T _2h    = T(2) * h;\n\n      x = x_init + _2h;\n      const T y0 = e.value();\n      x = x_init +   h;\n      const T y1 = e.value();\n      x = x_init -   h;\n      const T y2 = e.value();\n      x = x_init - _2h;\n      const T y3 = e.value();\n      x = x_init;\n\n      return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);\n   }\n\n   template <typename T>\n   inline T second_derivative(const expression<T>& e,\n                              T& x,\n                              const T& h = T(0.00001))\n   {\n      const T x_init = x;\n      const T _2h    = T(2) * h;\n\n      const T y = e.value();\n      x = x_init + _2h;\n      const T y0 = e.value();\n      x = x_init +   h;\n      const T y1 = e.value();\n      x = x_init -   h;\n      const T y2 = e.value();\n      x = x_init - _2h;\n      const T y3 = e.value();\n      x = x_init;\n\n      return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);\n   }\n\n   template <typename T>\n   inline T third_derivative(const expression<T>& e,\n                             T& x,\n                             const T& h = T(0.0001))\n   {\n      const T x_init = x;\n      const T _2h    = T(2) * h;\n\n      x = x_init + _2h;\n      const T y0 = e.value();\n      x = x_init +   h;\n      const T y1 = e.value();\n      x = x_init -   h;\n      const T y2 = e.value();\n      x = x_init - _2h;\n      const T y3 = e.value();\n      x = x_init;\n\n      return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);\n   }\n\n   template <typename T>\n   inline T derivative(const expression<T>& e,\n                       const std::string& variable_name,\n                       const T& h = T(0.00000001))\n   {\n      const symbol_table<T>& sym_table = e.get_symbol_table();\n\n      if (!sym_table.valid())\n      {\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n\n      details::variable_node<T>* var = sym_table.get_variable(variable_name);\n\n      if (var)\n      {\n         T& x = var->ref();\n         T x_original = x;\n         T result = derivative(e,x,h);\n         x = x_original;\n\n         return result;\n      }\n      else\n         return std::numeric_limits<T>::quiet_NaN();\n   }\n\n   template <typename T>\n   inline T second_derivative(const expression<T>& e,\n                              const std::string& variable_name,\n                              const T& h = T(0.00001))\n   {\n      const symbol_table<T>& sym_table = e.get_symbol_table();\n\n      if (!sym_table.valid())\n      {\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n\n      details::variable_node<T>* var = sym_table.get_variable(variable_name);\n\n      if (var)\n      {\n         T& x = var->ref();\n         const T x_original = x;\n         const T result = second_derivative(e,x,h);\n         x = x_original;\n\n         return result;\n      }\n      else\n         return std::numeric_limits<T>::quiet_NaN();\n   }\n\n   template <typename T>\n   inline T third_derivative(const expression<T>& e,\n                             const std::string& variable_name,\n                             const T& h = T(0.0001))\n   {\n      const symbol_table<T>& sym_table = e.get_symbol_table();\n\n      if (!sym_table.valid())\n      {\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n\n      details::variable_node<T>* var = sym_table.get_variable(variable_name);\n\n      if (var)\n      {\n         T& x = var->ref();\n         const T x_original = x;\n         const T result = third_derivative(e,x,h);\n         x = x_original;\n\n         return result;\n      }\n      else\n         return std::numeric_limits<T>::quiet_NaN();\n   }\n\n   /*\n      Note: The following 'compute' routines are simple helpers,\n      for quickly setting up the required pieces of code in order\n      to evaluate an expression. By virtue of how they operate\n      there will be an overhead with regards to their setup and\n      teardown and hence should not be used in time critical\n      sections of code.\n      Furthermore they only assume a small sub set of variables,\n      no string variables or user defined functions.\n   */\n   template <typename T>\n   inline bool compute(const std::string& expression_string, T& result)\n   {\n      // No variables\n      symbol_table<T> symbol_table;\n      symbol_table.add_constants();\n\n      expression<T> expression;\n      expression.register_symbol_table(symbol_table);\n\n      parser<T> parser;\n\n      if (parser.compile(expression_string,expression))\n      {\n         result = expression.value();\n\n         return true;\n      }\n      else\n         return false;\n   }\n\n   template <typename T>\n   inline bool compute(const std::string& expression_string,\n                       const T& x,\n                       T& result)\n   {\n      // Only 'x'\n      static const std::string x_var(\"x\");\n\n      symbol_table<T> symbol_table;\n      symbol_table.add_constants();\n      symbol_table.add_constant(x_var,x);\n\n      expression<T> expression;\n      expression.register_symbol_table(symbol_table);\n\n      parser<T> parser;\n\n      if (parser.compile(expression_string,expression))\n      {\n         result = expression.value();\n\n         return true;\n      }\n      else\n         return false;\n   }\n\n   template <typename T>\n   inline bool compute(const std::string& expression_string,\n                       const T&x, const T& y,\n                       T& result)\n   {\n      // Only 'x' and 'y'\n      static const std::string x_var(\"x\");\n      static const std::string y_var(\"y\");\n\n      symbol_table<T> symbol_table;\n      symbol_table.add_constants();\n      symbol_table.add_constant(x_var,x);\n      symbol_table.add_constant(y_var,y);\n\n      expression<T> expression;\n      expression.register_symbol_table(symbol_table);\n\n      parser<T> parser;\n\n      if (parser.compile(expression_string,expression))\n      {\n         result = expression.value();\n\n         return true;\n      }\n      else\n         return false;\n   }\n\n   template <typename T>\n   inline bool compute(const std::string& expression_string,\n                       const T& x, const T& y, const T& z,\n                       T& result)\n   {\n      // Only 'x', 'y' or 'z'\n      static const std::string x_var(\"x\");\n      static const std::string y_var(\"y\");\n      static const std::string z_var(\"z\");\n\n      symbol_table<T> symbol_table;\n      symbol_table.add_constants();\n      symbol_table.add_constant(x_var,x);\n      symbol_table.add_constant(y_var,y);\n      symbol_table.add_constant(z_var,z);\n\n      expression<T> expression;\n      expression.register_symbol_table(symbol_table);\n\n      parser<T> parser;\n\n      if (parser.compile(expression_string,expression))\n      {\n         result = expression.value();\n\n         return true;\n      }\n      else\n         return false;\n   }\n\n   template <typename T, std::size_t N>\n   class polynomial : public ifunction<T>\n   {\n   private:\n\n      template <typename Type, std::size_t NumberOfCoefficients>\n      struct poly_impl { };\n\n      template <typename Type>\n      struct poly_impl <Type,12>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,\n                                  const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,\n                                  const Type  c2, const Type  c1, const Type  c0)\n         {\n            // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,11>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,\n                                  const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,\n                                  const Type c1,  const Type  c0)\n         {\n            // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,10>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,\n                                  const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,\n                                  const Type c0)\n         {\n            // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,9>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,\n                                  const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)\n         {\n            // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,8>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,\n                                  const Type c3, const Type c2, const Type c1, const Type c0)\n         {\n            // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,7>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,\n                                  const Type c2, const Type c1, const Type c0)\n         {\n            // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,6>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,\n                                  const Type c1, const Type c0)\n         {\n            // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,5>\n      {\n         static inline T evaluate(const Type x,\n                                  const Type c5, const Type c4, const Type c3, const Type c2,\n                                  const Type c1, const Type c0)\n         {\n            // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,4>\n      {\n         static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)\n         {\n            // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,3>\n      {\n         static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)\n         {\n            // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0\n            return (((c3 * x + c2) * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,2>\n      {\n         static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)\n         {\n            // p(x) = c_2x^2 + c_1x^1 + c_0x^0\n            return ((c2 * x + c1) * x + c0);\n         }\n      };\n\n      template <typename Type>\n      struct poly_impl <Type,1>\n      {\n         static inline T evaluate(const Type x, const Type c1, const Type c0)\n         {\n            // p(x) = c_1x^1 + c_0x^0\n            return (c1 * x + c0);\n         }\n      };\n\n   public:\n\n      using ifunction<T>::operator();\n\n      polynomial()\n      : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())\n      {\n         disable_has_side_effects(*this);\n      }\n\n      virtual ~polynomial()\n      {}\n\n      #define poly_rtrn(NN) \\\n      return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :\n\n      inline virtual T operator() (const T& x, const T& c1, const T& c0)\n      {\n         poly_rtrn(1) poly_impl<T,1>::evaluate(x,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(2) poly_impl<T,2>::evaluate(x,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(3) poly_impl<T,3>::evaluate(x,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(4) poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(5) poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(6) poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(7) poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(8) poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(9) poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(10) poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(11) poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)\n      {\n         poly_rtrn(12) poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);\n      }\n\n      #undef poly_rtrn\n\n      inline virtual T operator() ()\n      {\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n\n      inline virtual T operator() (const T&)\n      {\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n\n      inline virtual T operator() (const T&, const T&)\n      {\n         return std::numeric_limits<T>::quiet_NaN();\n      }\n   };\n\n   template <typename T>\n   class function_compositor\n   {\n   public:\n\n      typedef exprtk::expression<T>             expression_t;\n      typedef exprtk::symbol_table<T>           symbol_table_t;\n      typedef exprtk::parser<T>                 parser_t;\n      typedef typename parser_t::settings_store settings_t;\n\n      struct function\n      {\n         function()\n         {}\n\n         function(const std::string& n)\n         : name_(n)\n         {}\n\n         function(const std::string& name,\n                  const std::string& expression)\n         : name_(name),\n           expression_(expression)\n         {}\n\n         function(const std::string& name,\n                  const std::string& expression,\n                  const std::string& v0)\n         : name_(name),\n           expression_(expression)\n         {\n            v_.push_back(v0);\n         }\n\n         function(const std::string& name,\n                  const std::string& expression,\n                  const std::string& v0, const std::string& v1)\n         : name_(name),\n           expression_(expression)\n         {\n            v_.push_back(v0); v_.push_back(v1);\n         }\n\n         function(const std::string& name,\n                  const std::string& expression,\n                  const std::string& v0, const std::string& v1,\n                  const std::string& v2)\n         : name_(name),\n           expression_(expression)\n         {\n            v_.push_back(v0); v_.push_back(v1);\n            v_.push_back(v2);\n         }\n\n         function(const std::string& name,\n                  const std::string& expression,\n                  const std::string& v0, const std::string& v1,\n                  const std::string& v2, const std::string& v3)\n         : name_(name),\n           expression_(expression)\n         {\n            v_.push_back(v0); v_.push_back(v1);\n            v_.push_back(v2); v_.push_back(v3);\n         }\n\n         function(const std::string& name,\n                  const std::string& expression,\n                  const std::string& v0, const std::string& v1,\n                  const std::string& v2, const std::string& v3,\n                  const std::string& v4)\n         : name_(name),\n           expression_(expression)\n         {\n            v_.push_back(v0); v_.push_back(v1);\n            v_.push_back(v2); v_.push_back(v3);\n            v_.push_back(v4);\n         }\n\n         inline function& name(const std::string& n)\n         {\n            name_ = n;\n            return (*this);\n         }\n\n         inline function& expression(const std::string& e)\n         {\n            expression_ = e;\n            return (*this);\n         }\n\n         inline function& var(const std::string& v)\n         {\n            v_.push_back(v);\n            return (*this);\n         }\n\n         std::string name_;\n         std::string expression_;\n         std::deque<std::string> v_;\n      };\n\n   private:\n\n      struct base_func : public exprtk::ifunction<T>\n      {\n         typedef const T&                       type;\n         typedef exprtk::ifunction<T>     function_t;\n         typedef std::vector<T*>            varref_t;\n         typedef std::vector<T>                var_t;\n         typedef std::pair<T*,std::size_t> lvarref_t;\n         typedef std::vector<lvarref_t>    lvr_vec_t;\n\n         using exprtk::ifunction<T>::operator();\n\n         base_func(const std::size_t& pc = 0)\n         : exprtk::ifunction<T>(pc),\n           local_var_stack_size(0),\n           stack_depth(0)\n         {\n            v.resize(pc);\n         }\n\n         virtual ~base_func()\n         {}\n\n         inline void update(const T& v0)\n         {\n            (*v[0]) = v0;\n         }\n\n         inline void update(const T& v0, const T& v1)\n         {\n            (*v[0]) = v0; (*v[1]) = v1;\n         }\n\n         inline void update(const T& v0, const T& v1, const T& v2)\n         {\n            (*v[0]) = v0; (*v[1]) = v1;\n            (*v[2]) = v2;\n         }\n\n         inline void update(const T& v0, const T& v1, const T& v2, const T& v3)\n         {\n            (*v[0]) = v0; (*v[1]) = v1;\n            (*v[2]) = v2; (*v[3]) = v3;\n         }\n\n         inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)\n         {\n            (*v[0]) = v0; (*v[1]) = v1;\n            (*v[2]) = v2; (*v[3]) = v3;\n            (*v[4]) = v4;\n         }\n\n         inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)\n         {\n            (*v[0]) = v0; (*v[1]) = v1;\n            (*v[2]) = v2; (*v[3]) = v3;\n            (*v[4]) = v4; (*v[5]) = v5;\n         }\n\n         inline function_t& setup(expression_t& expr)\n         {\n            expression = expr;\n\n            typedef typename expression_t::control_block::local_data_list_t ldl_t;\n\n            ldl_t ldl = expr.local_data_list();\n\n            std::vector<std::size_t> index_list;\n\n            for (std::size_t i = 0; i < ldl.size(); ++i)\n            {\n               if (ldl[i].size)\n               {\n                  index_list.push_back(i);\n               }\n            }\n\n            std::size_t input_param_count = 0;\n\n            for (std::size_t i = 0; i < index_list.size(); ++i)\n            {\n               const std::size_t index = index_list[i];\n\n               if (i < (index_list.size() - v.size()))\n               {\n                  lv.push_back(\n                        std::make_pair(\n                           reinterpret_cast<T*>(ldl[index].pointer),\n                           ldl[index].size));\n\n                  local_var_stack_size += ldl[index].size;\n               }\n               else\n                  v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);\n            }\n\n            clear_stack();\n\n            return (*this);\n         }\n\n         inline void pre()\n         {\n            if (stack_depth++)\n            {\n               if (!v.empty())\n               {\n                  var_t var_stack(v.size(),T(0));\n                  copy(v,var_stack);\n                  param_stack.push_back(var_stack);\n               }\n\n               if (!lv.empty())\n               {\n                  var_t local_var_stack(local_var_stack_size,T(0));\n                  copy(lv,local_var_stack);\n                  local_stack.push_back(local_var_stack);\n               }\n            }\n         }\n\n         inline void post()\n         {\n            if (--stack_depth)\n            {\n               if (!v.empty())\n               {\n                  copy(param_stack.back(),v);\n                  param_stack.pop_back();\n               }\n\n               if (!lv.empty())\n               {\n                  copy(local_stack.back(),lv);\n                  local_stack.pop_back();\n               }\n            }\n         }\n\n         void copy(const varref_t& src_v, var_t& dest_v)\n         {\n            for (std::size_t i = 0; i < src_v.size(); ++i)\n            {\n               dest_v[i] = (*src_v[i]);\n            }\n         }\n\n         void copy(const var_t& src_v, varref_t& dest_v)\n         {\n            for (std::size_t i = 0; i < src_v.size(); ++i)\n            {\n               (*dest_v[i]) = src_v[i];\n            }\n         }\n\n         void copy(const lvr_vec_t& src_v, var_t& dest_v)\n         {\n            typename var_t::iterator itr = dest_v.begin();\n            typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;\n\n            for (std::size_t i = 0; i < src_v.size(); ++i)\n            {\n               lvarref_t vr = src_v[i];\n\n               if (1 == vr.second)\n                  *itr++ = (*vr.first);\n               else\n               {\n                  std::copy(vr.first, vr.first + vr.second, itr);\n                  itr += static_cast<diff_t>(vr.second);\n               }\n            }\n         }\n\n         void copy(const var_t& src_v, lvr_vec_t& dest_v)\n         {\n            typename var_t::const_iterator itr = src_v.begin();\n            typedef  typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;\n\n            for (std::size_t i = 0; i < src_v.size(); ++i)\n            {\n               lvarref_t vr = dest_v[i];\n\n               if (1 == vr.second)\n                  (*vr.first) = *itr++;\n               else\n               {\n                  std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);\n                  itr += static_cast<diff_t>(vr.second);\n               }\n            }\n         }\n\n         inline void clear_stack()\n         {\n            for (std::size_t i = 0; i < v.size(); ++i)\n            {\n               (*v[i]) = 0;\n            }\n         }\n\n         inline virtual T value(expression_t& e)\n         {\n            return e.value();\n         }\n\n         expression_t expression;\n         varref_t v;\n         lvr_vec_t lv;\n         std::size_t local_var_stack_size;\n         std::size_t stack_depth;\n         std::deque<var_t> param_stack;\n         std::deque<var_t> local_stack;\n      };\n\n      typedef std::map<std::string,base_func*> funcparam_t;\n\n      struct func_0param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_0param() : base_func(0) {}\n\n         inline T operator() ()\n         {\n            return this->value(base_func::expression);\n         }\n      };\n\n      typedef const T& type;\n\n      template <typename BaseFuncType>\n      struct scoped_bft\n      {\n         scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }\n        ~scoped_bft()                              { bft_.post(); }\n\n         BaseFuncType& bft_;\n\n      private:\n\n         scoped_bft(scoped_bft&);\n         scoped_bft& operator=(scoped_bft&);\n      };\n\n      struct func_1param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_1param() : base_func(1) {}\n\n         inline T operator() (type v0)\n         {\n            scoped_bft<func_1param> sb(*this);\n            base_func::update(v0);\n            return this->value(base_func::expression);\n         }\n      };\n\n      struct func_2param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_2param() : base_func(2) {}\n\n         inline T operator() (type v0, type v1)\n         {\n            scoped_bft<func_2param> sb(*this);\n            base_func::update(v0, v1);\n            return this->value(base_func::expression);\n         }\n      };\n\n      struct func_3param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_3param() : base_func(3) {}\n\n         inline T operator() (type v0, type v1, type v2)\n         {\n            scoped_bft<func_3param> sb(*this);\n            base_func::update(v0, v1, v2);\n            return this->value(base_func::expression);\n         }\n      };\n\n      struct func_4param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_4param() : base_func(4) {}\n\n         inline T operator() (type v0, type v1, type v2, type v3)\n         {\n            scoped_bft<func_4param> sb(*this);\n            base_func::update(v0, v1, v2, v3);\n            return this->value(base_func::expression);\n         }\n      };\n\n      struct func_5param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_5param() : base_func(5) {}\n\n         inline T operator() (type v0, type v1, type v2, type v3, type v4)\n         {\n            scoped_bft<func_5param> sb(*this);\n            base_func::update(v0, v1, v2, v3, v4);\n            return this->value(base_func::expression);\n         }\n      };\n\n      struct func_6param : public base_func\n      {\n         using exprtk::ifunction<T>::operator();\n\n         func_6param() : base_func(6) {}\n\n         inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)\n         {\n            scoped_bft<func_6param> sb(*this);\n            base_func::update(v0, v1, v2, v3, v4, v5);\n            return this->value(base_func::expression);\n         }\n      };\n\n      static T return_value(expression_t& e)\n      {\n         typedef exprtk::results_context<T> results_context_t;\n         typedef typename results_context_t::type_store_t type_t;\n         typedef typename type_t::scalar_view scalar_t;\n\n         T result = e.value();\n\n         if (e.return_invoked())\n         {\n            // Due to the post compilation checks, it can be safely\n            // assumed that there will be at least one parameter\n            // and that the first parameter will always be scalar.\n            return scalar_t(e.results()[0])();\n         }\n\n         return result;\n      }\n\n      #define def_fp_retval(N)                               \\\n      struct func_##N##param_retval : public func_##N##param \\\n      {                                                      \\\n         inline T value(expression_t& e)                     \\\n         {                                                   \\\n            return return_value(e);                          \\\n         }                                                   \\\n      };                                                     \\\n\n      def_fp_retval(0)\n      def_fp_retval(1)\n      def_fp_retval(2)\n      def_fp_retval(3)\n      def_fp_retval(4)\n      def_fp_retval(5)\n      def_fp_retval(6)\n\n      template <typename Allocator,\n                template <typename,typename> class Sequence>\n      inline bool add(const std::string& name,\n                      const std::string& expression,\n                      const Sequence<std::string,Allocator>& var_list,\n                      const bool override = false)\n      {\n         const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);\n\n         if (expr_map_.end() != itr)\n         {\n            if (!override)\n            {\n               exprtk_debug((\"Compositor error(add): function '%s' already defined\\n\",\n                             name.c_str()));\n\n               return false;\n            }\n\n            remove(name, var_list.size());\n         }\n\n         if (compile_expression(name,expression,var_list))\n         {\n            const std::size_t n = var_list.size();\n\n            fp_map_[n][name]->setup(expr_map_[name]);\n\n            return true;\n         }\n         else\n         {\n            exprtk_debug((\"Compositor error(add): Failed to compile function '%s'\\n\",\n                          name.c_str()));\n\n            return false;\n         }\n      }\n\n   public:\n\n      function_compositor()\n      : parser_(settings_t::compile_all_opts +\n                settings_t::e_disable_zero_return),\n        fp_map_(7)\n      {}\n\n      function_compositor(const symbol_table_t& st)\n      : symbol_table_(st),\n        parser_(settings_t::compile_all_opts +\n                settings_t::e_disable_zero_return),\n        fp_map_(7)\n      {}\n\n     ~function_compositor()\n      {\n         clear();\n      }\n\n      inline symbol_table_t& symbol_table()\n      {\n         return symbol_table_;\n      }\n\n      inline void add_auxiliary_symtab(symbol_table_t& symtab)\n      {\n         auxiliary_symtab_list_.push_back(&symtab);\n      }\n\n      void clear()\n      {\n         symbol_table_.clear();\n         expr_map_    .clear();\n\n         for (std::size_t i = 0; i < fp_map_.size(); ++i)\n         {\n            typename funcparam_t::iterator itr = fp_map_[i].begin();\n            typename funcparam_t::iterator end = fp_map_[i].end  ();\n\n            while (itr != end)\n            {\n               delete itr->second;\n               ++itr;\n            }\n\n            fp_map_[i].clear();\n         }\n      }\n\n      inline bool add(const function& f, const bool override = false)\n      {\n         return add(f.name_, f.expression_, f.v_,override);\n      }\n\n   private:\n\n      template <typename Allocator,\n                template <typename,typename> class Sequence>\n      bool compile_expression(const std::string& name,\n                              const std::string& expression,\n                              const Sequence<std::string,Allocator>& input_var_list,\n                              bool  return_present = false)\n      {\n         expression_t compiled_expression;\n         symbol_table_t local_symbol_table;\n\n         local_symbol_table.load_from(symbol_table_);\n         local_symbol_table.add_constants();\n\n         if (!valid(name,input_var_list.size()))\n            return false;\n\n         if (!forward(name,\n                      input_var_list.size(),\n                      local_symbol_table,\n                      return_present))\n            return false;\n\n         compiled_expression.register_symbol_table(local_symbol_table);\n\n         for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)\n         {\n            compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));\n         }\n\n         std::string mod_expression;\n\n         for (std::size_t i = 0; i < input_var_list.size(); ++i)\n         {\n            mod_expression += \" var \" + input_var_list[i] + \"{};\\n\";\n         }\n\n         if (\n              ('{' == details::front(expression)) &&\n              ('}' == details::back (expression))\n            )\n            mod_expression += \"~\" + expression + \";\";\n         else\n            mod_expression += \"~{\" + expression + \"};\";\n\n         if (!parser_.compile(mod_expression,compiled_expression))\n         {\n            exprtk_debug((\"Compositor Error: %s\\n\",parser_.error().c_str()));\n            exprtk_debug((\"Compositor modified expression: \\n%s\\n\",mod_expression.c_str()));\n\n            remove(name,input_var_list.size());\n\n            return false;\n         }\n\n         if (!return_present && parser_.dec().return_present())\n         {\n            remove(name,input_var_list.size());\n\n            return compile_expression(name, expression, input_var_list, true);\n         }\n\n         // Make sure every return point has a scalar as its first parameter\n         if (parser_.dec().return_present())\n         {\n            typedef std::vector<std::string> str_list_t;\n\n            str_list_t ret_param_list = parser_.dec().return_param_type_list();\n\n            for (std::size_t i = 0; i < ret_param_list.size(); ++i)\n            {\n               const std::string& params = ret_param_list[i];\n\n               if (params.empty() || ('T' != params[0]))\n               {\n                  exprtk_debug((\"Compositor Error: Return statement in function '%s' is invalid\\n\",\n                                name.c_str()));\n\n                  remove(name,input_var_list.size());\n\n                  return false;\n               }\n            }\n         }\n\n         expr_map_[name] = compiled_expression;\n\n         exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);\n\n         if (symbol_table_.add_function(name,ifunc))\n            return true;\n         else\n         {\n            exprtk_debug((\"Compositor Error: Failed to add function '%s' to symbol table\\n\",\n                          name.c_str()));\n            return false;\n         }\n      }\n\n      inline bool symbol_used(const std::string& symbol) const\n      {\n         return (\n                  symbol_table_.is_variable       (symbol) ||\n                  symbol_table_.is_stringvar      (symbol) ||\n                  symbol_table_.is_function       (symbol) ||\n                  symbol_table_.is_vector         (symbol) ||\n                  symbol_table_.is_vararg_function(symbol)\n                );\n      }\n\n      inline bool valid(const std::string& name,\n                        const std::size_t& arg_count) const\n      {\n         if (arg_count > 6)\n            return false;\n         else if (symbol_used(name))\n            return false;\n         else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))\n            return false;\n         else\n            return true;\n      }\n\n      inline bool forward(const std::string& name,\n                          const std::size_t& arg_count,\n                          symbol_table_t& sym_table,\n                          const bool ret_present = false)\n      {\n         switch (arg_count)\n         {\n            #define case_stmt(N)                                     \\\n            case N : (fp_map_[arg_count])[name] =                    \\\n                     (!ret_present) ? static_cast<base_func*>        \\\n                                      (new func_##N##param) :        \\\n                                      static_cast<base_func*>        \\\n                                      (new func_##N##param_retval) ; \\\n                     break;                                          \\\n\n            case_stmt(0) case_stmt(1) case_stmt(2)\n            case_stmt(3) case_stmt(4) case_stmt(5)\n            case_stmt(6)\n            #undef case_stmt\n         }\n\n         exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);\n\n         return sym_table.add_function(name,ifunc);\n      }\n\n      inline void remove(const std::string& name, const std::size_t& arg_count)\n      {\n         if (arg_count > 6)\n            return;\n\n         const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);\n\n         if (expr_map_.end() != em_itr)\n         {\n            expr_map_.erase(em_itr);\n         }\n\n         const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);\n\n         if (fp_map_[arg_count].end() != fp_itr)\n         {\n            delete fp_itr->second;\n            fp_map_[arg_count].erase(fp_itr);\n         }\n\n         symbol_table_.remove_function(name);\n      }\n\n   private:\n\n      symbol_table_t symbol_table_;\n      parser_t parser_;\n      std::map<std::string,expression_t> expr_map_;\n      std::vector<funcparam_t> fp_map_;\n      std::vector<symbol_table_t*> auxiliary_symtab_list_;\n   };\n\n   template <typename T>\n   inline bool pgo_primer()\n   {\n      static const std::string expression_list[]\n                                        = {\n                                             \"(y + x)\",\n                                             \"2 * (y + x)\",\n                                             \"(2 * y + 2 * x)\",\n                                             \"(y + x / y) * (x - y / x)\",\n                                             \"x / ((x + y) * (x - y)) / y\",\n                                             \"1 - ((x * y) + (y / x)) - 3\",\n                                             \"sin(2 * x) + cos(pi / y)\",\n                                             \"1 - sin(2 * x) + cos(pi / y)\",\n                                             \"sqrt(1 - sin(2 * x) + cos(pi / y) / 3)\",\n                                             \"(x^2 / sin(2 * pi / y)) -x / 2\",\n                                             \"x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y\",\n                                             \"clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)\",\n                                             \"iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)\",\n                                             \"max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))\",\n                                             \"if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x\",\n                                             \"1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55\",\n                                             \"(yy + xx)\",\n                                             \"2 * (yy + xx)\",\n                                             \"(2 * yy + 2 * xx)\",\n                                             \"(yy + xx / yy) * (xx - yy / xx)\",\n                                             \"xx / ((xx + yy) * (xx - yy)) / yy\",\n                                             \"1 - ((xx * yy) + (yy / xx)) - 3\",\n                                             \"sin(2 * xx) + cos(pi / yy)\",\n                                             \"1 - sin(2 * xx) + cos(pi / yy)\",\n                                             \"sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)\",\n                                             \"(xx^2 / sin(2 * pi / yy)) -xx / 2\",\n                                             \"xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy\",\n                                             \"clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)\",\n                                             \"max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))\",\n                                             \"if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx\",\n                                             \"1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55\",\n                                             \"(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))\",\n                                             \"(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)\",\n                                             \"(x + y) * z\", \"x + (y * z)\", \"(x + y) * 7\", \"x + (y * 7)\",\n                                             \"(x + 7) * y\", \"x + (7 * y)\", \"(7 + x) * y\", \"7 + (x * y)\",\n                                             \"(2 + x) * 3\", \"2 + (x * 3)\", \"(2 + 3) * x\", \"2 + (3 * x)\",\n                                             \"(x + 2) * 3\", \"x + (2 * 3)\",\n                                             \"(x + y) * (z / w)\", \"(x + y) * (z / 7)\", \"(x + y) * (7 / z)\", \"(x + 7) * (y / z)\",\n                                             \"(7 + x) * (y / z)\", \"(2 + x) * (y / z)\", \"(x + 2) * (y / 3)\", \"(2 + x) * (y / 3)\",\n                                             \"(x + 2) * (3 / y)\", \"x + (y * (z / w))\", \"x + (y * (z / 7))\", \"x + (y * (7 / z))\",\n                                             \"x + (7 * (y / z))\", \"7 + (x * (y / z))\", \"2 + (x * (3 / y))\", \"x + (2 * (y / 4))\",\n                                             \"2 + (x * (y / 3))\", \"x + (2 * (3 / y))\",\n                                             \"x + ((y * z) / w)\", \"x + ((y * z) / 7)\", \"x + ((y * 7) / z)\", \"x + ((7 * y) / z)\",\n                                             \"7 + ((y * z) / w)\", \"2 + ((x * 3) / y)\", \"x + ((2 * y) / 3)\", \"2 + ((x * y) / 3)\",\n                                             \"x + ((2 * 3) / y)\", \"(((x + y) * z) / w)\",\n                                             \"(((x + y) * z) / 7)\", \"(((x + y) * 7) / z)\", \"(((x + 7) * y) / z)\", \"(((7 + x) * y) / z)\",\n                                             \"(((2 + x) * 3) / y)\", \"(((x + 2) * y) / 3)\", \"(((2 + x) * y) / 3)\", \"(((x + 2) * 3) / y)\",\n                                             \"((x + (y * z)) / w)\", \"((x + (y * z)) / 7)\", \"((x + (y * 7)) / y)\", \"((x + (7 * y)) / z)\",\n                                             \"((7 + (x * y)) / z)\", \"((2 + (x * 3)) / y)\", \"((x + (2 * y)) / 3)\", \"((2 + (x * y)) / 3)\",\n                                             \"((x + (2 * 3)) / y)\",\n                                             \"(xx + yy) * zz\", \"xx + (yy * zz)\",\n                                             \"(xx + yy) * 7\", \"xx + (yy * 7)\",\n                                             \"(xx + 7) * yy\", \"xx + (7 * yy)\",\n                                             \"(7 + xx) * yy\", \"7 + (xx * yy)\",\n                                             \"(2 + x) * 3\", \"2 + (x * 3)\",\n                                             \"(2 + 3) * x\", \"2 + (3 * x)\",\n                                             \"(x + 2) * 3\", \"x + (2 * 3)\",\n                                             \"(xx + yy) * (zz / ww)\", \"(xx + yy) * (zz / 7)\",\n                                             \"(xx + yy) * (7 / zz)\", \"(xx + 7) * (yy / zz)\",\n                                             \"(7 + xx) * (yy / zz)\", \"(2 + xx) * (yy / zz)\",\n                                             \"(xx + 2) * (yy / 3)\", \"(2 + xx) * (yy / 3)\",\n                                             \"(xx + 2) * (3 / yy)\", \"xx + (yy * (zz / ww))\",\n                                             \"xx + (yy * (zz / 7))\", \"xx + (yy * (7 / zz))\",\n                                             \"xx + (7 * (yy / zz))\", \"7 + (xx * (yy / zz))\",\n                                             \"2 + (xx * (3 / yy))\", \"xx + (2 * (yy / 4))\",\n                                             \"2 + (xx * (yy / 3))\", \"xx + (2 * (3 / yy))\",\n                                             \"xx + ((yy * zz) / ww)\", \"xx + ((yy * zz) / 7)\",\n                                             \"xx + ((yy * 7) / zz)\", \"xx + ((7 * yy) / zz)\",\n                                             \"7 + ((yy * zz) / ww)\", \"2 + ((xx * 3) / yy)\",\n                                             \"xx + ((2 * yy) / 3)\", \"2 + ((xx * yy) / 3)\",\n                                             \"xx + ((2 * 3) / yy)\", \"(((xx + yy) * zz) / ww)\",\n                                             \"(((xx + yy) * zz) / 7)\", \"(((xx + yy) * 7) / zz)\",\n                                             \"(((xx + 7) * yy) / zz)\", \"(((7 + xx) * yy) / zz)\",\n                                             \"(((2 + xx) * 3) / yy)\", \"(((xx + 2) * yy) / 3)\",\n                                             \"(((2 + xx) * yy) / 3)\", \"(((xx + 2) * 3) / yy)\",\n                                             \"((xx + (yy * zz)) / ww)\", \"((xx + (yy * zz)) / 7)\",\n                                             \"((xx + (yy * 7)) / yy)\", \"((xx + (7 * yy)) / zz)\",\n                                             \"((7 + (xx * yy)) / zz)\", \"((2 + (xx * 3)) / yy)\",\n                                             \"((xx + (2 * yy)) / 3)\", \"((2 + (xx * yy)) / 3)\",\n                                             \"((xx + (2 * 3)) / yy)\"\n                                          };\n      static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);\n\n      T  x = T(0);\n      T  y = T(0);\n      T  z = T(0);\n      T  w = T(0);\n      T xx = T(0);\n      T yy = T(0);\n      T zz = T(0);\n      T ww = T(0);\n\n      exprtk::symbol_table<T> symbol_table;\n      symbol_table.add_constants();\n      symbol_table.add_variable( \"x\", x);\n      symbol_table.add_variable( \"y\", y);\n      symbol_table.add_variable( \"z\", z);\n      symbol_table.add_variable( \"w\", w);\n      symbol_table.add_variable(\"xx\",xx);\n      symbol_table.add_variable(\"yy\",yy);\n      symbol_table.add_variable(\"zz\",zz);\n      symbol_table.add_variable(\"ww\",ww);\n\n      typedef typename std::deque<exprtk::expression<T> > expr_list_t;\n      expr_list_t expr_list;\n\n      const std::size_t rounds = 50;\n\n      {\n         for (std::size_t r = 0; r < rounds; ++r)\n         {\n            expr_list.clear();\n            exprtk::parser<T> parser;\n\n            for (std::size_t i = 0; i < expression_list_size; ++i)\n            {\n               exprtk::expression<T> expression;\n               expression.register_symbol_table(symbol_table);\n\n               if (!parser.compile(expression_list[i],expression))\n               {\n                  return false;\n               }\n\n               expr_list.push_back(expression);\n            }\n         }\n      }\n\n      struct execute\n      {\n         static inline T process(T& x, T& y, expression<T>& expression)\n         {\n            static const T lower_bound = T(-20);\n            static const T upper_bound = T(+20);\n\n            T delta = T(0.1);\n            T total = T(0);\n\n            for (x = lower_bound; x <= upper_bound; x += delta)\n            {\n               for (y = lower_bound; y <= upper_bound; y += delta)\n               {\n                  total += expression.value();\n               }\n            }\n\n            return total;\n         }\n      };\n\n      for (std::size_t i = 0; i < expr_list.size(); ++i)\n      {\n         execute::process( x,  y, expr_list[i]);\n         execute::process(xx, yy, expr_list[i]);\n      }\n\n      {\n         for (std::size_t i = 0; i < 10000; ++i)\n         {\n            T v = T(123.456 + i);\n\n            if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1)))))\n               return false;\n\n            #define else_stmt(N)                                                                                                           \\\n            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \\\n               return false;                                                                                                               \\\n\n            else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)\n            else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)\n            else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)\n            else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)\n            else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)\n            else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)\n            else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)\n            else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)\n            else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)\n            else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)\n            else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)\n            else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)\n            else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)\n            else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)\n            else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)\n         }\n      }\n\n      return true;\n   }\n}\n\n#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)\n#   ifndef NOMINMAX\n#      define NOMINMAX\n#   endif\n#   ifndef WIN32_LEAN_AND_MEAN\n#      define WIN32_LEAN_AND_MEAN\n#   endif\n#   include <windows.h>\n#   include <ctime>\n#else\n#   include <ctime>\n#   include <sys/time.h>\n#   include <sys/types.h>\n#endif\n\nnamespace exprtk\n{\n   class timer\n   {\n   public:\n\n      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)\n      timer()\n      : in_use_(false)\n      {\n         QueryPerformanceFrequency(&clock_frequency_);\n      }\n\n      inline void start()\n      {\n         in_use_ = true;\n         QueryPerformanceCounter(&start_time_);\n      }\n\n      inline void stop()\n      {\n         QueryPerformanceCounter(&stop_time_);\n         in_use_ = false;\n      }\n\n      inline double time() const\n      {\n         return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);\n      }\n\n      #else\n\n      timer()\n      : in_use_(false)\n      {\n         start_time_.tv_sec  = 0;\n         start_time_.tv_usec = 0;\n         stop_time_.tv_sec   = 0;\n         stop_time_.tv_usec  = 0;\n      }\n\n      inline void start()\n      {\n         in_use_ = true;\n         gettimeofday(&start_time_,0);\n      }\n\n      inline void stop()\n      {\n         gettimeofday(&stop_time_, 0);\n         in_use_ = false;\n      }\n\n      inline unsigned long long int usec_time() const\n      {\n         if (!in_use_)\n         {\n            if (stop_time_.tv_sec >= start_time_.tv_sec)\n            {\n               return 1000000LLU * static_cast<unsigned long long int>(stop_time_.tv_sec  - start_time_.tv_sec ) +\n                                   static_cast<unsigned long long int>(stop_time_.tv_usec - start_time_.tv_usec) ;\n            }\n            else\n               return std::numeric_limits<unsigned long long int>::max();\n         }\n         else\n            return std::numeric_limits<unsigned long long int>::max();\n      }\n\n      inline double time() const\n      {\n         return usec_time() * 0.000001;\n      }\n\n      #endif\n\n      inline bool in_use() const\n      {\n         return in_use_;\n      }\n\n   private:\n\n      bool in_use_;\n\n      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)\n         LARGE_INTEGER start_time_;\n         LARGE_INTEGER stop_time_;\n         LARGE_INTEGER clock_frequency_;\n      #else\n         struct timeval start_time_;\n         struct timeval stop_time_;\n      #endif\n   };\n\n} // namespace exprtk\n\n#ifndef exprtk_disable_rtl_io\nnamespace exprtk\n{\n   namespace rtl { namespace io { namespace details\n   {\n      template <typename T>\n      inline void print_type(const std::string& fmt,\n                             const T v,\n                             exprtk::details::numeric::details::real_type_tag)\n      {\n         printf(fmt.c_str(),v);\n      }\n\n      template <typename T>\n      struct print_impl\n      {\n         typedef typename igeneric_function<T>::generic_type generic_type;\n         typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;\n         typedef typename generic_type::scalar_view scalar_t;\n         typedef typename generic_type::vector_view vector_t;\n         typedef typename generic_type::string_view string_t;\n         typedef typename exprtk::details::numeric::details::number_type<T>::type num_type;\n\n         static void process(const std::string& scalar_format, parameter_list_t parameters)\n         {\n            for (std::size_t i = 0; i < parameters.size(); ++i)\n            {\n               generic_type& gt = parameters[i];\n\n               switch (gt.type)\n               {\n                  case generic_type::e_scalar : print(scalar_format,scalar_t(gt));\n                                                break;\n\n                  case generic_type::e_vector : print(scalar_format,vector_t(gt));\n                                                break;\n\n                  case generic_type::e_string : print(string_t(gt));\n                                                break;\n\n                  default                     : continue;\n               }\n            }\n         }\n\n         static inline void print(const std::string& scalar_format, const scalar_t& s)\n         {\n            print_type(scalar_format,s(),num_type());\n         }\n\n         static inline void print(const std::string& scalar_format, const vector_t& v)\n         {\n            for (std::size_t i = 0; i < v.size(); ++i)\n            {\n               print_type(scalar_format,v[i],num_type());\n\n               if ((i + 1) < v.size())\n                  printf(\" \");\n            }\n         }\n\n         static inline void print(const string_t& s)\n         {\n            printf(\"%s\",to_str(s).c_str());\n         }\n      };\n\n   } // namespace exprtk::rtl::io::details\n\n   template <typename T>\n   struct print : public exprtk::igeneric_function<T>\n   {\n      typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      print(const std::string& scalar_format = \"%10.5f\")\n      : scalar_format_(scalar_format)\n      {\n         exprtk::enable_zero_parameters(*this);\n      }\n\n      inline T operator() (parameter_list_t parameters)\n      {\n         details::print_impl<T>::process(scalar_format_,parameters);\n         return T(0);\n      }\n\n      std::string scalar_format_;\n   };\n\n   template <typename T>\n   struct println : public exprtk::igeneric_function<T>\n   {\n      typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      println(const std::string& scalar_format = \"%10.5f\")\n      : scalar_format_(scalar_format)\n      {\n         exprtk::enable_zero_parameters(*this);\n      }\n\n      inline T operator() (parameter_list_t parameters)\n      {\n         details::print_impl<T>::process(scalar_format_,parameters);\n         printf(\"\\n\");\n         return T(0);\n      }\n\n      std::string scalar_format_;\n   };\n\n   template <typename T>\n   struct package\n   {\n      print  <T> p;\n      println<T> pl;\n\n      bool register_package(exprtk::symbol_table<T>& symtab)\n      {\n         #define exprtk_register_function(FunctionName,FunctionType)              \\\n         if (!symtab.add_function(FunctionName,FunctionType))                     \\\n         {                                                                        \\\n            exprtk_debug((                                                        \\\n              \"exprtk::rtl::io::register_package - Failed to add function: %s\\n\", \\\n              FunctionName));                                                     \\\n            return false;                                                         \\\n         }                                                                        \\\n\n         exprtk_register_function(\"print\"   , p)\n         exprtk_register_function(\"println\" ,pl)\n         #undef exprtk_register_function\n\n         return true;\n      }\n   };\n\n   } // namespace exprtk::rtl::io\n   } // namespace exprtk::rtl\n}    // namespace exprtk\n#endif\n\n#ifndef exprtk_disable_rtl_io_file\n#include <fstream>\nnamespace exprtk\n{\n   namespace rtl { namespace io { namespace file { namespace details\n   {\n      enum file_mode\n      {\n         e_error = 0,\n         e_read  = 1,\n         e_write = 2,\n         e_rdwrt = 4\n      };\n\n      struct file_descriptor\n      {\n         file_descriptor(const std::string& fname, const std::string& access)\n         : stream_ptr(0),\n           mode(get_file_mode(access)),\n           file_name(fname)\n         {}\n\n         void*       stream_ptr;\n         file_mode   mode;\n         std::string file_name;\n\n         bool open()\n         {\n            if (e_read == mode)\n            {\n               std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);\n\n               if (!(*stream))\n               {\n                  file_name.clear();\n                  delete stream;\n\n                  return false;\n               }\n               else\n                  stream_ptr = stream;\n\n               return true;\n            }\n            else if (e_write == mode)\n            {\n               std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);\n\n               if (!(*stream))\n               {\n                  file_name.clear();\n                  delete stream;\n\n                  return false;\n               }\n               else\n                  stream_ptr = stream;\n\n               return true;\n            }\n            else if (e_rdwrt == mode)\n            {\n               std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);\n\n               if (!(*stream))\n               {\n                  file_name.clear();\n                  delete stream;\n\n                  return false;\n               }\n               else\n                  stream_ptr = stream;\n\n               return true;\n            }\n            else\n               return false;\n         }\n\n         template <typename Stream, typename Ptr>\n         void close(Ptr& p)\n         {\n            Stream* stream = reinterpret_cast<Stream*>(p);\n            stream->close();\n            delete stream;\n            p = reinterpret_cast<Ptr>(0);\n         }\n\n         bool close()\n         {\n            switch (mode)\n            {\n               case e_read  : close<std::ifstream>(stream_ptr);\n                              break;\n\n               case e_write : close<std::ofstream>(stream_ptr);\n                              break;\n\n               case e_rdwrt : close<std::fstream> (stream_ptr);\n                              break;\n\n               default      : return false;\n            }\n\n            return true;\n         }\n\n         template <typename View>\n         bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)\n         {\n            switch (mode)\n            {\n               case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->\n                                 write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));\n                              break;\n\n               case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->\n                                 write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));\n                              break;\n\n               default      : return false;\n            }\n\n            return true;\n         }\n\n         template <typename View>\n         bool read(View& view, const std::size_t amount, const std::size_t offset = 0)\n         {\n            switch (mode)\n            {\n               case e_read  : reinterpret_cast<std::ifstream*>(stream_ptr)->\n                                 read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));\n                              break;\n\n               case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->\n                                 read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));\n                              break;\n\n               default      : return false;\n            }\n\n            return true;\n         }\n\n         bool getline(std::string& s)\n         {\n            switch (mode)\n            {\n               case e_read  : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));\n               case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));\n               default      : return false;\n            }\n         }\n\n         bool eof()\n         {\n            switch (mode)\n            {\n               case e_read  : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();\n               case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();\n               case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();\n               default      : return true;\n            }\n         }\n\n         file_mode get_file_mode(const std::string& access)\n         {\n            if (access.empty() || access.size() > 2)\n               return e_error;\n\n            std::size_t w_cnt = 0;\n            std::size_t r_cnt = 0;\n\n            for (std::size_t i = 0; i < access.size(); ++i)\n            {\n               switch (std::tolower(access[i]))\n               {\n                  case 'r' : r_cnt++; break;\n                  case 'w' : w_cnt++; break;\n                  default  : return e_error;\n               }\n            }\n\n            if ((0 == r_cnt) && (0 == w_cnt))\n               return e_error;\n            else if ((r_cnt > 1) || (w_cnt > 1))\n               return e_error;\n            else if ((1 == r_cnt) && (1 == w_cnt))\n               return e_rdwrt;\n            else if (1 == r_cnt)\n               return e_read;\n            else\n               return e_write;\n         }\n      };\n\n      template <typename T>\n      file_descriptor* make_handle(T v)\n      {\n         file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);\n\n         std::memcpy(reinterpret_cast<char*>(&fd),\n                     reinterpret_cast<const char*>(&v),\n                     sizeof(fd));\n         return fd;\n      }\n\n      template <typename T>\n      void perform_check()\n      {\n         #ifdef _MSC_VER\n         #pragma warning(push)\n         #pragma warning(disable: 4127)\n         #endif\n         if (sizeof(T) < sizeof(void*))\n         {\n            throw std::runtime_error(\"exprtk::rtl::io::file - Error - pointer size larger than holder.\");\n         }\n         #ifdef _MSC_VER\n         #pragma warning(pop)\n         #endif\n      }\n\n   } // namespace exprtk::rtl::io::file::details\n\n   template <typename T>\n   class open : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::string_view    string_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      open()\n      : exprtk::igeneric_function<T>(\"S|SS\")\n      { details::perform_check<T>(); }\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         std::string file_name;\n         std::string access;\n\n         file_name = to_str(string_t(parameters[0]));\n\n         if (file_name.empty())\n            return T(0);\n\n         if (0 == ps_index)\n            access = \"r\";\n         else if (0 == string_t(parameters[1]).size())\n            return T(0);\n         else\n            access = to_str(string_t(parameters[1]));\n\n         details::file_descriptor* fd = new details::file_descriptor(file_name,access);\n\n         if (fd->open())\n         {\n            T t = T(0);\n\n            std::memcpy(reinterpret_cast<char*>(&t ),\n                        reinterpret_cast<char*>(&fd),\n                        sizeof(fd));\n            return t;\n         }\n         else\n         {\n            delete fd;\n            return T(0);\n         }\n      }\n   };\n\n   template <typename T>\n   struct close : public exprtk::ifunction<T>\n   {\n      using exprtk::ifunction<T>::operator();\n\n      close()\n      : exprtk::ifunction<T>(1)\n      { details::perform_check<T>(); }\n\n      inline T operator() (const T& v)\n      {\n         details::file_descriptor* fd = details::make_handle(v);\n\n         if (!fd->close())\n            return T(0);\n\n         delete fd;\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class write : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::string_view    string_t;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      write()\n      : igfun_t(\"TS|TST|TV|TVT\")\n      { details::perform_check<T>(); }\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());\n\n         std::size_t amount = 0;\n\n         switch (ps_index)\n         {\n            case 0  : {\n                         const string_t buffer(parameters[1]);\n                         amount = buffer.size();\n                         return T(fd->write(buffer,amount) ? 1 : 0);\n                      }\n\n            case 1  : {\n                         const string_t buffer(parameters[1]);\n                         amount = std::min(buffer.size(),\n                                           static_cast<std::size_t>(scalar_t(parameters[2])()));\n                         return T(fd->write(buffer,amount) ? 1 : 0);\n                      }\n\n            case 2  : {\n                         const vector_t vec(parameters[1]);\n                         amount = vec.size();\n                         return T(fd->write(vec,amount) ? 1 : 0);\n                      }\n\n            case 3  : {\n                         const vector_t vec(parameters[1]);\n                         amount = std::min(vec.size(),\n                                           static_cast<std::size_t>(scalar_t(parameters[2])()));\n                         return T(fd->write(vec,amount) ? 1 : 0);\n                      }\n         }\n\n         return T(0);\n      }\n   };\n\n   template <typename T>\n   class read : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::string_view    string_t;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      read()\n      : igfun_t(\"TS|TST|TV|TVT\")\n      { details::perform_check<T>(); }\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());\n\n         std::size_t amount = 0;\n\n         switch (ps_index)\n         {\n            case 0  : {\n                         string_t buffer(parameters[1]);\n                         amount = buffer.size();\n                         return T(fd->read(buffer,amount) ? 1 : 0);\n                      }\n\n            case 1  : {\n                         string_t buffer(parameters[1]);\n                         amount = std::min(buffer.size(),\n                                           static_cast<std::size_t>(scalar_t(parameters[2])()));\n                         return T(fd->read(buffer,amount) ? 1 : 0);\n                      }\n\n            case 2  : {\n                         vector_t vec(parameters[1]);\n                         amount = vec.size();\n                         return T(fd->read(vec,amount) ? 1 : 0);\n                      }\n\n            case 3  : {\n                         vector_t vec(parameters[1]);\n                         amount = std::min(vec.size(),\n                                           static_cast<std::size_t>(scalar_t(parameters[2])()));\n                         return T(fd->read(vec,amount) ? 1 : 0);\n                      }\n         }\n\n         return T(0);\n      }\n   };\n\n   template <typename T>\n   class getline : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::string_view    string_t;\n      typedef typename generic_type::scalar_view    scalar_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      getline()\n      : igfun_t(\"T\",igfun_t::e_rtrn_string)\n      { details::perform_check<T>(); }\n\n      inline T operator() (std::string& result,\n                           parameter_list_t parameters)\n      {\n         details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());\n         return T(fd->getline(result) ? 1 : 0);\n      }\n   };\n\n   template <typename T>\n   struct eof : public exprtk::ifunction<T>\n   {\n      using exprtk::ifunction<T>::operator();\n\n      eof()\n      : exprtk::ifunction<T>(1)\n      { details::perform_check<T>(); }\n\n      inline T operator() (const T& v)\n      {\n         details::file_descriptor* fd = details::make_handle(v);\n\n         return (fd->eof() ? T(1) : T(0));\n      }\n   };\n\n   template <typename T>\n   struct package\n   {\n      open   <T> o;\n      close  <T> c;\n      write  <T> w;\n      read   <T> r;\n      getline<T> g;\n      eof    <T> e;\n\n      bool register_package(exprtk::symbol_table<T>& symtab)\n      {\n         #define exprtk_register_function(FunctionName,FunctionType)                    \\\n         if (!symtab.add_function(FunctionName,FunctionType))                           \\\n         {                                                                              \\\n            exprtk_debug((                                                              \\\n              \"exprtk::rtl::io::file::register_package - Failed to add function: %s\\n\", \\\n              FunctionName));                                                           \\\n            return false;                                                               \\\n         }                                                                              \\\n\n         exprtk_register_function(\"open\"   ,o)\n         exprtk_register_function(\"close\"  ,c)\n         exprtk_register_function(\"write\"  ,w)\n         exprtk_register_function(\"read\"   ,r)\n         exprtk_register_function(\"getline\",g)\n         exprtk_register_function(\"eof\"    ,e)\n         #undef exprtk_register_function\n\n         return true;\n      }\n   };\n\n   } // namespace exprtk::rtl::io::file\n   } // namespace exprtk::rtl::io\n   } // namespace exprtk::rtl\n}    // namespace exprtk\n#endif\n\n#ifndef exprtk_disable_rtl_vecops\nnamespace exprtk\n{\n   namespace rtl { namespace vecops {\n\n   namespace helper\n   {\n      template <typename Vector>\n      inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)\n      {\n         if (r0 > (v.size() - 1))\n            return true;\n         else if (r1 > (v.size() - 1))\n            return true;\n         else if (r1 < r0)\n            return true;\n         else\n            return false;\n      }\n\n      template <typename T>\n      struct load_vector_range\n      {\n         typedef typename exprtk::igeneric_function<T> igfun_t;\n         typedef typename igfun_t::parameter_list_t    parameter_list_t;\n         typedef typename igfun_t::generic_type        generic_type;\n         typedef typename generic_type::scalar_view    scalar_t;\n         typedef typename generic_type::vector_view    vector_t;\n\n         static inline bool process(parameter_list_t& parameters,\n                                    std::size_t& r0, std::size_t& r1,\n                                    const std::size_t& r0_prmidx,\n                                    const std::size_t& r1_prmidx,\n                                    const std::size_t vec_idx = 0)\n         {\n            if (r0_prmidx >= parameters.size())\n               return false;\n\n            if (r1_prmidx >= parameters.size())\n               return false;\n\n            if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))\n               return false;\n\n            if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))\n               return false;\n\n            return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);\n         }\n      };\n   }\n\n   namespace details\n   {\n      template <typename T>\n      inline void kahan_sum(T& sum, T& error, T v)\n      {\n         T x = v - error;\n         T y = sum + x;\n         error = (y - sum) - x;\n         sum = y;\n      }\n\n   } // namespace exprtk::rtl::details\n\n   template <typename T>\n   class all_true : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      all_true()\n      : exprtk::igeneric_function<T>(\"V|VTT\")\n        /*\n           Overloads:\n           0. V   - vector\n           1. VTT - vector, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)\n            )\n            return std::numeric_limits<T>::quiet_NaN();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            if (vec[i] == T(0))\n            {\n               return T(0);\n            }\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class all_false : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      all_false()\n      : exprtk::igeneric_function<T>(\"V|VTT\")\n        /*\n           Overloads:\n           0. V   - vector\n           1. VTT - vector, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)\n            )\n            return std::numeric_limits<T>::quiet_NaN();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            if (vec[i] != T(0))\n            {\n               return T(0);\n            }\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class any_true : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      any_true()\n      : exprtk::igeneric_function<T>(\"V|VTT\")\n        /*\n           Overloads:\n           0. V   - vector\n           1. VTT - vector, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)\n            )\n            return std::numeric_limits<T>::quiet_NaN();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            if (vec[i] != T(0))\n            {\n               return T(1);\n            }\n         }\n\n         return T(0);\n      }\n   };\n\n   template <typename T>\n   class any_false : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      any_false()\n      : exprtk::igeneric_function<T>(\"V|VTT\")\n        /*\n           Overloads:\n           0. V   - vector\n           1. VTT - vector, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)\n            )\n            return std::numeric_limits<T>::quiet_NaN();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            if (vec[i] == T(0))\n            {\n               return T(1);\n            }\n         }\n\n         return T(0);\n      }\n   };\n\n   template <typename T>\n   class count : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      count()\n      : exprtk::igeneric_function<T>(\"V|VTT\")\n        /*\n           Overloads:\n           0. V   - vector\n           1. VTT - vector, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)\n            )\n            return std::numeric_limits<T>::quiet_NaN();\n\n         std::size_t cnt = 0;\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            if (vec[i] != T(0)) ++cnt;\n         }\n\n         return T(cnt);\n      }\n   };\n\n   template <typename T>\n   class copy : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      copy()\n      : exprtk::igeneric_function<T>(\"VV|VTTVTT\")\n        /*\n           Overloads:\n           0. VV     - x(vector), y(vector)\n           1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[0]);\n               vector_t y(parameters[(0 == ps_index) ? 1 : 3]);\n\n         std::size_t xr0 = 0;\n         std::size_t xr1 = x.size() - 1;\n\n         std::size_t yr0 = 0;\n         std::size_t yr1 = y.size() - 1;\n\n         if (1 == ps_index)\n         {\n            if (\n                 !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||\n                 !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)\n               )\n               return T(0);\n         }\n\n         const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);\n\n         std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);\n\n         return T(n);\n      }\n   };\n\n   template <typename T>\n   class rol : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      rol()\n      : exprtk::igeneric_function<T>(\"VT|VTTT\")\n        /*\n           Overloads:\n           0. VT   - vector, N\n           1. VTTT - vector, N, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         std::size_t n  = 0;\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (!scalar_t(parameters[1]).to_uint(n))\n            return T(0);\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)\n            )\n            return T(0);\n\n         std::size_t dist  = r1 - r0 + 1;\n         std::size_t shift = n % dist;\n\n         std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class ror : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      ror()\n      : exprtk::igeneric_function<T>(\"VT|VTTT\")\n        /*\n           Overloads:\n           0. VT   - vector, N\n           1. VTTT - vector, N, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         std::size_t n  = 0;\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (!scalar_t(parameters[1]).to_uint(n))\n            return T(0);\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)\n            )\n            return T(0);\n\n         std::size_t dist  = r1 - r0 + 1;\n         std::size_t shift = (dist - (n % dist)) % dist;\n\n         std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class shift_left : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      shift_left()\n      : exprtk::igeneric_function<T>(\"VT|VTTT\")\n        /*\n           Overloads:\n           0. VT   - vector, N\n           1. VTTT - vector, N, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         std::size_t n  = 0;\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (!scalar_t(parameters[1]).to_uint(n))\n            return T(0);\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)\n            )\n            return T(0);\n\n         std::size_t dist  = r1 - r0 + 1;\n\n         if (n > dist)\n            return T(0);\n\n         std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);\n\n         for (std::size_t i = r1 - n + 1; i <= r1; ++i)\n         {\n            vec[i] = T(0);\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class shift_right : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      shift_right()\n      : exprtk::igeneric_function<T>(\"VT|VTTT\")\n        /*\n           Overloads:\n           0. VT   - vector, N\n           1. VTTT - vector, N, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         std::size_t n  = 0;\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (!scalar_t(parameters[1]).to_uint(n))\n            return T(0);\n\n         if (\n              (1 == ps_index) &&\n              !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)\n            )\n            return T(0);\n\n         std::size_t dist  = r1 - r0 + 1;\n\n         if (n > dist)\n            return T(0);\n\n         std::size_t shift = (dist - (n % dist)) % dist;\n\n         std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);\n\n         for (std::size_t i = r0; i < r0 + n; ++i)\n         {\n            vec[i] = T(0);\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class sort : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::string_view    string_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      sort()\n      : exprtk::igeneric_function<T>(\"V|VTT|VS|VSTT\")\n        /*\n           Overloads:\n           0. V    - vector\n           1. VTT  - vector, r0, r1\n           2. VS   - vector, string\n           3. VSTT - vector, string, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))\n            return T(0);\n         if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))\n            return T(0);\n\n         bool ascending = true;\n\n         if ((2 == ps_index) || (3 == ps_index))\n         {\n            if (exprtk::details::imatch(to_str(string_t(parameters[1])),\"ascending\"))\n               ascending = true;\n            else if (exprtk::details::imatch(to_str(string_t(parameters[1])),\"descending\"))\n               ascending = false;\n            else\n               return T(0);\n         }\n\n         if (ascending)\n            std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T>   ());\n         else\n            std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class nthelement : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      nthelement()\n      : exprtk::igeneric_function<T>(\"VT|VTTT\")\n        /*\n           Overloads:\n           0. VT   - vector, nth-element\n           1. VTTT - vector, nth-element, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         std::size_t n  = 0;\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if (!scalar_t(parameters[1]).to_uint(n))\n            return T(0);\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class iota : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      iota()\n      : exprtk::igeneric_function<T>(\"VT|VTT|VTTT|VTTTT\")\n        /*\n           Overloads:\n           0. VT    - vector, increment\n           1. VTT   - vector, increment, base\n           2. VTTTT - vector, increment, r0, r1\n           3. VTTTT - vector, increment, base, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         vector_t vec(parameters[0]);\n\n         T increment = scalar_t(parameters[1])();\n         T base      = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))\n            return std::numeric_limits<T>::quiet_NaN();\n         else\n         {\n            long long j = 0;\n\n            for (std::size_t i = r0; i <= r1; ++i, ++j)\n            {\n               vec[i] = base + (increment * j);\n            }\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class sumk : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      sumk()\n      : exprtk::igeneric_function<T>(\"V|VTT\")\n        /*\n           Overloads:\n           0. V   - vector\n           1. VTT - vector, r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t vec(parameters[0]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = vec.size() - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         T result = T(0);\n         T error  = T(0);\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            details::kahan_sum(result, error, vec[i]);\n         }\n\n         return result;\n      }\n   };\n\n   template <typename T>\n   class axpy : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      axpy()\n      : exprtk::igeneric_function<T>(\"TVV|TVVTT\")\n        /*\n           y <- ax + y\n           Overloads:\n           0. TVV   - a, x(vector), y(vector)\n           1. TVVTT - a, x(vector), y(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[1]);\n               vector_t y(parameters[2]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = std::min(x.size(),y.size()) - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(y,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         T a = scalar_t(parameters[0])();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            y[i] = (a * x[i]) + y[i];\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class axpby : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      axpby()\n      : exprtk::igeneric_function<T>(\"TVTV|TVTVTT\")\n        /*\n           y <- ax + by\n           Overloads:\n           0. TVTV   - a, x(vector), b, y(vector)\n           1. TVTVTT - a, x(vector), b, y(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[1]);\n               vector_t y(parameters[3]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = std::min(x.size(),y.size()) - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(y,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         const T a = scalar_t(parameters[0])();\n         const T b = scalar_t(parameters[2])();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            y[i] = (a * x[i]) + (b * y[i]);\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class axpyz : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      axpyz()\n      : exprtk::igeneric_function<T>(\"TVVV|TVVVTT\")\n        /*\n           z <- ax + y\n           Overloads:\n           0. TVVV   - a, x(vector), y(vector), z(vector)\n           1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[1]);\n         const vector_t y(parameters[2]);\n               vector_t z(parameters[3]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = std::min(x.size(),y.size()) - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(y,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(z,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         T a = scalar_t(parameters[0])();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            z[i] = (a * x[i]) + y[i];\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class axpbyz : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      axpbyz()\n      : exprtk::igeneric_function<T>(\"TVTVV|TVTVVTT\")\n        /*\n           z <- ax + by\n           Overloads:\n           0. TVTVV   - a, x(vector), b, y(vector), z(vector)\n           1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[1]);\n         const vector_t y(parameters[3]);\n               vector_t z(parameters[4]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = std::min(x.size(),y.size()) - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(y,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(z,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         const T a = scalar_t(parameters[0])();\n         const T b = scalar_t(parameters[2])();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            z[i] = (a * x[i]) + (b * y[i]);\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class axpbz : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      axpbz()\n      : exprtk::igeneric_function<T>(\"TVTV|TVTVTT\")\n        /*\n           z <- ax + b\n           Overloads:\n           0. TVTV   - a, x(vector), b, z(vector)\n           1. TVTVTT - a, x(vector), b, z(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[1]);\n               vector_t z(parameters[3]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = x.size() - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(z,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         const T a = scalar_t(parameters[0])();\n         const T b = scalar_t(parameters[2])();\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            z[i] = (a * x[i]) + b;\n         }\n\n         return T(1);\n      }\n   };\n\n   template <typename T>\n   class dot : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      dot()\n      : exprtk::igeneric_function<T>(\"VV|VVTT\")\n        /*\n           Overloads:\n           0. VV   - x(vector), y(vector)\n           1. VVTT - x(vector), y(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[0]);\n         const vector_t y(parameters[1]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = std::min(x.size(),y.size()) - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(y,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         T result = T(0);\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            result += (x[i] * y[i]);\n         }\n\n         return result;\n      }\n   };\n\n   template <typename T>\n   class dotk : public exprtk::igeneric_function<T>\n   {\n   public:\n\n      typedef typename exprtk::igeneric_function<T> igfun_t;\n      typedef typename igfun_t::parameter_list_t    parameter_list_t;\n      typedef typename igfun_t::generic_type        generic_type;\n      typedef typename generic_type::scalar_view    scalar_t;\n      typedef typename generic_type::vector_view    vector_t;\n\n      using exprtk::igeneric_function<T>::operator();\n\n      dotk()\n      : exprtk::igeneric_function<T>(\"VV|VVTT\")\n        /*\n           Overloads:\n           0. VV   - x(vector), y(vector)\n           1. VVTT - x(vector), y(vector), r0, r1\n        */\n      {}\n\n      inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)\n      {\n         const vector_t x(parameters[0]);\n         const vector_t y(parameters[1]);\n\n         std::size_t r0 = 0;\n         std::size_t r1 = std::min(x.size(),y.size()) - 1;\n\n         if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))\n            return std::numeric_limits<T>::quiet_NaN();\n         else if (helper::invalid_range(y,r0,r1))\n            return std::numeric_limits<T>::quiet_NaN();\n\n         T result = T(0);\n         T error  = T(0);\n\n         for (std::size_t i = r0; i <= r1; ++i)\n         {\n            details::kahan_sum(result, error, (x[i] * y[i]));\n         }\n\n         return result;\n      }\n   };\n\n   template <typename T>\n   struct package\n   {\n      all_true   <T> at;\n      all_false  <T> af;\n      any_true   <T> nt;\n      any_false  <T> nf;\n      count      <T>  c;\n      copy       <T> cp;\n      rol        <T> rl;\n      ror        <T> rr;\n      shift_left <T> sl;\n      shift_right<T> sr;\n      sort       <T> st;\n      nthelement <T> ne;\n      iota       <T> ia;\n      sumk       <T> sk;\n      axpy       <T> b1_axpy;\n      axpby      <T> b1_axpby;\n      axpyz      <T> b1_axpyz;\n      axpbyz     <T> b1_axpbyz;\n      axpbz      <T> b1_axpbz;\n      dot        <T> dt;\n      dotk       <T> dtk;\n\n      bool register_package(exprtk::symbol_table<T>& symtab)\n      {\n         #define exprtk_register_function(FunctionName,FunctionType)                  \\\n         if (!symtab.add_function(FunctionName,FunctionType))                         \\\n         {                                                                            \\\n            exprtk_debug((                                                            \\\n              \"exprtk::rtl::vecops::register_package - Failed to add function: %s\\n\", \\\n              FunctionName));                                                         \\\n            return false;                                                             \\\n         }                                                                            \\\n\n         exprtk_register_function(\"all_true\"     ,at)\n         exprtk_register_function(\"all_false\"    ,af)\n         exprtk_register_function(\"any_true\"     ,nt)\n         exprtk_register_function(\"any_false\"    ,nf)\n         exprtk_register_function(\"count\"        , c)\n         exprtk_register_function(\"copy\"        , cp)\n         exprtk_register_function(\"rotate_left\"  ,rl)\n         exprtk_register_function(\"rol\"          ,rl)\n         exprtk_register_function(\"rotate_right\" ,rr)\n         exprtk_register_function(\"ror\"          ,rr)\n         exprtk_register_function(\"shftl\"        ,sl)\n         exprtk_register_function(\"shftr\"        ,sr)\n         exprtk_register_function(\"sort\"         ,st)\n         exprtk_register_function(\"nth_element\"  ,ne)\n         exprtk_register_function(\"iota\"         ,ia)\n         exprtk_register_function(\"sumk\"         ,sk)\n         exprtk_register_function(\"axpy\"    ,b1_axpy)\n         exprtk_register_function(\"axpby\"  ,b1_axpby)\n         exprtk_register_function(\"axpyz\"  ,b1_axpyz)\n         exprtk_register_function(\"axpbyz\",b1_axpbyz)\n         exprtk_register_function(\"axpbz\"  ,b1_axpbz)\n         exprtk_register_function(\"dot\"          ,dt)\n         exprtk_register_function(\"dotk\"        ,dtk)\n         #undef exprtk_register_function\n\n         return true;\n      }\n   };\n\n   } // namespace exprtk::rtl::vecops\n   } // namespace exprtk::rtl\n}    // namespace exprtk\n#endif\n\nnamespace exprtk\n{\n   namespace information\n   {\n      static const char* library = \"Mathematical Expression Toolkit\";\n      static const char* version = \"2.71828182845904523536028747135266249775724709369\"\n                                   \"9959574966967627724076630353547594571382178525166\";\n      static const char* date    = \"20171111\";\n\n      static inline std::string data()\n      {\n         static const std::string info_str = std::string(library) +\n                                             std::string(\" v\") + std::string(version) +\n                                             std::string(\" (\") + date + std::string(\")\");\n         return info_str;\n      }\n\n   } // namespace information\n\n   #ifdef exprtk_debug\n   #undef exprtk_debug\n   #endif\n\n   #ifdef exprtk_error_location\n   #undef exprtk_error_location\n   #endif\n\n   #ifdef exprtk_disable_fallthrough_begin\n   #undef exprtk_disable_fallthrough_begin\n   #endif\n\n   #ifdef exprtk_disable_fallthrough_end\n   #undef exprtk_disable_fallthrough_end\n   #endif\n\n} // namespace exprtk\n\n#endif\n"
  },
  {
    "path": "3rdparty/exprtk/license/license.json",
    "content": "{\"Name\":\"The MIT License (MIT)\",\"Text\":\"Copyright (c) 1999 Arash Partow\\r\\n\\r\\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \\\"Software\\\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\\r\\n\\r\\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\\r\\n\\r\\nTHE SOFTWARE IS PROVIDED \\\"AS IS\\\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\",\"Id\":622575,\"ShortName\":\"MIT\",\"StartDate\":\"\\/Date(1487713546373-0800)\\/\"}"
  },
  {
    "path": "3rdparty/fastnoise/CMakeLists.txt",
    "content": "add_library(fastnoise)\n\ntarget_include_directories(fastnoise\n\tPUBLIC\n\t\t${CMAKE_CURRENT_SOURCE_DIR}\n)\n\ntarget_sources(fastnoise\n\tPRIVATE\n\t\tFastNoise.h\n\t\tFastNoise.cpp\n)\n"
  },
  {
    "path": "3rdparty/fastnoise/FastNoise.cpp",
    "content": "// FastNoise.cpp\r\n//\r\n// MIT License\r\n//\r\n// Copyright(c) 2017 Jordan Peck\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy\r\n// of this software and associated documentation files(the \"Software\"), to deal\r\n// in the Software without restriction, including without limitation the rights\r\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is\r\n// furnished to do so, subject to the following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all\r\n// copies or substantial portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n// SOFTWARE.\r\n//\r\n// The developer's email is jorzixdan.me2@gzixmail.com (for great email, take\r\n// off every 'zix'.)\r\n//\r\n\r\n#include \"FastNoise.h\"\r\n\r\n#include <algorithm>\r\n#include <assert.h>\r\n#include <math.h>\r\n#include <random>\r\n\r\nconst FN_DECIMAL GRAD_X[] = {\r\n\t1, -1, 1, -1,\r\n\t1, -1, 1, -1,\r\n\t0, 0, 0, 0\r\n};\r\nconst FN_DECIMAL GRAD_Y[] = {\r\n\t1, 1, -1, -1,\r\n\t0, 0, 0, 0,\r\n\t1, -1, 1, -1\r\n};\r\nconst FN_DECIMAL GRAD_Z[] = {\r\n\t0, 0, 0, 0,\r\n\t1, 1, -1, -1,\r\n\t1, 1, -1, -1\r\n};\r\n\r\nconst FN_DECIMAL GRAD_4D[] = {\r\n\t0, 1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1,\r\n\t0, -1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1,\r\n\t1, 0, 1, 1, 1, 0, 1, -1, 1, 0, -1, 1, 1, 0, -1, -1,\r\n\t-1, 0, 1, 1, -1, 0, 1, -1, -1, 0, -1, 1, -1, 0, -1, -1,\r\n\t1, 1, 0, 1, 1, 1, 0, -1, 1, -1, 0, 1, 1, -1, 0, -1,\r\n\t-1, 1, 0, 1, -1, 1, 0, -1, -1, -1, 0, 1, -1, -1, 0, -1,\r\n\t1, 1, 1, 0, 1, 1, -1, 0, 1, -1, 1, 0, 1, -1, -1, 0,\r\n\t-1, 1, 1, 0, -1, 1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 0\r\n};\r\n\r\nconst FN_DECIMAL VAL_LUT[] = {\r\n\tFN_DECIMAL( 0.3490196078 ),\r\n\tFN_DECIMAL( 0.4352941176 ),\r\n\tFN_DECIMAL( -0.4509803922 ),\r\n\tFN_DECIMAL( 0.6392156863 ),\r\n\tFN_DECIMAL( 0.5843137255 ),\r\n\tFN_DECIMAL( -0.1215686275 ),\r\n\tFN_DECIMAL( 0.7176470588 ),\r\n\tFN_DECIMAL( -0.1058823529 ),\r\n\tFN_DECIMAL( 0.3960784314 ),\r\n\tFN_DECIMAL( 0.0431372549 ),\r\n\tFN_DECIMAL( -0.03529411765 ),\r\n\tFN_DECIMAL( 0.3176470588 ),\r\n\tFN_DECIMAL( 0.7254901961 ),\r\n\tFN_DECIMAL( 0.137254902 ),\r\n\tFN_DECIMAL( 0.8588235294 ),\r\n\tFN_DECIMAL( -0.8196078431 ),\r\n\tFN_DECIMAL( -0.7960784314 ),\r\n\tFN_DECIMAL( -0.3333333333 ),\r\n\tFN_DECIMAL( -0.6705882353 ),\r\n\tFN_DECIMAL( -0.3882352941 ),\r\n\tFN_DECIMAL( 0.262745098 ),\r\n\tFN_DECIMAL( 0.3254901961 ),\r\n\tFN_DECIMAL( -0.6470588235 ),\r\n\tFN_DECIMAL( -0.9215686275 ),\r\n\tFN_DECIMAL( -0.5294117647 ),\r\n\tFN_DECIMAL( 0.5294117647 ),\r\n\tFN_DECIMAL( -0.4666666667 ),\r\n\tFN_DECIMAL( 0.8117647059 ),\r\n\tFN_DECIMAL( 0.3803921569 ),\r\n\tFN_DECIMAL( 0.662745098 ),\r\n\tFN_DECIMAL( 0.03529411765 ),\r\n\tFN_DECIMAL( -0.6156862745 ),\r\n\tFN_DECIMAL( -0.01960784314 ),\r\n\tFN_DECIMAL( -0.3568627451 ),\r\n\tFN_DECIMAL( -0.09019607843 ),\r\n\tFN_DECIMAL( 0.7490196078 ),\r\n\tFN_DECIMAL( 0.8352941176 ),\r\n\tFN_DECIMAL( -0.4039215686 ),\r\n\tFN_DECIMAL( -0.7490196078 ),\r\n\tFN_DECIMAL( 0.9529411765 ),\r\n\tFN_DECIMAL( -0.0431372549 ),\r\n\tFN_DECIMAL( -0.9294117647 ),\r\n\tFN_DECIMAL( -0.6549019608 ),\r\n\tFN_DECIMAL( 0.9215686275 ),\r\n\tFN_DECIMAL( -0.06666666667 ),\r\n\tFN_DECIMAL( -0.4431372549 ),\r\n\tFN_DECIMAL( 0.4117647059 ),\r\n\tFN_DECIMAL( -0.4196078431 ),\r\n\tFN_DECIMAL( -0.7176470588 ),\r\n\tFN_DECIMAL( -0.8117647059 ),\r\n\tFN_DECIMAL( -0.2549019608 ),\r\n\tFN_DECIMAL( 0.4901960784 ),\r\n\tFN_DECIMAL( 0.9137254902 ),\r\n\tFN_DECIMAL( 0.7882352941 ),\r\n\tFN_DECIMAL( -1.0 ),\r\n\tFN_DECIMAL( -0.4745098039 ),\r\n\tFN_DECIMAL( 0.7960784314 ),\r\n\tFN_DECIMAL( 0.8509803922 ),\r\n\tFN_DECIMAL( -0.6784313725 ),\r\n\tFN_DECIMAL( 0.4588235294 ),\r\n\tFN_DECIMAL( 1.0 ),\r\n\tFN_DECIMAL( -0.1843137255 ),\r\n\tFN_DECIMAL( 0.4509803922 ),\r\n\tFN_DECIMAL( 0.1450980392 ),\r\n\tFN_DECIMAL( -0.231372549 ),\r\n\tFN_DECIMAL( -0.968627451 ),\r\n\tFN_DECIMAL( -0.8588235294 ),\r\n\tFN_DECIMAL( 0.4274509804 ),\r\n\tFN_DECIMAL( 0.003921568627 ),\r\n\tFN_DECIMAL( -0.003921568627 ),\r\n\tFN_DECIMAL( 0.2156862745 ),\r\n\tFN_DECIMAL( 0.5058823529 ),\r\n\tFN_DECIMAL( 0.7647058824 ),\r\n\tFN_DECIMAL( 0.2078431373 ),\r\n\tFN_DECIMAL( -0.5921568627 ),\r\n\tFN_DECIMAL( 0.5764705882 ),\r\n\tFN_DECIMAL( -0.1921568627 ),\r\n\tFN_DECIMAL( -0.937254902 ),\r\n\tFN_DECIMAL( 0.08235294118 ),\r\n\tFN_DECIMAL( -0.08235294118 ),\r\n\tFN_DECIMAL( 0.9058823529 ),\r\n\tFN_DECIMAL( 0.8274509804 ),\r\n\tFN_DECIMAL( 0.02745098039 ),\r\n\tFN_DECIMAL( -0.168627451 ),\r\n\tFN_DECIMAL( -0.7803921569 ),\r\n\tFN_DECIMAL( 0.1137254902 ),\r\n\tFN_DECIMAL( -0.9450980392 ),\r\n\tFN_DECIMAL( 0.2 ),\r\n\tFN_DECIMAL( 0.01960784314 ),\r\n\tFN_DECIMAL( 0.5607843137 ),\r\n\tFN_DECIMAL( 0.2705882353 ),\r\n\tFN_DECIMAL( 0.4431372549 ),\r\n\tFN_DECIMAL( -0.9607843137 ),\r\n\tFN_DECIMAL( 0.6156862745 ),\r\n\tFN_DECIMAL( 0.9294117647 ),\r\n\tFN_DECIMAL( -0.07450980392 ),\r\n\tFN_DECIMAL( 0.3098039216 ),\r\n\tFN_DECIMAL( 0.9921568627 ),\r\n\tFN_DECIMAL( -0.9137254902 ),\r\n\tFN_DECIMAL( -0.2941176471 ),\r\n\tFN_DECIMAL( -0.3411764706 ),\r\n\tFN_DECIMAL( -0.6235294118 ),\r\n\tFN_DECIMAL( -0.7647058824 ),\r\n\tFN_DECIMAL( -0.8901960784 ),\r\n\tFN_DECIMAL( 0.05882352941 ),\r\n\tFN_DECIMAL( 0.2392156863 ),\r\n\tFN_DECIMAL( 0.7333333333 ),\r\n\tFN_DECIMAL( 0.6549019608 ),\r\n\tFN_DECIMAL( 0.2470588235 ),\r\n\tFN_DECIMAL( 0.231372549 ),\r\n\tFN_DECIMAL( -0.3960784314 ),\r\n\tFN_DECIMAL( -0.05098039216 ),\r\n\tFN_DECIMAL( -0.2235294118 ),\r\n\tFN_DECIMAL( -0.3725490196 ),\r\n\tFN_DECIMAL( 0.6235294118 ),\r\n\tFN_DECIMAL( 0.7019607843 ),\r\n\tFN_DECIMAL( -0.8274509804 ),\r\n\tFN_DECIMAL( 0.4196078431 ),\r\n\tFN_DECIMAL( 0.07450980392 ),\r\n\tFN_DECIMAL( 0.8666666667 ),\r\n\tFN_DECIMAL( -0.537254902 ),\r\n\tFN_DECIMAL( -0.5058823529 ),\r\n\tFN_DECIMAL( -0.8039215686 ),\r\n\tFN_DECIMAL( 0.09019607843 ),\r\n\tFN_DECIMAL( -0.4823529412 ),\r\n\tFN_DECIMAL( 0.6705882353 ),\r\n\tFN_DECIMAL( -0.7882352941 ),\r\n\tFN_DECIMAL( 0.09803921569 ),\r\n\tFN_DECIMAL( -0.6078431373 ),\r\n\tFN_DECIMAL( 0.8039215686 ),\r\n\tFN_DECIMAL( -0.6 ),\r\n\tFN_DECIMAL( -0.3254901961 ),\r\n\tFN_DECIMAL( -0.4117647059 ),\r\n\tFN_DECIMAL( -0.01176470588 ),\r\n\tFN_DECIMAL( 0.4823529412 ),\r\n\tFN_DECIMAL( 0.168627451 ),\r\n\tFN_DECIMAL( 0.8745098039 ),\r\n\tFN_DECIMAL( -0.3647058824 ),\r\n\tFN_DECIMAL( -0.1607843137 ),\r\n\tFN_DECIMAL( 0.568627451 ),\r\n\tFN_DECIMAL( -0.9921568627 ),\r\n\tFN_DECIMAL( 0.9450980392 ),\r\n\tFN_DECIMAL( 0.5137254902 ),\r\n\tFN_DECIMAL( 0.01176470588 ),\r\n\tFN_DECIMAL( -0.1450980392 ),\r\n\tFN_DECIMAL( -0.5529411765 ),\r\n\tFN_DECIMAL( -0.5764705882 ),\r\n\tFN_DECIMAL( -0.1137254902 ),\r\n\tFN_DECIMAL( 0.5215686275 ),\r\n\tFN_DECIMAL( 0.1607843137 ),\r\n\tFN_DECIMAL( 0.3725490196 ),\r\n\tFN_DECIMAL( -0.2 ),\r\n\tFN_DECIMAL( -0.7254901961 ),\r\n\tFN_DECIMAL( 0.631372549 ),\r\n\tFN_DECIMAL( 0.7098039216 ),\r\n\tFN_DECIMAL( -0.568627451 ),\r\n\tFN_DECIMAL( 0.1294117647 ),\r\n\tFN_DECIMAL( -0.3098039216 ),\r\n\tFN_DECIMAL( 0.7411764706 ),\r\n\tFN_DECIMAL( -0.8509803922 ),\r\n\tFN_DECIMAL( 0.2549019608 ),\r\n\tFN_DECIMAL( -0.6392156863 ),\r\n\tFN_DECIMAL( -0.5607843137 ),\r\n\tFN_DECIMAL( -0.3176470588 ),\r\n\tFN_DECIMAL( 0.937254902 ),\r\n\tFN_DECIMAL( 0.9843137255 ),\r\n\tFN_DECIMAL( 0.5921568627 ),\r\n\tFN_DECIMAL( 0.6941176471 ),\r\n\tFN_DECIMAL( 0.2862745098 ),\r\n\tFN_DECIMAL( -0.5215686275 ),\r\n\tFN_DECIMAL( 0.1764705882 ),\r\n\tFN_DECIMAL( 0.537254902 ),\r\n\tFN_DECIMAL( -0.4901960784 ),\r\n\tFN_DECIMAL( -0.4588235294 ),\r\n\tFN_DECIMAL( -0.2078431373 ),\r\n\tFN_DECIMAL( -0.2156862745 ),\r\n\tFN_DECIMAL( 0.7725490196 ),\r\n\tFN_DECIMAL( 0.3647058824 ),\r\n\tFN_DECIMAL( -0.2392156863 ),\r\n\tFN_DECIMAL( 0.2784313725 ),\r\n\tFN_DECIMAL( -0.8823529412 ),\r\n\tFN_DECIMAL( 0.8980392157 ),\r\n\tFN_DECIMAL( 0.1215686275 ),\r\n\tFN_DECIMAL( 0.1058823529 ),\r\n\tFN_DECIMAL( -0.8745098039 ),\r\n\tFN_DECIMAL( -0.9843137255 ),\r\n\tFN_DECIMAL( -0.7019607843 ),\r\n\tFN_DECIMAL( 0.9607843137 ),\r\n\tFN_DECIMAL( 0.2941176471 ),\r\n\tFN_DECIMAL( 0.3411764706 ),\r\n\tFN_DECIMAL( 0.1529411765 ),\r\n\tFN_DECIMAL( 0.06666666667 ),\r\n\tFN_DECIMAL( -0.9764705882 ),\r\n\tFN_DECIMAL( 0.3019607843 ),\r\n\tFN_DECIMAL( 0.6470588235 ),\r\n\tFN_DECIMAL( -0.5843137255 ),\r\n\tFN_DECIMAL( 0.05098039216 ),\r\n\tFN_DECIMAL( -0.5137254902 ),\r\n\tFN_DECIMAL( -0.137254902 ),\r\n\tFN_DECIMAL( 0.3882352941 ),\r\n\tFN_DECIMAL( -0.262745098 ),\r\n\tFN_DECIMAL( -0.3019607843 ),\r\n\tFN_DECIMAL( -0.1764705882 ),\r\n\tFN_DECIMAL( -0.7568627451 ),\r\n\tFN_DECIMAL( 0.1843137255 ),\r\n\tFN_DECIMAL( -0.5450980392 ),\r\n\tFN_DECIMAL( -0.4980392157 ),\r\n\tFN_DECIMAL( -0.2784313725 ),\r\n\tFN_DECIMAL( -0.9529411765 ),\r\n\tFN_DECIMAL( -0.09803921569 ),\r\n\tFN_DECIMAL( 0.8901960784 ),\r\n\tFN_DECIMAL( -0.2862745098 ),\r\n\tFN_DECIMAL( -0.3803921569 ),\r\n\tFN_DECIMAL( 0.5529411765 ),\r\n\tFN_DECIMAL( 0.7803921569 ),\r\n\tFN_DECIMAL( -0.8352941176 ),\r\n\tFN_DECIMAL( 0.6862745098 ),\r\n\tFN_DECIMAL( 0.7568627451 ),\r\n\tFN_DECIMAL( 0.4980392157 ),\r\n\tFN_DECIMAL( -0.6862745098 ),\r\n\tFN_DECIMAL( -0.8980392157 ),\r\n\tFN_DECIMAL( -0.7725490196 ),\r\n\tFN_DECIMAL( -0.7098039216 ),\r\n\tFN_DECIMAL( -0.2470588235 ),\r\n\tFN_DECIMAL( -0.9058823529 ),\r\n\tFN_DECIMAL( 0.9764705882 ),\r\n\tFN_DECIMAL( 0.1921568627 ),\r\n\tFN_DECIMAL( 0.8431372549 ),\r\n\tFN_DECIMAL( -0.05882352941 ),\r\n\tFN_DECIMAL( 0.3568627451 ),\r\n\tFN_DECIMAL( 0.6078431373 ),\r\n\tFN_DECIMAL( 0.5450980392 ),\r\n\tFN_DECIMAL( 0.4039215686 ),\r\n\tFN_DECIMAL( -0.7333333333 ),\r\n\tFN_DECIMAL( -0.4274509804 ),\r\n\tFN_DECIMAL( 0.6 ),\r\n\tFN_DECIMAL( 0.6784313725 ),\r\n\tFN_DECIMAL( -0.631372549 ),\r\n\tFN_DECIMAL( -0.02745098039 ),\r\n\tFN_DECIMAL( -0.1294117647 ),\r\n\tFN_DECIMAL( 0.3333333333 ),\r\n\tFN_DECIMAL( -0.8431372549 ),\r\n\tFN_DECIMAL( 0.2235294118 ),\r\n\tFN_DECIMAL( -0.3490196078 ),\r\n\tFN_DECIMAL( -0.6941176471 ),\r\n\tFN_DECIMAL( 0.8823529412 ),\r\n\tFN_DECIMAL( 0.4745098039 ),\r\n\tFN_DECIMAL( 0.4666666667 ),\r\n\tFN_DECIMAL( -0.7411764706 ),\r\n\tFN_DECIMAL( -0.2705882353 ),\r\n\tFN_DECIMAL( 0.968627451 ),\r\n\tFN_DECIMAL( 0.8196078431 ),\r\n\tFN_DECIMAL( -0.662745098 ),\r\n\tFN_DECIMAL( -0.4352941176 ),\r\n\tFN_DECIMAL( -0.8666666667 ),\r\n\tFN_DECIMAL( -0.1529411765 ),\r\n};\r\n\r\nconst FN_DECIMAL CELL_2D_X[] = {\r\n\tFN_DECIMAL( -0.6440658039 ),\r\n\tFN_DECIMAL( -0.08028078721 ),\r\n\tFN_DECIMAL( 0.9983546168 ),\r\n\tFN_DECIMAL( 0.9869492062 ),\r\n\tFN_DECIMAL( 0.9284746418 ),\r\n\tFN_DECIMAL( 0.6051097552 ),\r\n\tFN_DECIMAL( -0.794167404 ),\r\n\tFN_DECIMAL( -0.3488667991 ),\r\n\tFN_DECIMAL( -0.943136526 ),\r\n\tFN_DECIMAL( -0.9968171318 ),\r\n\tFN_DECIMAL( 0.8740961579 ),\r\n\tFN_DECIMAL( 0.1421139764 ),\r\n\tFN_DECIMAL( 0.4282553608 ),\r\n\tFN_DECIMAL( -0.9986665833 ),\r\n\tFN_DECIMAL( 0.9996760121 ),\r\n\tFN_DECIMAL( -0.06248383632 ),\r\n\tFN_DECIMAL( 0.7120139305 ),\r\n\tFN_DECIMAL( 0.8917660409 ),\r\n\tFN_DECIMAL( 0.1094842955 ),\r\n\tFN_DECIMAL( -0.8730880804 ),\r\n\tFN_DECIMAL( 0.2594811489 ),\r\n\tFN_DECIMAL( -0.6690063346 ),\r\n\tFN_DECIMAL( -0.9996834972 ),\r\n\tFN_DECIMAL( -0.8803608671 ),\r\n\tFN_DECIMAL( -0.8166554937 ),\r\n\tFN_DECIMAL( 0.8955599676 ),\r\n\tFN_DECIMAL( -0.9398321388 ),\r\n\tFN_DECIMAL( 0.07615451399 ),\r\n\tFN_DECIMAL( -0.7147270565 ),\r\n\tFN_DECIMAL( 0.8707354457 ),\r\n\tFN_DECIMAL( -0.9580008579 ),\r\n\tFN_DECIMAL( 0.4905965632 ),\r\n\tFN_DECIMAL( 0.786775944 ),\r\n\tFN_DECIMAL( 0.1079711577 ),\r\n\tFN_DECIMAL( 0.2686638979 ),\r\n\tFN_DECIMAL( 0.6113487322 ),\r\n\tFN_DECIMAL( -0.530770584 ),\r\n\tFN_DECIMAL( -0.7837268286 ),\r\n\tFN_DECIMAL( -0.8558691039 ),\r\n\tFN_DECIMAL( -0.5726093896 ),\r\n\tFN_DECIMAL( -0.9830740914 ),\r\n\tFN_DECIMAL( 0.7087766359 ),\r\n\tFN_DECIMAL( 0.6807027153 ),\r\n\tFN_DECIMAL( -0.08864708788 ),\r\n\tFN_DECIMAL( 0.6704485923 ),\r\n\tFN_DECIMAL( -0.1350735482 ),\r\n\tFN_DECIMAL( -0.9381333003 ),\r\n\tFN_DECIMAL( 0.9756655376 ),\r\n\tFN_DECIMAL( 0.4231433671 ),\r\n\tFN_DECIMAL( -0.4959787385 ),\r\n\tFN_DECIMAL( 0.1005554325 ),\r\n\tFN_DECIMAL( -0.7645857281 ),\r\n\tFN_DECIMAL( -0.5859053796 ),\r\n\tFN_DECIMAL( -0.9751154306 ),\r\n\tFN_DECIMAL( -0.6972258572 ),\r\n\tFN_DECIMAL( 0.7907012002 ),\r\n\tFN_DECIMAL( -0.9109899213 ),\r\n\tFN_DECIMAL( -0.9584307894 ),\r\n\tFN_DECIMAL( -0.8269529333 ),\r\n\tFN_DECIMAL( 0.2608264719 ),\r\n\tFN_DECIMAL( -0.7773760119 ),\r\n\tFN_DECIMAL( 0.7606456974 ),\r\n\tFN_DECIMAL( -0.8961083758 ),\r\n\tFN_DECIMAL( -0.9838134719 ),\r\n\tFN_DECIMAL( 0.7338893576 ),\r\n\tFN_DECIMAL( 0.2161226729 ),\r\n\tFN_DECIMAL( 0.673509891 ),\r\n\tFN_DECIMAL( -0.5512056873 ),\r\n\tFN_DECIMAL( 0.6899744332 ),\r\n\tFN_DECIMAL( 0.868004831 ),\r\n\tFN_DECIMAL( 0.5897430311 ),\r\n\tFN_DECIMAL( -0.8950444221 ),\r\n\tFN_DECIMAL( -0.3595752773 ),\r\n\tFN_DECIMAL( 0.8209486981 ),\r\n\tFN_DECIMAL( -0.2912360132 ),\r\n\tFN_DECIMAL( -0.9965011374 ),\r\n\tFN_DECIMAL( 0.9766994634 ),\r\n\tFN_DECIMAL( 0.738790822 ),\r\n\tFN_DECIMAL( -0.4730947722 ),\r\n\tFN_DECIMAL( 0.8946479441 ),\r\n\tFN_DECIMAL( -0.6943628971 ),\r\n\tFN_DECIMAL( -0.6620468182 ),\r\n\tFN_DECIMAL( -0.0887255502 ),\r\n\tFN_DECIMAL( -0.7512250855 ),\r\n\tFN_DECIMAL( -0.5322986898 ),\r\n\tFN_DECIMAL( 0.5226295385 ),\r\n\tFN_DECIMAL( 0.2296318375 ),\r\n\tFN_DECIMAL( 0.7915307344 ),\r\n\tFN_DECIMAL( -0.2756485999 ),\r\n\tFN_DECIMAL( -0.6900234522 ),\r\n\tFN_DECIMAL( 0.07090588086 ),\r\n\tFN_DECIMAL( 0.5981278485 ),\r\n\tFN_DECIMAL( 0.3033429312 ),\r\n\tFN_DECIMAL( -0.7253142797 ),\r\n\tFN_DECIMAL( -0.9855874307 ),\r\n\tFN_DECIMAL( -0.1761843396 ),\r\n\tFN_DECIMAL( -0.6438468325 ),\r\n\tFN_DECIMAL( -0.9956136595 ),\r\n\tFN_DECIMAL( 0.8541580762 ),\r\n\tFN_DECIMAL( -0.9999807666 ),\r\n\tFN_DECIMAL( -0.02152416253 ),\r\n\tFN_DECIMAL( -0.8705983095 ),\r\n\tFN_DECIMAL( -0.1197138014 ),\r\n\tFN_DECIMAL( -0.992107781 ),\r\n\tFN_DECIMAL( -0.9091181546 ),\r\n\tFN_DECIMAL( 0.788610536 ),\r\n\tFN_DECIMAL( -0.994636402 ),\r\n\tFN_DECIMAL( 0.4211256853 ),\r\n\tFN_DECIMAL( 0.3110430857 ),\r\n\tFN_DECIMAL( -0.4031127839 ),\r\n\tFN_DECIMAL( 0.7610684239 ),\r\n\tFN_DECIMAL( 0.7685674467 ),\r\n\tFN_DECIMAL( 0.152271555 ),\r\n\tFN_DECIMAL( -0.9364648723 ),\r\n\tFN_DECIMAL( 0.1681333739 ),\r\n\tFN_DECIMAL( -0.3567427907 ),\r\n\tFN_DECIMAL( -0.418445483 ),\r\n\tFN_DECIMAL( -0.98774778 ),\r\n\tFN_DECIMAL( 0.8705250765 ),\r\n\tFN_DECIMAL( -0.8911701067 ),\r\n\tFN_DECIMAL( -0.7315350966 ),\r\n\tFN_DECIMAL( 0.6030885658 ),\r\n\tFN_DECIMAL( -0.4149130821 ),\r\n\tFN_DECIMAL( 0.7585339481 ),\r\n\tFN_DECIMAL( 0.6963196535 ),\r\n\tFN_DECIMAL( 0.8332685012 ),\r\n\tFN_DECIMAL( -0.8086815232 ),\r\n\tFN_DECIMAL( 0.7518116724 ),\r\n\tFN_DECIMAL( -0.3490535894 ),\r\n\tFN_DECIMAL( 0.6972110903 ),\r\n\tFN_DECIMAL( -0.8795676928 ),\r\n\tFN_DECIMAL( -0.6442331882 ),\r\n\tFN_DECIMAL( 0.6610236811 ),\r\n\tFN_DECIMAL( -0.9853565782 ),\r\n\tFN_DECIMAL( -0.590338458 ),\r\n\tFN_DECIMAL( 0.09843602117 ),\r\n\tFN_DECIMAL( 0.5646534882 ),\r\n\tFN_DECIMAL( -0.6023259233 ),\r\n\tFN_DECIMAL( -0.3539248861 ),\r\n\tFN_DECIMAL( 0.5132728656 ),\r\n\tFN_DECIMAL( 0.9380385118 ),\r\n\tFN_DECIMAL( -0.7599270056 ),\r\n\tFN_DECIMAL( -0.7425936564 ),\r\n\tFN_DECIMAL( -0.6679610562 ),\r\n\tFN_DECIMAL( -0.3018497816 ),\r\n\tFN_DECIMAL( 0.814478266 ),\r\n\tFN_DECIMAL( 0.03777430269 ),\r\n\tFN_DECIMAL( -0.7514235086 ),\r\n\tFN_DECIMAL( 0.9662556939 ),\r\n\tFN_DECIMAL( -0.4720194901 ),\r\n\tFN_DECIMAL( -0.435054126 ),\r\n\tFN_DECIMAL( 0.7091901235 ),\r\n\tFN_DECIMAL( 0.929379209 ),\r\n\tFN_DECIMAL( 0.9997434357 ),\r\n\tFN_DECIMAL( 0.8306320299 ),\r\n\tFN_DECIMAL( -0.9434019629 ),\r\n\tFN_DECIMAL( -0.133133759 ),\r\n\tFN_DECIMAL( 0.5048413216 ),\r\n\tFN_DECIMAL( 0.3711995273 ),\r\n\tFN_DECIMAL( 0.98552091 ),\r\n\tFN_DECIMAL( 0.7401857005 ),\r\n\tFN_DECIMAL( -0.9999981398 ),\r\n\tFN_DECIMAL( -0.2144033253 ),\r\n\tFN_DECIMAL( 0.4808624681 ),\r\n\tFN_DECIMAL( -0.413835885 ),\r\n\tFN_DECIMAL( 0.644229305 ),\r\n\tFN_DECIMAL( 0.9626648696 ),\r\n\tFN_DECIMAL( 0.1833665934 ),\r\n\tFN_DECIMAL( 0.5794129 ),\r\n\tFN_DECIMAL( 0.01404446873 ),\r\n\tFN_DECIMAL( 0.4388494993 ),\r\n\tFN_DECIMAL( 0.5213612322 ),\r\n\tFN_DECIMAL( -0.5281609948 ),\r\n\tFN_DECIMAL( -0.9745306846 ),\r\n\tFN_DECIMAL( -0.9904373013 ),\r\n\tFN_DECIMAL( 0.9100232252 ),\r\n\tFN_DECIMAL( -0.9914057719 ),\r\n\tFN_DECIMAL( 0.7892627765 ),\r\n\tFN_DECIMAL( 0.3364421659 ),\r\n\tFN_DECIMAL( -0.9416099764 ),\r\n\tFN_DECIMAL( 0.7802732656 ),\r\n\tFN_DECIMAL( 0.886302871 ),\r\n\tFN_DECIMAL( 0.6524471291 ),\r\n\tFN_DECIMAL( 0.5762186726 ),\r\n\tFN_DECIMAL( -0.08987644664 ),\r\n\tFN_DECIMAL( -0.2177026782 ),\r\n\tFN_DECIMAL( -0.9720345052 ),\r\n\tFN_DECIMAL( -0.05722538858 ),\r\n\tFN_DECIMAL( 0.8105983127 ),\r\n\tFN_DECIMAL( 0.3410261032 ),\r\n\tFN_DECIMAL( 0.6452309645 ),\r\n\tFN_DECIMAL( -0.7810612152 ),\r\n\tFN_DECIMAL( 0.9989395718 ),\r\n\tFN_DECIMAL( -0.808247815 ),\r\n\tFN_DECIMAL( 0.6370177929 ),\r\n\tFN_DECIMAL( 0.5844658772 ),\r\n\tFN_DECIMAL( 0.2054070861 ),\r\n\tFN_DECIMAL( 0.055960522 ),\r\n\tFN_DECIMAL( -0.995827561 ),\r\n\tFN_DECIMAL( 0.893409165 ),\r\n\tFN_DECIMAL( -0.931516824 ),\r\n\tFN_DECIMAL( 0.328969469 ),\r\n\tFN_DECIMAL( -0.3193837488 ),\r\n\tFN_DECIMAL( 0.7314755657 ),\r\n\tFN_DECIMAL( -0.7913517714 ),\r\n\tFN_DECIMAL( -0.2204109786 ),\r\n\tFN_DECIMAL( 0.9955900414 ),\r\n\tFN_DECIMAL( -0.7112353139 ),\r\n\tFN_DECIMAL( -0.7935008741 ),\r\n\tFN_DECIMAL( -0.9961918204 ),\r\n\tFN_DECIMAL( -0.9714163995 ),\r\n\tFN_DECIMAL( -0.9566188669 ),\r\n\tFN_DECIMAL( 0.2748495632 ),\r\n\tFN_DECIMAL( -0.4681743221 ),\r\n\tFN_DECIMAL( -0.9614449642 ),\r\n\tFN_DECIMAL( 0.585194072 ),\r\n\tFN_DECIMAL( 0.4532946061 ),\r\n\tFN_DECIMAL( -0.9916113176 ),\r\n\tFN_DECIMAL( 0.942479587 ),\r\n\tFN_DECIMAL( -0.9813704753 ),\r\n\tFN_DECIMAL( -0.6538429571 ),\r\n\tFN_DECIMAL( 0.2923335053 ),\r\n\tFN_DECIMAL( -0.2246660704 ),\r\n\tFN_DECIMAL( -0.1800781949 ),\r\n\tFN_DECIMAL( -0.9581216256 ),\r\n\tFN_DECIMAL( 0.552215082 ),\r\n\tFN_DECIMAL( -0.9296791922 ),\r\n\tFN_DECIMAL( 0.643183699 ),\r\n\tFN_DECIMAL( 0.9997325981 ),\r\n\tFN_DECIMAL( -0.4606920354 ),\r\n\tFN_DECIMAL( -0.2148721265 ),\r\n\tFN_DECIMAL( 0.3482070809 ),\r\n\tFN_DECIMAL( 0.3075517813 ),\r\n\tFN_DECIMAL( 0.6274756393 ),\r\n\tFN_DECIMAL( 0.8910881765 ),\r\n\tFN_DECIMAL( -0.6397771309 ),\r\n\tFN_DECIMAL( -0.4479080125 ),\r\n\tFN_DECIMAL( -0.5247665011 ),\r\n\tFN_DECIMAL( -0.8386507094 ),\r\n\tFN_DECIMAL( 0.3901291416 ),\r\n\tFN_DECIMAL( 0.1458336921 ),\r\n\tFN_DECIMAL( 0.01624613149 ),\r\n\tFN_DECIMAL( -0.8273199879 ),\r\n\tFN_DECIMAL( 0.5611100679 ),\r\n\tFN_DECIMAL( -0.8380219841 ),\r\n\tFN_DECIMAL( -0.9856122234 ),\r\n\tFN_DECIMAL( -0.861398618 ),\r\n\tFN_DECIMAL( 0.6398413916 ),\r\n\tFN_DECIMAL( 0.2694510795 ),\r\n\tFN_DECIMAL( 0.4327334514 ),\r\n\tFN_DECIMAL( -0.9960265354 ),\r\n\tFN_DECIMAL( -0.939570655 ),\r\n\tFN_DECIMAL( -0.8846996446 ),\r\n\tFN_DECIMAL( 0.7642113189 ),\r\n\tFN_DECIMAL( -0.7002080528 ),\r\n\tFN_DECIMAL( 0.664508256 ),\r\n};\r\nconst FN_DECIMAL CELL_2D_Y[] = {\r\n\tFN_DECIMAL( 0.7649700911 ),\r\n\tFN_DECIMAL( 0.9967722885 ),\r\n\tFN_DECIMAL( 0.05734160033 ),\r\n\tFN_DECIMAL( -0.1610318741 ),\r\n\tFN_DECIMAL( 0.371395799 ),\r\n\tFN_DECIMAL( -0.7961420628 ),\r\n\tFN_DECIMAL( 0.6076990492 ),\r\n\tFN_DECIMAL( -0.9371723195 ),\r\n\tFN_DECIMAL( 0.3324056156 ),\r\n\tFN_DECIMAL( 0.07972205329 ),\r\n\tFN_DECIMAL( -0.4857529277 ),\r\n\tFN_DECIMAL( -0.9898503007 ),\r\n\tFN_DECIMAL( 0.9036577593 ),\r\n\tFN_DECIMAL( 0.05162417479 ),\r\n\tFN_DECIMAL( -0.02545330525 ),\r\n\tFN_DECIMAL( -0.998045976 ),\r\n\tFN_DECIMAL( -0.7021653386 ),\r\n\tFN_DECIMAL( -0.4524967717 ),\r\n\tFN_DECIMAL( -0.9939885256 ),\r\n\tFN_DECIMAL( -0.4875625128 ),\r\n\tFN_DECIMAL( -0.9657481729 ),\r\n\tFN_DECIMAL( -0.7432567015 ),\r\n\tFN_DECIMAL( 0.02515761212 ),\r\n\tFN_DECIMAL( 0.4743044842 ),\r\n\tFN_DECIMAL( 0.5771254669 ),\r\n\tFN_DECIMAL( 0.4449408324 ),\r\n\tFN_DECIMAL( 0.3416365773 ),\r\n\tFN_DECIMAL( 0.9970960285 ),\r\n\tFN_DECIMAL( 0.6994034849 ),\r\n\tFN_DECIMAL( 0.4917517499 ),\r\n\tFN_DECIMAL( 0.286765333 ),\r\n\tFN_DECIMAL( 0.8713868327 ),\r\n\tFN_DECIMAL( 0.6172387009 ),\r\n\tFN_DECIMAL( 0.9941540269 ),\r\n\tFN_DECIMAL( 0.9632339851 ),\r\n\tFN_DECIMAL( -0.7913613129 ),\r\n\tFN_DECIMAL( 0.847515538 ),\r\n\tFN_DECIMAL( 0.6211056739 ),\r\n\tFN_DECIMAL( 0.5171924952 ),\r\n\tFN_DECIMAL( -0.8198283277 ),\r\n\tFN_DECIMAL( -0.1832084353 ),\r\n\tFN_DECIMAL( 0.7054329737 ),\r\n\tFN_DECIMAL( 0.7325597678 ),\r\n\tFN_DECIMAL( 0.9960630973 ),\r\n\tFN_DECIMAL( 0.7419559859 ),\r\n\tFN_DECIMAL( 0.9908355749 ),\r\n\tFN_DECIMAL( -0.346274329 ),\r\n\tFN_DECIMAL( 0.2192641299 ),\r\n\tFN_DECIMAL( -0.9060627411 ),\r\n\tFN_DECIMAL( -0.8683346653 ),\r\n\tFN_DECIMAL( 0.9949314574 ),\r\n\tFN_DECIMAL( -0.6445220433 ),\r\n\tFN_DECIMAL( -0.8103794704 ),\r\n\tFN_DECIMAL( -0.2216977607 ),\r\n\tFN_DECIMAL( 0.7168515217 ),\r\n\tFN_DECIMAL( 0.612202264 ),\r\n\tFN_DECIMAL( -0.412428616 ),\r\n\tFN_DECIMAL( 0.285325116 ),\r\n\tFN_DECIMAL( 0.56227115 ),\r\n\tFN_DECIMAL( -0.9653857009 ),\r\n\tFN_DECIMAL( -0.6290361962 ),\r\n\tFN_DECIMAL( 0.6491672535 ),\r\n\tFN_DECIMAL( 0.443835306 ),\r\n\tFN_DECIMAL( -0.1791955706 ),\r\n\tFN_DECIMAL( -0.6792690269 ),\r\n\tFN_DECIMAL( -0.9763662173 ),\r\n\tFN_DECIMAL( 0.7391782104 ),\r\n\tFN_DECIMAL( 0.8343693968 ),\r\n\tFN_DECIMAL( 0.7238337389 ),\r\n\tFN_DECIMAL( 0.4965557504 ),\r\n\tFN_DECIMAL( 0.8075909592 ),\r\n\tFN_DECIMAL( -0.4459769977 ),\r\n\tFN_DECIMAL( -0.9331160806 ),\r\n\tFN_DECIMAL( -0.5710019572 ),\r\n\tFN_DECIMAL( 0.9566512346 ),\r\n\tFN_DECIMAL( -0.08357920318 ),\r\n\tFN_DECIMAL( 0.2146116448 ),\r\n\tFN_DECIMAL( -0.6739348049 ),\r\n\tFN_DECIMAL( 0.8810115417 ),\r\n\tFN_DECIMAL( 0.4467718167 ),\r\n\tFN_DECIMAL( -0.7196250184 ),\r\n\tFN_DECIMAL( -0.749462481 ),\r\n\tFN_DECIMAL( 0.9960561112 ),\r\n\tFN_DECIMAL( 0.6600461127 ),\r\n\tFN_DECIMAL( -0.8465566164 ),\r\n\tFN_DECIMAL( -0.8525598897 ),\r\n\tFN_DECIMAL( -0.9732775654 ),\r\n\tFN_DECIMAL( 0.6111293616 ),\r\n\tFN_DECIMAL( -0.9612584717 ),\r\n\tFN_DECIMAL( -0.7237870097 ),\r\n\tFN_DECIMAL( -0.9974830104 ),\r\n\tFN_DECIMAL( -0.8014006968 ),\r\n\tFN_DECIMAL( 0.9528814544 ),\r\n\tFN_DECIMAL( -0.6884178931 ),\r\n\tFN_DECIMAL( -0.1691668301 ),\r\n\tFN_DECIMAL( 0.9843571905 ),\r\n\tFN_DECIMAL( 0.7651544003 ),\r\n\tFN_DECIMAL( -0.09355982605 ),\r\n\tFN_DECIMAL( -0.5200134429 ),\r\n\tFN_DECIMAL( -0.006202125807 ),\r\n\tFN_DECIMAL( -0.9997683284 ),\r\n\tFN_DECIMAL( 0.4919944954 ),\r\n\tFN_DECIMAL( -0.9928084436 ),\r\n\tFN_DECIMAL( -0.1253880012 ),\r\n\tFN_DECIMAL( -0.4165383308 ),\r\n\tFN_DECIMAL( -0.6148930171 ),\r\n\tFN_DECIMAL( -0.1034332049 ),\r\n\tFN_DECIMAL( -0.9070022917 ),\r\n\tFN_DECIMAL( -0.9503958117 ),\r\n\tFN_DECIMAL( 0.9151503065 ),\r\n\tFN_DECIMAL( -0.6486716073 ),\r\n\tFN_DECIMAL( 0.6397687707 ),\r\n\tFN_DECIMAL( -0.9883386937 ),\r\n\tFN_DECIMAL( 0.3507613761 ),\r\n\tFN_DECIMAL( 0.9857642561 ),\r\n\tFN_DECIMAL( -0.9342026446 ),\r\n\tFN_DECIMAL( -0.9082419159 ),\r\n\tFN_DECIMAL( 0.1560587169 ),\r\n\tFN_DECIMAL( 0.4921240607 ),\r\n\tFN_DECIMAL( -0.453669308 ),\r\n\tFN_DECIMAL( 0.6818037859 ),\r\n\tFN_DECIMAL( 0.7976742329 ),\r\n\tFN_DECIMAL( 0.9098610522 ),\r\n\tFN_DECIMAL( 0.651633524 ),\r\n\tFN_DECIMAL( 0.7177318024 ),\r\n\tFN_DECIMAL( -0.5528685241 ),\r\n\tFN_DECIMAL( 0.5882467118 ),\r\n\tFN_DECIMAL( 0.6593778956 ),\r\n\tFN_DECIMAL( 0.9371027648 ),\r\n\tFN_DECIMAL( -0.7168658839 ),\r\n\tFN_DECIMAL( -0.4757737632 ),\r\n\tFN_DECIMAL( 0.7648291307 ),\r\n\tFN_DECIMAL( 0.7503650398 ),\r\n\tFN_DECIMAL( 0.1705063456 ),\r\n\tFN_DECIMAL( -0.8071558121 ),\r\n\tFN_DECIMAL( -0.9951433815 ),\r\n\tFN_DECIMAL( -0.8253280792 ),\r\n\tFN_DECIMAL( -0.7982502628 ),\r\n\tFN_DECIMAL( 0.9352738503 ),\r\n\tFN_DECIMAL( 0.8582254747 ),\r\n\tFN_DECIMAL( -0.3465310238 ),\r\n\tFN_DECIMAL( 0.65000842 ),\r\n\tFN_DECIMAL( -0.6697422351 ),\r\n\tFN_DECIMAL( 0.7441962291 ),\r\n\tFN_DECIMAL( -0.9533555 ),\r\n\tFN_DECIMAL( 0.5801940659 ),\r\n\tFN_DECIMAL( -0.9992862963 ),\r\n\tFN_DECIMAL( -0.659820211 ),\r\n\tFN_DECIMAL( 0.2575848092 ),\r\n\tFN_DECIMAL( 0.881588113 ),\r\n\tFN_DECIMAL( -0.9004043022 ),\r\n\tFN_DECIMAL( -0.7050172826 ),\r\n\tFN_DECIMAL( 0.369126382 ),\r\n\tFN_DECIMAL( -0.02265088836 ),\r\n\tFN_DECIMAL( 0.5568217228 ),\r\n\tFN_DECIMAL( -0.3316515286 ),\r\n\tFN_DECIMAL( 0.991098079 ),\r\n\tFN_DECIMAL( -0.863212164 ),\r\n\tFN_DECIMAL( -0.9285531277 ),\r\n\tFN_DECIMAL( 0.1695539323 ),\r\n\tFN_DECIMAL( -0.672402505 ),\r\n\tFN_DECIMAL( -0.001928841934 ),\r\n\tFN_DECIMAL( 0.9767452145 ),\r\n\tFN_DECIMAL( -0.8767960349 ),\r\n\tFN_DECIMAL( 0.9103515037 ),\r\n\tFN_DECIMAL( -0.7648324016 ),\r\n\tFN_DECIMAL( 0.2706960452 ),\r\n\tFN_DECIMAL( -0.9830446035 ),\r\n\tFN_DECIMAL( 0.8150341657 ),\r\n\tFN_DECIMAL( -0.9999013716 ),\r\n\tFN_DECIMAL( -0.8985605806 ),\r\n\tFN_DECIMAL( 0.8533360801 ),\r\n\tFN_DECIMAL( 0.8491442537 ),\r\n\tFN_DECIMAL( -0.2242541966 ),\r\n\tFN_DECIMAL( -0.1379635899 ),\r\n\tFN_DECIMAL( -0.4145572694 ),\r\n\tFN_DECIMAL( 0.1308227633 ),\r\n\tFN_DECIMAL( 0.6140555916 ),\r\n\tFN_DECIMAL( 0.9417041303 ),\r\n\tFN_DECIMAL( -0.336705587 ),\r\n\tFN_DECIMAL( -0.6254387508 ),\r\n\tFN_DECIMAL( 0.4631060578 ),\r\n\tFN_DECIMAL( -0.7578342456 ),\r\n\tFN_DECIMAL( -0.8172955655 ),\r\n\tFN_DECIMAL( -0.9959529228 ),\r\n\tFN_DECIMAL( -0.9760151351 ),\r\n\tFN_DECIMAL( 0.2348380732 ),\r\n\tFN_DECIMAL( -0.9983612848 ),\r\n\tFN_DECIMAL( 0.5856025746 ),\r\n\tFN_DECIMAL( -0.9400538266 ),\r\n\tFN_DECIMAL( -0.7639875669 ),\r\n\tFN_DECIMAL( 0.6244544645 ),\r\n\tFN_DECIMAL( 0.04604054566 ),\r\n\tFN_DECIMAL( 0.5888424828 ),\r\n\tFN_DECIMAL( 0.7708490978 ),\r\n\tFN_DECIMAL( -0.8114182882 ),\r\n\tFN_DECIMAL( 0.9786766212 ),\r\n\tFN_DECIMAL( -0.9984329822 ),\r\n\tFN_DECIMAL( 0.09125496582 ),\r\n\tFN_DECIMAL( -0.4492438803 ),\r\n\tFN_DECIMAL( -0.3636982357 ),\r\n\tFN_DECIMAL( 0.9443405575 ),\r\n\tFN_DECIMAL( -0.9476254645 ),\r\n\tFN_DECIMAL( -0.6818676535 ),\r\n\tFN_DECIMAL( -0.6113610831 ),\r\n\tFN_DECIMAL( 0.9754070948 ),\r\n\tFN_DECIMAL( -0.0938108173 ),\r\n\tFN_DECIMAL( -0.7029540015 ),\r\n\tFN_DECIMAL( -0.6085691109 ),\r\n\tFN_DECIMAL( -0.08718862881 ),\r\n\tFN_DECIMAL( -0.237381926 ),\r\n\tFN_DECIMAL( 0.2913423132 ),\r\n\tFN_DECIMAL( 0.9614872426 ),\r\n\tFN_DECIMAL( 0.8836361266 ),\r\n\tFN_DECIMAL( -0.2749974196 ),\r\n\tFN_DECIMAL( -0.8108932717 ),\r\n\tFN_DECIMAL( -0.8913607575 ),\r\n\tFN_DECIMAL( 0.129255541 ),\r\n\tFN_DECIMAL( -0.3342637104 ),\r\n\tFN_DECIMAL( -0.1921249337 ),\r\n\tFN_DECIMAL( -0.7566302845 ),\r\n\tFN_DECIMAL( -0.9563164339 ),\r\n\tFN_DECIMAL( -0.9744358146 ),\r\n\tFN_DECIMAL( 0.9836522982 ),\r\n\tFN_DECIMAL( -0.2863615732 ),\r\n\tFN_DECIMAL( 0.8337016872 ),\r\n\tFN_DECIMAL( 0.3683701937 ),\r\n\tFN_DECIMAL( 0.7657119102 ),\r\n\tFN_DECIMAL( -0.02312427772 ),\r\n\tFN_DECIMAL( 0.8875600535 ),\r\n\tFN_DECIMAL( 0.976642191 ),\r\n\tFN_DECIMAL( 0.9374176384 ),\r\n\tFN_DECIMAL( 0.9515313457 ),\r\n\tFN_DECIMAL( -0.7786361937 ),\r\n\tFN_DECIMAL( -0.4538302125 ),\r\n\tFN_DECIMAL( -0.7685604874 ),\r\n\tFN_DECIMAL( -0.8940796454 ),\r\n\tFN_DECIMAL( -0.8512462154 ),\r\n\tFN_DECIMAL( 0.5446696133 ),\r\n\tFN_DECIMAL( 0.9207601495 ),\r\n\tFN_DECIMAL( -0.9893091197 ),\r\n\tFN_DECIMAL( -0.9998680229 ),\r\n\tFN_DECIMAL( 0.5617309299 ),\r\n\tFN_DECIMAL( -0.8277411985 ),\r\n\tFN_DECIMAL( 0.545636467 ),\r\n\tFN_DECIMAL( 0.1690223212 ),\r\n\tFN_DECIMAL( -0.5079295433 ),\r\n\tFN_DECIMAL( 0.7685069899 ),\r\n\tFN_DECIMAL( -0.9630140787 ),\r\n\tFN_DECIMAL( 0.9015219132 ),\r\n\tFN_DECIMAL( 0.08905695279 ),\r\n\tFN_DECIMAL( -0.3423550559 ),\r\n\tFN_DECIMAL( -0.4661614943 ),\r\n\tFN_DECIMAL( -0.6449659371 ),\r\n\tFN_DECIMAL( 0.7139388509 ),\r\n\tFN_DECIMAL( 0.7472809229 ),\r\n};\r\nconst FN_DECIMAL CELL_3D_X[] = {\r\n\tFN_DECIMAL( 0.3752498686 ),\r\n\tFN_DECIMAL( 0.687188096 ),\r\n\tFN_DECIMAL( 0.2248135212 ),\r\n\tFN_DECIMAL( 0.6692006647 ),\r\n\tFN_DECIMAL( -0.4376476931 ),\r\n\tFN_DECIMAL( 0.6139972552 ),\r\n\tFN_DECIMAL( 0.9494563929 ),\r\n\tFN_DECIMAL( 0.8065108882 ),\r\n\tFN_DECIMAL( -0.2218812853 ),\r\n\tFN_DECIMAL( 0.8484661167 ),\r\n\tFN_DECIMAL( 0.5551817596 ),\r\n\tFN_DECIMAL( 0.2133903499 ),\r\n\tFN_DECIMAL( 0.5195126593 ),\r\n\tFN_DECIMAL( -0.6440141975 ),\r\n\tFN_DECIMAL( -0.5192897331 ),\r\n\tFN_DECIMAL( -0.3697654077 ),\r\n\tFN_DECIMAL( -0.07927779647 ),\r\n\tFN_DECIMAL( 0.4187757321 ),\r\n\tFN_DECIMAL( -0.750078731 ),\r\n\tFN_DECIMAL( 0.6579554632 ),\r\n\tFN_DECIMAL( -0.6859803838 ),\r\n\tFN_DECIMAL( -0.6878407087 ),\r\n\tFN_DECIMAL( 0.9490848347 ),\r\n\tFN_DECIMAL( 0.5795829433 ),\r\n\tFN_DECIMAL( -0.5325976529 ),\r\n\tFN_DECIMAL( -0.1363699466 ),\r\n\tFN_DECIMAL( 0.417665879 ),\r\n\tFN_DECIMAL( -0.9108236468 ),\r\n\tFN_DECIMAL( 0.4438605427 ),\r\n\tFN_DECIMAL( 0.819294887 ),\r\n\tFN_DECIMAL( -0.4033873915 ),\r\n\tFN_DECIMAL( -0.2817317705 ),\r\n\tFN_DECIMAL( 0.3969665622 ),\r\n\tFN_DECIMAL( 0.5323450134 ),\r\n\tFN_DECIMAL( -0.6833017297 ),\r\n\tFN_DECIMAL( 0.3881436661 ),\r\n\tFN_DECIMAL( -0.7119144767 ),\r\n\tFN_DECIMAL( -0.2306979838 ),\r\n\tFN_DECIMAL( -0.9398873022 ),\r\n\tFN_DECIMAL( 0.1701906676 ),\r\n\tFN_DECIMAL( -0.4261839496 ),\r\n\tFN_DECIMAL( -0.003712295499 ),\r\n\tFN_DECIMAL( -0.734675004 ),\r\n\tFN_DECIMAL( -0.3195046015 ),\r\n\tFN_DECIMAL( 0.7345307424 ),\r\n\tFN_DECIMAL( 0.9766246496 ),\r\n\tFN_DECIMAL( -0.02003735175 ),\r\n\tFN_DECIMAL( -0.4824156342 ),\r\n\tFN_DECIMAL( 0.4245892007 ),\r\n\tFN_DECIMAL( 0.9072427669 ),\r\n\tFN_DECIMAL( 0.593346808 ),\r\n\tFN_DECIMAL( -0.8911762541 ),\r\n\tFN_DECIMAL( -0.7657571834 ),\r\n\tFN_DECIMAL( -0.5268198896 ),\r\n\tFN_DECIMAL( -0.8801903279 ),\r\n\tFN_DECIMAL( -0.6296409617 ),\r\n\tFN_DECIMAL( -0.09492481344 ),\r\n\tFN_DECIMAL( -0.4920470525 ),\r\n\tFN_DECIMAL( 0.7307666154 ),\r\n\tFN_DECIMAL( -0.2514540636 ),\r\n\tFN_DECIMAL( -0.3356210347 ),\r\n\tFN_DECIMAL( -0.3522787894 ),\r\n\tFN_DECIMAL( 0.87847885 ),\r\n\tFN_DECIMAL( -0.7424096346 ),\r\n\tFN_DECIMAL( 0.5757585274 ),\r\n\tFN_DECIMAL( 0.4519299338 ),\r\n\tFN_DECIMAL( 0.6420368628 ),\r\n\tFN_DECIMAL( -0.1128478447 ),\r\n\tFN_DECIMAL( 0.499874883 ),\r\n\tFN_DECIMAL( 0.5291681739 ),\r\n\tFN_DECIMAL( -0.5098837195 ),\r\n\tFN_DECIMAL( 0.5639583502 ),\r\n\tFN_DECIMAL( -0.8456386526 ),\r\n\tFN_DECIMAL( -0.9657134875 ),\r\n\tFN_DECIMAL( -0.576437342 ),\r\n\tFN_DECIMAL( -0.5666013014 ),\r\n\tFN_DECIMAL( 0.5667702405 ),\r\n\tFN_DECIMAL( -0.481316582 ),\r\n\tFN_DECIMAL( 0.7313389916 ),\r\n\tFN_DECIMAL( -0.3805628566 ),\r\n\tFN_DECIMAL( -0.6512675909 ),\r\n\tFN_DECIMAL( -0.2787156951 ),\r\n\tFN_DECIMAL( 0.8648059114 ),\r\n\tFN_DECIMAL( -0.9730216276 ),\r\n\tFN_DECIMAL( -0.8335820906 ),\r\n\tFN_DECIMAL( 0.2673159641 ),\r\n\tFN_DECIMAL( 0.231150148 ),\r\n\tFN_DECIMAL( 0.01286214638 ),\r\n\tFN_DECIMAL( 0.6774953261 ),\r\n\tFN_DECIMAL( 0.6542885718 ),\r\n\tFN_DECIMAL( -0.02545450161 ),\r\n\tFN_DECIMAL( 0.2101238586 ),\r\n\tFN_DECIMAL( -0.5572105885 ),\r\n\tFN_DECIMAL( 0.813705672 ),\r\n\tFN_DECIMAL( -0.7546026951 ),\r\n\tFN_DECIMAL( -0.2502500006 ),\r\n\tFN_DECIMAL( -0.9979289381 ),\r\n\tFN_DECIMAL( 0.7024037039 ),\r\n\tFN_DECIMAL( 0.08990874624 ),\r\n\tFN_DECIMAL( 0.8170812432 ),\r\n\tFN_DECIMAL( 0.4226980265 ),\r\n\tFN_DECIMAL( -0.2442153475 ),\r\n\tFN_DECIMAL( -0.9183326731 ),\r\n\tFN_DECIMAL( 0.6068222411 ),\r\n\tFN_DECIMAL( 0.818676691 ),\r\n\tFN_DECIMAL( -0.7236735282 ),\r\n\tFN_DECIMAL( -0.5383903295 ),\r\n\tFN_DECIMAL( -0.6269337242 ),\r\n\tFN_DECIMAL( -0.0939331121 ),\r\n\tFN_DECIMAL( 0.9203878539 ),\r\n\tFN_DECIMAL( -0.7256396824 ),\r\n\tFN_DECIMAL( 0.6292431149 ),\r\n\tFN_DECIMAL( 0.4234156978 ),\r\n\tFN_DECIMAL( 0.006685688024 ),\r\n\tFN_DECIMAL( -0.2598694113 ),\r\n\tFN_DECIMAL( 0.6408036421 ),\r\n\tFN_DECIMAL( 0.05899871622 ),\r\n\tFN_DECIMAL( 0.7090281418 ),\r\n\tFN_DECIMAL( -0.5905222072 ),\r\n\tFN_DECIMAL( 0.3128214264 ),\r\n\tFN_DECIMAL( -0.691925826 ),\r\n\tFN_DECIMAL( 0.3634019349 ),\r\n\tFN_DECIMAL( -0.6772511147 ),\r\n\tFN_DECIMAL( -0.3204583896 ),\r\n\tFN_DECIMAL( -0.3906740409 ),\r\n\tFN_DECIMAL( -0.3342190395 ),\r\n\tFN_DECIMAL( -0.517779592 ),\r\n\tFN_DECIMAL( -0.6817711267 ),\r\n\tFN_DECIMAL( 0.6422383105 ),\r\n\tFN_DECIMAL( 0.4388482478 ),\r\n\tFN_DECIMAL( 0.2968562611 ),\r\n\tFN_DECIMAL( -0.2019778353 ),\r\n\tFN_DECIMAL( 0.6014865048 ),\r\n\tFN_DECIMAL( 0.9519280722 ),\r\n\tFN_DECIMAL( 0.3398889569 ),\r\n\tFN_DECIMAL( 0.8179709354 ),\r\n\tFN_DECIMAL( 0.2365522154 ),\r\n\tFN_DECIMAL( 0.3262175096 ),\r\n\tFN_DECIMAL( -0.8060715954 ),\r\n\tFN_DECIMAL( -0.2068642503 ),\r\n\tFN_DECIMAL( 0.6208057279 ),\r\n\tFN_DECIMAL( -0.5274282502 ),\r\n\tFN_DECIMAL( -0.3722334928 ),\r\n\tFN_DECIMAL( -0.8923412971 ),\r\n\tFN_DECIMAL( 0.5341834201 ),\r\n\tFN_DECIMAL( -0.3663701513 ),\r\n\tFN_DECIMAL( -0.6114600319 ),\r\n\tFN_DECIMAL( 0.5026307556 ),\r\n\tFN_DECIMAL( 0.8396151729 ),\r\n\tFN_DECIMAL( 0.9245042467 ),\r\n\tFN_DECIMAL( -0.7994843957 ),\r\n\tFN_DECIMAL( -0.5357200589 ),\r\n\tFN_DECIMAL( -0.6283359739 ),\r\n\tFN_DECIMAL( -0.61351886 ),\r\n\tFN_DECIMAL( -0.875632008 ),\r\n\tFN_DECIMAL( -0.5278879423 ),\r\n\tFN_DECIMAL( 0.9087491985 ),\r\n\tFN_DECIMAL( -0.03500215466 ),\r\n\tFN_DECIMAL( -0.261365798 ),\r\n\tFN_DECIMAL( -0.579523541 ),\r\n\tFN_DECIMAL( -0.3765052689 ),\r\n\tFN_DECIMAL( -0.74398252 ),\r\n\tFN_DECIMAL( 0.4257318052 ),\r\n\tFN_DECIMAL( -0.1214508921 ),\r\n\tFN_DECIMAL( 0.8561809753 ),\r\n\tFN_DECIMAL( 0.6802835104 ),\r\n\tFN_DECIMAL( -0.5452131039 ),\r\n\tFN_DECIMAL( -0.1997156478 ),\r\n\tFN_DECIMAL( 0.4562348357 ),\r\n\tFN_DECIMAL( -0.811704301 ),\r\n\tFN_DECIMAL( 0.67793962 ),\r\n\tFN_DECIMAL( -0.9237819106 ),\r\n\tFN_DECIMAL( 0.6973511259 ),\r\n\tFN_DECIMAL( -0.5189506 ),\r\n\tFN_DECIMAL( 0.5517320032 ),\r\n\tFN_DECIMAL( -0.396710831 ),\r\n\tFN_DECIMAL( 0.5493762815 ),\r\n\tFN_DECIMAL( -0.2507853002 ),\r\n\tFN_DECIMAL( 0.4788634005 ),\r\n\tFN_DECIMAL( 0.387333516 ),\r\n\tFN_DECIMAL( -0.2176515694 ),\r\n\tFN_DECIMAL( 0.6749832419 ),\r\n\tFN_DECIMAL( 0.2148283022 ),\r\n\tFN_DECIMAL( -0.7521815872 ),\r\n\tFN_DECIMAL( 0.4697000159 ),\r\n\tFN_DECIMAL( 0.7890593699 ),\r\n\tFN_DECIMAL( -0.7606162952 ),\r\n\tFN_DECIMAL( 0.01083397843 ),\r\n\tFN_DECIMAL( 0.5254091908 ),\r\n\tFN_DECIMAL( -0.6748025877 ),\r\n\tFN_DECIMAL( 0.751091524 ),\r\n\tFN_DECIMAL( 0.05259056135 ),\r\n\tFN_DECIMAL( 0.01889481232 ),\r\n\tFN_DECIMAL( -0.6037423727 ),\r\n\tFN_DECIMAL( -0.6542965129 ),\r\n\tFN_DECIMAL( 0.08873301081 ),\r\n\tFN_DECIMAL( -0.6191345671 ),\r\n\tFN_DECIMAL( 0.4331858488 ),\r\n\tFN_DECIMAL( -0.3858351946 ),\r\n\tFN_DECIMAL( -0.1429059747 ),\r\n\tFN_DECIMAL( 0.4118221036 ),\r\n\tFN_DECIMAL( -0.6247153214 ),\r\n\tFN_DECIMAL( -0.611423014 ),\r\n\tFN_DECIMAL( 0.5542939606 ),\r\n\tFN_DECIMAL( -0.9432768808 ),\r\n\tFN_DECIMAL( -0.4567870451 ),\r\n\tFN_DECIMAL( -0.7349133547 ),\r\n\tFN_DECIMAL( 0.399304489 ),\r\n\tFN_DECIMAL( -0.7474927672 ),\r\n\tFN_DECIMAL( 0.02589419753 ),\r\n\tFN_DECIMAL( 0.783915821 ),\r\n\tFN_DECIMAL( 0.6138668752 ),\r\n\tFN_DECIMAL( 0.4276376047 ),\r\n\tFN_DECIMAL( -0.4347886353 ),\r\n\tFN_DECIMAL( 0.02947841302 ),\r\n\tFN_DECIMAL( -0.833742746 ),\r\n\tFN_DECIMAL( 0.3817221742 ),\r\n\tFN_DECIMAL( -0.8743368359 ),\r\n\tFN_DECIMAL( -0.3823443796 ),\r\n\tFN_DECIMAL( -0.6829243811 ),\r\n\tFN_DECIMAL( -0.3681903049 ),\r\n\tFN_DECIMAL( -0.367626833 ),\r\n\tFN_DECIMAL( -0.434583373 ),\r\n\tFN_DECIMAL( 0.235891995 ),\r\n\tFN_DECIMAL( -0.6874880269 ),\r\n\tFN_DECIMAL( -0.5115661773 ),\r\n\tFN_DECIMAL( -0.5534962601 ),\r\n\tFN_DECIMAL( 0.5632777056 ),\r\n\tFN_DECIMAL( 0.686191532 ),\r\n\tFN_DECIMAL( -0.05095871588 ),\r\n\tFN_DECIMAL( -0.06865785057 ),\r\n\tFN_DECIMAL( -0.5975288531 ),\r\n\tFN_DECIMAL( -0.6429790056 ),\r\n\tFN_DECIMAL( -0.3729361548 ),\r\n\tFN_DECIMAL( 0.2237917666 ),\r\n\tFN_DECIMAL( 0.6046773225 ),\r\n\tFN_DECIMAL( -0.5041542295 ),\r\n\tFN_DECIMAL( -0.03972191174 ),\r\n\tFN_DECIMAL( 0.7028828406 ),\r\n\tFN_DECIMAL( -0.5560856498 ),\r\n\tFN_DECIMAL( 0.5898328456 ),\r\n\tFN_DECIMAL( -0.9308076766 ),\r\n\tFN_DECIMAL( 0.4617069864 ),\r\n\tFN_DECIMAL( 0.3190983137 ),\r\n\tFN_DECIMAL( 0.9116567753 ),\r\n\tFN_DECIMAL( -0.45029554 ),\r\n\tFN_DECIMAL( 0.3346334459 ),\r\n\tFN_DECIMAL( 0.8525005645 ),\r\n\tFN_DECIMAL( 0.2528483381 ),\r\n\tFN_DECIMAL( -0.8306630147 ),\r\n\tFN_DECIMAL( -0.6880390622 ),\r\n\tFN_DECIMAL( 0.7448684026 ),\r\n\tFN_DECIMAL( -0.1963355843 ),\r\n\tFN_DECIMAL( -0.5900257974 ),\r\n\tFN_DECIMAL( 0.9097057294 ),\r\n\tFN_DECIMAL( -0.2509196808 ),\r\n};\r\nconst FN_DECIMAL CELL_3D_Y[] = {\r\n\tFN_DECIMAL( -0.6760585049 ),\r\n\tFN_DECIMAL( -0.09136176499 ),\r\n\tFN_DECIMAL( 0.1681325679 ),\r\n\tFN_DECIMAL( -0.6688468686 ),\r\n\tFN_DECIMAL( -0.4822753902 ),\r\n\tFN_DECIMAL( -0.7891068824 ),\r\n\tFN_DECIMAL( -0.1877509944 ),\r\n\tFN_DECIMAL( 0.548470914 ),\r\n\tFN_DECIMAL( -0.463339443 ),\r\n\tFN_DECIMAL( -0.4050542082 ),\r\n\tFN_DECIMAL( 0.3218158513 ),\r\n\tFN_DECIMAL( 0.2546493823 ),\r\n\tFN_DECIMAL( -0.3753271935 ),\r\n\tFN_DECIMAL( 0.4745384887 ),\r\n\tFN_DECIMAL( 0.481254652 ),\r\n\tFN_DECIMAL( -0.8934416489 ),\r\n\tFN_DECIMAL( -0.6737085076 ),\r\n\tFN_DECIMAL( 0.7469917228 ),\r\n\tFN_DECIMAL( 0.3826230411 ),\r\n\tFN_DECIMAL( 0.6751013678 ),\r\n\tFN_DECIMAL( -0.7248119515 ),\r\n\tFN_DECIMAL( -0.3224276742 ),\r\n\tFN_DECIMAL( -0.02076190936 ),\r\n\tFN_DECIMAL( -0.6404268166 ),\r\n\tFN_DECIMAL( -0.5292028444 ),\r\n\tFN_DECIMAL( 0.7151414636 ),\r\n\tFN_DECIMAL( -0.6144655059 ),\r\n\tFN_DECIMAL( -0.369912124 ),\r\n\tFN_DECIMAL( 0.6942067212 ),\r\n\tFN_DECIMAL( -0.4481558248 ),\r\n\tFN_DECIMAL( -0.6366894559 ),\r\n\tFN_DECIMAL( 0.5956568471 ),\r\n\tFN_DECIMAL( 0.564274539 ),\r\n\tFN_DECIMAL( 0.7145584688 ),\r\n\tFN_DECIMAL( 0.6871918316 ),\r\n\tFN_DECIMAL( 0.5657918509 ),\r\n\tFN_DECIMAL( -0.6275978114 ),\r\n\tFN_DECIMAL( 0.4146983062 ),\r\n\tFN_DECIMAL( 0.2638993789 ),\r\n\tFN_DECIMAL( -0.792633138 ),\r\n\tFN_DECIMAL( 0.5706133514 ),\r\n\tFN_DECIMAL( 0.8606546462 ),\r\n\tFN_DECIMAL( 0.6490900316 ),\r\n\tFN_DECIMAL( -0.8242699196 ),\r\n\tFN_DECIMAL( 0.6765819124 ),\r\n\tFN_DECIMAL( 0.1959534069 ),\r\n\tFN_DECIMAL( -0.8426769757 ),\r\n\tFN_DECIMAL( -0.5917672797 ),\r\n\tFN_DECIMAL( 0.7517364266 ),\r\n\tFN_DECIMAL( 0.03252559226 ),\r\n\tFN_DECIMAL( 0.0883617105 ),\r\n\tFN_DECIMAL( 0.4475064813 ),\r\n\tFN_DECIMAL( -0.1418643552 ),\r\n\tFN_DECIMAL( 0.7343428473 ),\r\n\tFN_DECIMAL( 0.3870192548 ),\r\n\tFN_DECIMAL( -0.7716703522 ),\r\n\tFN_DECIMAL( 0.4839898327 ),\r\n\tFN_DECIMAL( 0.7437439055 ),\r\n\tFN_DECIMAL( -0.5989573348 ),\r\n\tFN_DECIMAL( -0.8357068955 ),\r\n\tFN_DECIMAL( 0.6086049038 ),\r\n\tFN_DECIMAL( 0.9194627258 ),\r\n\tFN_DECIMAL( 0.4718297238 ),\r\n\tFN_DECIMAL( -0.2650335884 ),\r\n\tFN_DECIMAL( -0.6470352599 ),\r\n\tFN_DECIMAL( -0.5555181303 ),\r\n\tFN_DECIMAL( 0.1222351235 ),\r\n\tFN_DECIMAL( 0.7802044684 ),\r\n\tFN_DECIMAL( -0.8636947022 ),\r\n\tFN_DECIMAL( -0.2341352163 ),\r\n\tFN_DECIMAL( 0.683030874 ),\r\n\tFN_DECIMAL( -0.5005858287 ),\r\n\tFN_DECIMAL( 0.2334616211 ),\r\n\tFN_DECIMAL( 0.2576877608 ),\r\n\tFN_DECIMAL( 0.6666816727 ),\r\n\tFN_DECIMAL( -0.7663996863 ),\r\n\tFN_DECIMAL( 0.794201982 ),\r\n\tFN_DECIMAL( 0.6189308788 ),\r\n\tFN_DECIMAL( 0.6071033261 ),\r\n\tFN_DECIMAL( -0.4206058253 ),\r\n\tFN_DECIMAL( -0.3957336915 ),\r\n\tFN_DECIMAL( -0.8170257484 ),\r\n\tFN_DECIMAL( -0.1043240417 ),\r\n\tFN_DECIMAL( 0.0002167596213 ),\r\n\tFN_DECIMAL( 0.1816339018 ),\r\n\tFN_DECIMAL( -0.6838094939 ),\r\n\tFN_DECIMAL( -0.2495341969 ),\r\n\tFN_DECIMAL( -0.7116756954 ),\r\n\tFN_DECIMAL( -0.03361673621 ),\r\n\tFN_DECIMAL( -0.3350836431 ),\r\n\tFN_DECIMAL( 0.2137186039 ),\r\n\tFN_DECIMAL( 0.2557996786 ),\r\n\tFN_DECIMAL( 0.7490117093 ),\r\n\tFN_DECIMAL( 0.4942936549 ),\r\n\tFN_DECIMAL( -0.352686853 ),\r\n\tFN_DECIMAL( -0.3952445435 ),\r\n\tFN_DECIMAL( -0.0459964767 ),\r\n\tFN_DECIMAL( -0.7115787471 ),\r\n\tFN_DECIMAL( 0.08022899756 ),\r\n\tFN_DECIMAL( 0.5362268157 ),\r\n\tFN_DECIMAL( -0.8258613686 ),\r\n\tFN_DECIMAL( 0.1114171723 ),\r\n\tFN_DECIMAL( 0.3882823051 ),\r\n\tFN_DECIMAL( -0.7915404457 ),\r\n\tFN_DECIMAL( 0.3250957662 ),\r\n\tFN_DECIMAL( 0.6401346464 ),\r\n\tFN_DECIMAL( -0.2662724517 ),\r\n\tFN_DECIMAL( -0.6727907114 ),\r\n\tFN_DECIMAL( -0.994730818 ),\r\n\tFN_DECIMAL( -0.3596358977 ),\r\n\tFN_DECIMAL( 0.2344610069 ),\r\n\tFN_DECIMAL( -0.6645215546 ),\r\n\tFN_DECIMAL( -0.7107590611 ),\r\n\tFN_DECIMAL( -0.4646617327 ),\r\n\tFN_DECIMAL( 0.6717191355 ),\r\n\tFN_DECIMAL( 0.5101893498 ),\r\n\tFN_DECIMAL( 0.1185768238 ),\r\n\tFN_DECIMAL( 0.236005093 ),\r\n\tFN_DECIMAL( -0.7811024061 ),\r\n\tFN_DECIMAL( 0.5089325193 ),\r\n\tFN_DECIMAL( 0.6073187658 ),\r\n\tFN_DECIMAL( -0.7930732557 ),\r\n\tFN_DECIMAL( -0.6822767155 ),\r\n\tFN_DECIMAL( 0.3201532885 ),\r\n\tFN_DECIMAL( 0.7545302807 ),\r\n\tFN_DECIMAL( 0.1072664448 ),\r\n\tFN_DECIMAL( 0.6784033173 ),\r\n\tFN_DECIMAL( -0.6595924967 ),\r\n\tFN_DECIMAL( 0.7276509498 ),\r\n\tFN_DECIMAL( 0.5586689436 ),\r\n\tFN_DECIMAL( -0.6498636788 ),\r\n\tFN_DECIMAL( 0.6789333174 ),\r\n\tFN_DECIMAL( 0.7105966551 ),\r\n\tFN_DECIMAL( -0.2872214155 ),\r\n\tFN_DECIMAL( 0.496746217 ),\r\n\tFN_DECIMAL( -0.3880337977 ),\r\n\tFN_DECIMAL( 0.7324070604 ),\r\n\tFN_DECIMAL( -0.9326634749 ),\r\n\tFN_DECIMAL( -0.5867839255 ),\r\n\tFN_DECIMAL( 0.8003043651 ),\r\n\tFN_DECIMAL( -0.1631882481 ),\r\n\tFN_DECIMAL( -0.6796374681 ),\r\n\tFN_DECIMAL( -0.8066678503 ),\r\n\tFN_DECIMAL( 0.4238177418 ),\r\n\tFN_DECIMAL( 0.7715863549 ),\r\n\tFN_DECIMAL( 0.5455367347 ),\r\n\tFN_DECIMAL( -0.03205115397 ),\r\n\tFN_DECIMAL( -0.6005545066 ),\r\n\tFN_DECIMAL( -0.5423640002 ),\r\n\tFN_DECIMAL( 0.3569205906 ),\r\n\tFN_DECIMAL( -0.582071752 ),\r\n\tFN_DECIMAL( 0.6407354361 ),\r\n\tFN_DECIMAL( 0.7777142984 ),\r\n\tFN_DECIMAL( -0.09956428618 ),\r\n\tFN_DECIMAL( 0.1100002681 ),\r\n\tFN_DECIMAL( 0.8136349123 ),\r\n\tFN_DECIMAL( 0.2923431904 ),\r\n\tFN_DECIMAL( 0.9735794425 ),\r\n\tFN_DECIMAL( 0.8324974864 ),\r\n\tFN_DECIMAL( -0.6179617717 ),\r\n\tFN_DECIMAL( -0.9248386523 ),\r\n\tFN_DECIMAL( -0.6448780771 ),\r\n\tFN_DECIMAL( -0.5274402761 ),\r\n\tFN_DECIMAL( -0.7862170565 ),\r\n\tFN_DECIMAL( 0.2682099744 ),\r\n\tFN_DECIMAL( -0.5848777694 ),\r\n\tFN_DECIMAL( -0.6364561467 ),\r\n\tFN_DECIMAL( -0.7167402514 ),\r\n\tFN_DECIMAL( -0.8677012494 ),\r\n\tFN_DECIMAL( 0.4205286707 ),\r\n\tFN_DECIMAL( -0.7007832749 ),\r\n\tFN_DECIMAL( 0.243272451 ),\r\n\tFN_DECIMAL( -0.1899846085 ),\r\n\tFN_DECIMAL( -0.6146124977 ),\r\n\tFN_DECIMAL( -0.8093357692 ),\r\n\tFN_DECIMAL( -0.03545096987 ),\r\n\tFN_DECIMAL( -0.7191590868 ),\r\n\tFN_DECIMAL( 0.7478645848 ),\r\n\tFN_DECIMAL( 0.3623517328 ),\r\n\tFN_DECIMAL( 0.8436992512 ),\r\n\tFN_DECIMAL( -0.2445711729 ),\r\n\tFN_DECIMAL( 0.6897356637 ),\r\n\tFN_DECIMAL( -0.1708070787 ),\r\n\tFN_DECIMAL( 0.4639272368 ),\r\n\tFN_DECIMAL( -0.7917186656 ),\r\n\tFN_DECIMAL( 0.02980025428 ),\r\n\tFN_DECIMAL( 0.6334156172 ),\r\n\tFN_DECIMAL( -0.9815544807 ),\r\n\tFN_DECIMAL( -0.2307217304 ),\r\n\tFN_DECIMAL( 0.1080823318 ),\r\n\tFN_DECIMAL( 0.5167601798 ),\r\n\tFN_DECIMAL( -0.845120016 ),\r\n\tFN_DECIMAL( 0.441572562 ),\r\n\tFN_DECIMAL( 0.5876789172 ),\r\n\tFN_DECIMAL( -0.6365908737 ),\r\n\tFN_DECIMAL( 0.68350166 ),\r\n\tFN_DECIMAL( 0.5849723959 ),\r\n\tFN_DECIMAL( 0.1164114357 ),\r\n\tFN_DECIMAL( -0.7379813884 ),\r\n\tFN_DECIMAL( -0.9613237178 ),\r\n\tFN_DECIMAL( -0.9071943084 ),\r\n\tFN_DECIMAL( -0.7682111105 ),\r\n\tFN_DECIMAL( 0.639074459 ),\r\n\tFN_DECIMAL( -0.619358298 ),\r\n\tFN_DECIMAL( 0.2807257131 ),\r\n\tFN_DECIMAL( -0.01800868791 ),\r\n\tFN_DECIMAL( 0.3776607289 ),\r\n\tFN_DECIMAL( 0.7207567823 ),\r\n\tFN_DECIMAL( 0.5536661486 ),\r\n\tFN_DECIMAL( -0.9974053117 ),\r\n\tFN_DECIMAL( -0.02047200006 ),\r\n\tFN_DECIMAL( -0.6739453804 ),\r\n\tFN_DECIMAL( -0.5607471297 ),\r\n\tFN_DECIMAL( 0.8815553192 ),\r\n\tFN_DECIMAL( 0.8275977415 ),\r\n\tFN_DECIMAL( 0.3928902456 ),\r\n\tFN_DECIMAL( 0.550991396 ),\r\n\tFN_DECIMAL( 0.4247623676 ),\r\n\tFN_DECIMAL( -0.3436948871 ),\r\n\tFN_DECIMAL( -0.3653537677 ),\r\n\tFN_DECIMAL( 0.3181702902 ),\r\n\tFN_DECIMAL( -0.6067173171 ),\r\n\tFN_DECIMAL( -0.8984128477 ),\r\n\tFN_DECIMAL( 0.4220839766 ),\r\n\tFN_DECIMAL( 0.7238407199 ),\r\n\tFN_DECIMAL( -0.7766913695 ),\r\n\tFN_DECIMAL( 0.6460037842 ),\r\n\tFN_DECIMAL( 0.2544775664 ),\r\n\tFN_DECIMAL( 0.6488840578 ),\r\n\tFN_DECIMAL( 0.805016833 ),\r\n\tFN_DECIMAL( -0.9183807036 ),\r\n\tFN_DECIMAL( 0.4144046357 ),\r\n\tFN_DECIMAL( 0.270587208 ),\r\n\tFN_DECIMAL( -0.8813684494 ),\r\n\tFN_DECIMAL( 0.6985971877 ),\r\n\tFN_DECIMAL( -0.7795603017 ),\r\n\tFN_DECIMAL( -0.8624480731 ),\r\n\tFN_DECIMAL( 0.5532697017 ),\r\n\tFN_DECIMAL( 0.711179521 ),\r\n\tFN_DECIMAL( -0.7798160574 ),\r\n\tFN_DECIMAL( 0.5225859041 ),\r\n\tFN_DECIMAL( 0.1261859368 ),\r\n\tFN_DECIMAL( 0.3398033582 ),\r\n\tFN_DECIMAL( -0.7472173667 ),\r\n\tFN_DECIMAL( -0.4032647119 ),\r\n\tFN_DECIMAL( -0.4246578154 ),\r\n\tFN_DECIMAL( 0.8481212377 ),\r\n\tFN_DECIMAL( -0.2144838537 ),\r\n\tFN_DECIMAL( 0.3431714491 ),\r\n\tFN_DECIMAL( 0.5310188231 ),\r\n\tFN_DECIMAL( 0.6682978632 ),\r\n\tFN_DECIMAL( 0.3110433206 ),\r\n\tFN_DECIMAL( 0.9263293599 ),\r\n\tFN_DECIMAL( -0.6155600569 ),\r\n\tFN_DECIMAL( 0.07169784399 ),\r\n\tFN_DECIMAL( 0.8985888773 ),\r\n};\r\nconst FN_DECIMAL CELL_3D_Z[] = {\r\n\tFN_DECIMAL( -0.6341391283 ),\r\n\tFN_DECIMAL( -0.7207118346 ),\r\n\tFN_DECIMAL( 0.9597866014 ),\r\n\tFN_DECIMAL( 0.3237504235 ),\r\n\tFN_DECIMAL( -0.7588642466 ),\r\n\tFN_DECIMAL( -0.01782410481 ),\r\n\tFN_DECIMAL( 0.2515593809 ),\r\n\tFN_DECIMAL( 0.2207257205 ),\r\n\tFN_DECIMAL( -0.8579541106 ),\r\n\tFN_DECIMAL( 0.3406410681 ),\r\n\tFN_DECIMAL( 0.7669470462 ),\r\n\tFN_DECIMAL( -0.9431957648 ),\r\n\tFN_DECIMAL( 0.7676171537 ),\r\n\tFN_DECIMAL( -0.6000491115 ),\r\n\tFN_DECIMAL( -0.7062096948 ),\r\n\tFN_DECIMAL( 0.2550207115 ),\r\n\tFN_DECIMAL( 0.7347325213 ),\r\n\tFN_DECIMAL( 0.5163625202 ),\r\n\tFN_DECIMAL( -0.5394270162 ),\r\n\tFN_DECIMAL( 0.3336656285 ),\r\n\tFN_DECIMAL( -0.0638635111 ),\r\n\tFN_DECIMAL( -0.6503195787 ),\r\n\tFN_DECIMAL( 0.3143356798 ),\r\n\tFN_DECIMAL( -0.5039217245 ),\r\n\tFN_DECIMAL( 0.6605180464 ),\r\n\tFN_DECIMAL( -0.6855479011 ),\r\n\tFN_DECIMAL( -0.6693185756 ),\r\n\tFN_DECIMAL( 0.1832083647 ),\r\n\tFN_DECIMAL( -0.5666258437 ),\r\n\tFN_DECIMAL( 0.3576482138 ),\r\n\tFN_DECIMAL( -0.6571949095 ),\r\n\tFN_DECIMAL( -0.7522101635 ),\r\n\tFN_DECIMAL( -0.7238865886 ),\r\n\tFN_DECIMAL( 0.4538887323 ),\r\n\tFN_DECIMAL( 0.2467106257 ),\r\n\tFN_DECIMAL( 0.7274778869 ),\r\n\tFN_DECIMAL( 0.3151170655 ),\r\n\tFN_DECIMAL( -0.8802293764 ),\r\n\tFN_DECIMAL( -0.2167232729 ),\r\n\tFN_DECIMAL( 0.5854637865 ),\r\n\tFN_DECIMAL( 0.7019741052 ),\r\n\tFN_DECIMAL( 0.5091756071 ),\r\n\tFN_DECIMAL( 0.1973189533 ),\r\n\tFN_DECIMAL( 0.46743546 ),\r\n\tFN_DECIMAL( 0.05197599597 ),\r\n\tFN_DECIMAL( 0.088354718 ),\r\n\tFN_DECIMAL( 0.5380464843 ),\r\n\tFN_DECIMAL( -0.6458224544 ),\r\n\tFN_DECIMAL( -0.5045952393 ),\r\n\tFN_DECIMAL( 0.419347884 ),\r\n\tFN_DECIMAL( 0.8000823542 ),\r\n\tFN_DECIMAL( -0.07445020656 ),\r\n\tFN_DECIMAL( -0.6272881641 ),\r\n\tFN_DECIMAL( -0.428020311 ),\r\n\tFN_DECIMAL( -0.2747382083 ),\r\n\tFN_DECIMAL( -0.08987283726 ),\r\n\tFN_DECIMAL( 0.8699098354 ),\r\n\tFN_DECIMAL( 0.4524761885 ),\r\n\tFN_DECIMAL( -0.3274603257 ),\r\n\tFN_DECIMAL( 0.4882262167 ),\r\n\tFN_DECIMAL( -0.7189983256 ),\r\n\tFN_DECIMAL( 0.1746079907 ),\r\n\tFN_DECIMAL( 0.0751772698 ),\r\n\tFN_DECIMAL( -0.6152927202 ),\r\n\tFN_DECIMAL( 0.4998474673 ),\r\n\tFN_DECIMAL( -0.6979677227 ),\r\n\tFN_DECIMAL( 0.7568667263 ),\r\n\tFN_DECIMAL( -0.6152612058 ),\r\n\tFN_DECIMAL( 0.06447140991 ),\r\n\tFN_DECIMAL( -0.8155744872 ),\r\n\tFN_DECIMAL( -0.5229602449 ),\r\n\tFN_DECIMAL( 0.6567836838 ),\r\n\tFN_DECIMAL( -0.4799905631 ),\r\n\tFN_DECIMAL( 0.03153534591 ),\r\n\tFN_DECIMAL( 0.4724992466 ),\r\n\tFN_DECIMAL( -0.3026458097 ),\r\n\tFN_DECIMAL( -0.2191225827 ),\r\n\tFN_DECIMAL( -0.620692287 ),\r\n\tFN_DECIMAL( 0.3107552588 ),\r\n\tFN_DECIMAL( 0.8235670294 ),\r\n\tFN_DECIMAL( 0.6474915988 ),\r\n\tFN_DECIMAL( -0.5047637941 ),\r\n\tFN_DECIMAL( 0.4911488878 ),\r\n\tFN_DECIMAL( -0.2307138167 ),\r\n\tFN_DECIMAL( -0.5216800015 ),\r\n\tFN_DECIMAL( 0.6789305939 ),\r\n\tFN_DECIMAL( 0.9403734863 ),\r\n\tFN_DECIMAL( 0.702390397 ),\r\n\tFN_DECIMAL( 0.7347584625 ),\r\n\tFN_DECIMAL( 0.6779567958 ),\r\n\tFN_DECIMAL( 0.9765635805 ),\r\n\tFN_DECIMAL( -0.9436177661 ),\r\n\tFN_DECIMAL( -0.358465925 ),\r\n\tFN_DECIMAL( -0.3058706624 ),\r\n\tFN_DECIMAL( 0.5533414464 ),\r\n\tFN_DECIMAL( -0.8838306897 ),\r\n\tFN_DECIMAL( 0.04496841812 ),\r\n\tFN_DECIMAL( 0.01687374963 ),\r\n\tFN_DECIMAL( -0.9927133148 ),\r\n\tFN_DECIMAL( -0.211752318 ),\r\n\tFN_DECIMAL( 0.3732015249 ),\r\n\tFN_DECIMAL( 0.9632990593 ),\r\n\tFN_DECIMAL( -0.07682417004 ),\r\n\tFN_DECIMAL( -0.07232213047 ),\r\n\tFN_DECIMAL( 0.4733721775 ),\r\n\tFN_DECIMAL( 0.2579229713 ),\r\n\tFN_DECIMAL( 0.7995216286 ),\r\n\tFN_DECIMAL( 0.3928189967 ),\r\n\tFN_DECIMAL( 0.04107517667 ),\r\n\tFN_DECIMAL( 0.1534542912 ),\r\n\tFN_DECIMAL( 0.6468965045 ),\r\n\tFN_DECIMAL( 0.4030684878 ),\r\n\tFN_DECIMAL( -0.5617300988 ),\r\n\tFN_DECIMAL( -0.885463029 ),\r\n\tFN_DECIMAL( 0.693729985 ),\r\n\tFN_DECIMAL( -0.5736527866 ),\r\n\tFN_DECIMAL( -0.9911905409 ),\r\n\tFN_DECIMAL( -0.66451538 ),\r\n\tFN_DECIMAL( 0.2028855685 ),\r\n\tFN_DECIMAL( 0.8019541421 ),\r\n\tFN_DECIMAL( -0.3903877149 ),\r\n\tFN_DECIMAL( -0.4888495114 ),\r\n\tFN_DECIMAL( -0.2753714057 ),\r\n\tFN_DECIMAL( -0.8915202143 ),\r\n\tFN_DECIMAL( 0.5273119089 ),\r\n\tFN_DECIMAL( 0.9363714773 ),\r\n\tFN_DECIMAL( -0.5212228249 ),\r\n\tFN_DECIMAL( -0.31642672 ),\r\n\tFN_DECIMAL( 0.2409440761 ),\r\n\tFN_DECIMAL( -0.703776404 ),\r\n\tFN_DECIMAL( -0.6996810411 ),\r\n\tFN_DECIMAL( -0.7058714505 ),\r\n\tFN_DECIMAL( -0.3650566783 ),\r\n\tFN_DECIMAL( 0.1064744278 ),\r\n\tFN_DECIMAL( 0.7985729102 ),\r\n\tFN_DECIMAL( 0.424680257 ),\r\n\tFN_DECIMAL( -0.6384535592 ),\r\n\tFN_DECIMAL( 0.1540161646 ),\r\n\tFN_DECIMAL( -0.07702731943 ),\r\n\tFN_DECIMAL( -0.5627789132 ),\r\n\tFN_DECIMAL( -0.7667919169 ),\r\n\tFN_DECIMAL( -0.509815999 ),\r\n\tFN_DECIMAL( 0.4590525092 ),\r\n\tFN_DECIMAL( 0.1552595611 ),\r\n\tFN_DECIMAL( 0.345402042 ),\r\n\tFN_DECIMAL( 0.7537656024 ),\r\n\tFN_DECIMAL( 0.7906259247 ),\r\n\tFN_DECIMAL( -0.6218493452 ),\r\n\tFN_DECIMAL( 0.02979350071 ),\r\n\tFN_DECIMAL( -0.1337893489 ),\r\n\tFN_DECIMAL( -0.1483818606 ),\r\n\tFN_DECIMAL( 0.549965562 ),\r\n\tFN_DECIMAL( 0.01882482408 ),\r\n\tFN_DECIMAL( -0.7833783002 ),\r\n\tFN_DECIMAL( 0.4702855809 ),\r\n\tFN_DECIMAL( 0.2435827372 ),\r\n\tFN_DECIMAL( 0.2978428332 ),\r\n\tFN_DECIMAL( 0.2256499906 ),\r\n\tFN_DECIMAL( 0.4885036897 ),\r\n\tFN_DECIMAL( 0.5312962584 ),\r\n\tFN_DECIMAL( 0.05401156992 ),\r\n\tFN_DECIMAL( 0.1749922158 ),\r\n\tFN_DECIMAL( -0.7352273018 ),\r\n\tFN_DECIMAL( 0.6058980284 ),\r\n\tFN_DECIMAL( 0.4416079111 ),\r\n\tFN_DECIMAL( 0.4417378638 ),\r\n\tFN_DECIMAL( 0.5455879807 ),\r\n\tFN_DECIMAL( -0.6681295324 ),\r\n\tFN_DECIMAL( 0.1973431441 ),\r\n\tFN_DECIMAL( 0.4053292055 ),\r\n\tFN_DECIMAL( 0.2220375492 ),\r\n\tFN_DECIMAL( 0.2957118467 ),\r\n\tFN_DECIMAL( 0.6910913512 ),\r\n\tFN_DECIMAL( 0.5940890106 ),\r\n\tFN_DECIMAL( -0.2014135283 ),\r\n\tFN_DECIMAL( -0.9172588213 ),\r\n\tFN_DECIMAL( -0.4254361401 ),\r\n\tFN_DECIMAL( -0.6146586825 ),\r\n\tFN_DECIMAL( -0.7996193253 ),\r\n\tFN_DECIMAL( -0.3716777111 ),\r\n\tFN_DECIMAL( -0.9448876842 ),\r\n\tFN_DECIMAL( -0.2620349924 ),\r\n\tFN_DECIMAL( 0.9615995749 ),\r\n\tFN_DECIMAL( -0.4679683524 ),\r\n\tFN_DECIMAL( 0.3905937144 ),\r\n\tFN_DECIMAL( 0.613593722 ),\r\n\tFN_DECIMAL( 0.1422937358 ),\r\n\tFN_DECIMAL( 0.1908754211 ),\r\n\tFN_DECIMAL( 0.8189704912 ),\r\n\tFN_DECIMAL( -0.7300408736 ),\r\n\tFN_DECIMAL( -0.4108776451 ),\r\n\tFN_DECIMAL( -0.5319834504 ),\r\n\tFN_DECIMAL( -0.8970265651 ),\r\n\tFN_DECIMAL( -0.5386359045 ),\r\n\tFN_DECIMAL( 0.4082255906 ),\r\n\tFN_DECIMAL( 0.7245356676 ),\r\n\tFN_DECIMAL( 0.5239080873 ),\r\n\tFN_DECIMAL( -0.8937552226 ),\r\n\tFN_DECIMAL( -0.553637673 ),\r\n\tFN_DECIMAL( 0.2354455182 ),\r\n\tFN_DECIMAL( -0.0860293075 ),\r\n\tFN_DECIMAL( -0.1399373318 ),\r\n\tFN_DECIMAL( -0.4666323327 ),\r\n\tFN_DECIMAL( 0.5560157407 ),\r\n\tFN_DECIMAL( 0.1772619533 ),\r\n\tFN_DECIMAL( -0.8893937725 ),\r\n\tFN_DECIMAL( -0.5632714576 ),\r\n\tFN_DECIMAL( -0.5666264959 ),\r\n\tFN_DECIMAL( -0.3670263736 ),\r\n\tFN_DECIMAL( -0.06717242579 ),\r\n\tFN_DECIMAL( 0.6205295181 ),\r\n\tFN_DECIMAL( -0.4110536264 ),\r\n\tFN_DECIMAL( 0.7090054553 ),\r\n\tFN_DECIMAL( 0.183899597 ),\r\n\tFN_DECIMAL( -0.5605470555 ),\r\n\tFN_DECIMAL( 0.3879565548 ),\r\n\tFN_DECIMAL( 0.7420893903 ),\r\n\tFN_DECIMAL( -0.2347595118 ),\r\n\tFN_DECIMAL( -0.8577217497 ),\r\n\tFN_DECIMAL( 0.6325590203 ),\r\n\tFN_DECIMAL( -0.8736152276 ),\r\n\tFN_DECIMAL( 0.7048011129 ),\r\n\tFN_DECIMAL( -0.06317948268 ),\r\n\tFN_DECIMAL( 0.8753285574 ),\r\n\tFN_DECIMAL( -0.05843650473 ),\r\n\tFN_DECIMAL( -0.3674922622 ),\r\n\tFN_DECIMAL( -0.5256624401 ),\r\n\tFN_DECIMAL( 0.7861039337 ),\r\n\tFN_DECIMAL( 0.3287714416 ),\r\n\tFN_DECIMAL( 0.5910593099 ),\r\n\tFN_DECIMAL( -0.3896960134 ),\r\n\tFN_DECIMAL( 0.6864605361 ),\r\n\tFN_DECIMAL( 0.7164918431 ),\r\n\tFN_DECIMAL( -0.290014277 ),\r\n\tFN_DECIMAL( -0.6796169617 ),\r\n\tFN_DECIMAL( 0.1632515592 ),\r\n\tFN_DECIMAL( 0.04485347486 ),\r\n\tFN_DECIMAL( 0.8320545697 ),\r\n\tFN_DECIMAL( 0.01339408056 ),\r\n\tFN_DECIMAL( -0.2874989857 ),\r\n\tFN_DECIMAL( 0.615630723 ),\r\n\tFN_DECIMAL( 0.3430367014 ),\r\n\tFN_DECIMAL( 0.8193658136 ),\r\n\tFN_DECIMAL( -0.5829600957 ),\r\n\tFN_DECIMAL( 0.07911697781 ),\r\n\tFN_DECIMAL( 0.7854296063 ),\r\n\tFN_DECIMAL( -0.4107442306 ),\r\n\tFN_DECIMAL( 0.4766964066 ),\r\n\tFN_DECIMAL( -0.9045999527 ),\r\n\tFN_DECIMAL( -0.1673856787 ),\r\n\tFN_DECIMAL( 0.2828077348 ),\r\n\tFN_DECIMAL( -0.5902737632 ),\r\n\tFN_DECIMAL( -0.321506229 ),\r\n\tFN_DECIMAL( -0.5224513133 ),\r\n\tFN_DECIMAL( -0.4090169985 ),\r\n\tFN_DECIMAL( -0.3599685311 ),\r\n};\r\n\r\nstatic int FastFloor( FN_DECIMAL f )\r\n{\r\n\treturn ( f >= 0 ? (int)f : (int)f - 1 );\r\n}\r\nstatic int FastRound( FN_DECIMAL f )\r\n{\r\n\treturn ( f >= 0 ) ? (int)( f + FN_DECIMAL( 0.5 ) ) : (int)( f - FN_DECIMAL( 0.5 ) );\r\n}\r\nstatic int FastAbs( int i )\r\n{\r\n\treturn abs( i );\r\n}\r\nstatic FN_DECIMAL FastAbs( FN_DECIMAL f )\r\n{\r\n\treturn fabs( f );\r\n}\r\nstatic FN_DECIMAL Lerp( FN_DECIMAL a, FN_DECIMAL b, FN_DECIMAL t )\r\n{\r\n\treturn a + t * ( b - a );\r\n}\r\nstatic FN_DECIMAL InterpHermiteFunc( FN_DECIMAL t )\r\n{\r\n\treturn t * t * ( 3 - 2 * t );\r\n}\r\nstatic FN_DECIMAL InterpQuinticFunc( FN_DECIMAL t )\r\n{\r\n\treturn t * t * t * ( t * ( t * 6 - 15 ) + 10 );\r\n}\r\nstatic FN_DECIMAL CubicLerp( FN_DECIMAL a, FN_DECIMAL b, FN_DECIMAL c, FN_DECIMAL d, FN_DECIMAL t )\r\n{\r\n\tFN_DECIMAL p = ( d - c ) - ( a - b );\r\n\treturn t * t * t * p + t * t * ( ( a - b ) - p ) + t * ( c - a ) + b;\r\n}\r\n\r\nvoid FastNoise::SetSeed( int seed )\r\n{\r\n\tm_seed = seed;\r\n\r\n\tstd::mt19937 gen( seed );\r\n\r\n\tfor ( int i = 0; i < 256; i++ )\r\n\t\tm_perm[i] = i;\r\n\r\n\tfor ( int j = 0; j < 256; j++ )\r\n\t{\r\n\t\tstd::uniform_int_distribution<> dis( 0, 256 - j );\r\n\t\tint k     = dis( gen ) + j;\r\n\t\tint l     = m_perm[j];\r\n\t\tm_perm[j] = m_perm[j + 256] = m_perm[k];\r\n\t\tm_perm[k]                   = l;\r\n\t\tm_perm12[j] = m_perm12[j + 256] = m_perm[j] % 12;\r\n\t}\r\n}\r\n\r\nvoid FastNoise::CalculateFractalBounding()\r\n{\r\n\tfloat amp        = m_gain;\r\n\tfloat ampFractal = 1.0f;\r\n\tfor ( int i = 1; i < m_octaves; i++ )\r\n\t{\r\n\t\tampFractal += amp;\r\n\t\tamp *= m_gain;\r\n\t}\r\n\tm_fractalBounding = 1.0f / ampFractal;\r\n}\r\n\r\nvoid FastNoise::SetCellularDistance2Indices( int cellularDistanceIndex0, int cellularDistanceIndex1 )\r\n{\r\n\tm_cellularDistanceIndex0 = std::min( cellularDistanceIndex0, cellularDistanceIndex1 );\r\n\tm_cellularDistanceIndex1 = std::max( cellularDistanceIndex0, cellularDistanceIndex1 );\r\n\r\n\tm_cellularDistanceIndex0 = std::min( std::max( m_cellularDistanceIndex0, 0 ), FN_CELLULAR_INDEX_MAX );\r\n\tm_cellularDistanceIndex1 = std::min( std::max( m_cellularDistanceIndex1, 0 ), FN_CELLULAR_INDEX_MAX );\r\n}\r\n\r\nvoid FastNoise::GetCellularDistance2Indices( int& cellularDistanceIndex0, int& cellularDistanceIndex1 ) const\r\n{\r\n\tcellularDistanceIndex0 = m_cellularDistanceIndex0;\r\n\tcellularDistanceIndex1 = m_cellularDistanceIndex1;\r\n}\r\n\r\nunsigned char FastNoise::Index2D_12( unsigned char offset, int x, int y ) const\r\n{\r\n\treturn m_perm12[( x & 0xff ) + m_perm[( y & 0xff ) + offset]];\r\n}\r\nunsigned char FastNoise::Index3D_12( unsigned char offset, int x, int y, int z ) const\r\n{\r\n\treturn m_perm12[( x & 0xff ) + m_perm[( y & 0xff ) + m_perm[( z & 0xff ) + offset]]];\r\n}\r\nunsigned char FastNoise::Index4D_32( unsigned char offset, int x, int y, int z, int w ) const\r\n{\r\n\treturn m_perm[( x & 0xff ) + m_perm[( y & 0xff ) + m_perm[( z & 0xff ) + m_perm[( w & 0xff ) + offset]]]] & 31;\r\n}\r\nunsigned char FastNoise::Index2D_256( unsigned char offset, int x, int y ) const\r\n{\r\n\treturn m_perm[( x & 0xff ) + m_perm[( y & 0xff ) + offset]];\r\n}\r\nunsigned char FastNoise::Index3D_256( unsigned char offset, int x, int y, int z ) const\r\n{\r\n\treturn m_perm[( x & 0xff ) + m_perm[( y & 0xff ) + m_perm[( z & 0xff ) + offset]]];\r\n}\r\nunsigned char FastNoise::Index4D_256( unsigned char offset, int x, int y, int z, int w ) const\r\n{\r\n\treturn m_perm[( x & 0xff ) + m_perm[( y & 0xff ) + m_perm[( z & 0xff ) + m_perm[( w & 0xff ) + offset]]]];\r\n}\r\n\r\n// Hashing\r\n#define X_PRIME 1619\r\n#define Y_PRIME 31337\r\n#define Z_PRIME 6971\r\n#define W_PRIME 1013\r\n\r\nstatic FN_DECIMAL ValCoord2D( int seed, int x, int y )\r\n{\r\n\tint n = seed;\r\n\tn ^= X_PRIME * x;\r\n\tn ^= Y_PRIME * y;\r\n\r\n\treturn ( n * n * n * 60493 ) / FN_DECIMAL( 2147483648 );\r\n}\r\nstatic FN_DECIMAL ValCoord3D( int seed, int x, int y, int z )\r\n{\r\n\tint n = seed;\r\n\tn ^= X_PRIME * x;\r\n\tn ^= Y_PRIME * y;\r\n\tn ^= Z_PRIME * z;\r\n\r\n\treturn ( n * n * n * 60493 ) / FN_DECIMAL( 2147483648 );\r\n}\r\nstatic FN_DECIMAL ValCoord4D( int seed, int x, int y, int z, int w )\r\n{\r\n\tint n = seed;\r\n\tn ^= X_PRIME * x;\r\n\tn ^= Y_PRIME * y;\r\n\tn ^= Z_PRIME * z;\r\n\tn ^= W_PRIME * w;\r\n\r\n\treturn ( n * n * n * 60493 ) / FN_DECIMAL( 2147483648 );\r\n}\r\n\r\nFN_DECIMAL FastNoise::ValCoord2DFast( unsigned char offset, int x, int y ) const\r\n{\r\n\treturn VAL_LUT[Index2D_256( offset, x, y )];\r\n}\r\nFN_DECIMAL FastNoise::ValCoord3DFast( unsigned char offset, int x, int y, int z ) const\r\n{\r\n\treturn VAL_LUT[Index3D_256( offset, x, y, z )];\r\n}\r\n\r\nFN_DECIMAL FastNoise::GradCoord2D( unsigned char offset, int x, int y, FN_DECIMAL xd, FN_DECIMAL yd ) const\r\n{\r\n\tunsigned char lutPos = Index2D_12( offset, x, y );\r\n\r\n\treturn xd * GRAD_X[lutPos] + yd * GRAD_Y[lutPos];\r\n}\r\nFN_DECIMAL FastNoise::GradCoord3D( unsigned char offset, int x, int y, int z, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd ) const\r\n{\r\n\tunsigned char lutPos = Index3D_12( offset, x, y, z );\r\n\r\n\treturn xd * GRAD_X[lutPos] + yd * GRAD_Y[lutPos] + zd * GRAD_Z[lutPos];\r\n}\r\nFN_DECIMAL FastNoise::GradCoord4D( unsigned char offset, int x, int y, int z, int w, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd, FN_DECIMAL wd ) const\r\n{\r\n\tunsigned char lutPos = Index4D_32( offset, x, y, z, w ) << 2;\r\n\r\n\treturn xd * GRAD_4D[lutPos] + yd * GRAD_4D[lutPos + 1] + zd * GRAD_4D[lutPos + 2] + wd * GRAD_4D[lutPos + 3];\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetNoise( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\tz *= m_frequency;\r\n\r\n\tswitch ( m_noiseType )\r\n\t{\r\n\t\tcase Value:\r\n\t\t\treturn SingleValue( 0, x, y, z );\r\n\t\tcase ValueFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SingleValueFractalFBM( x, y, z );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SingleValueFractalBillow( x, y, z );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SingleValueFractalRigidMulti( x, y, z );\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\tcase Perlin:\r\n\t\t\treturn SinglePerlin( 0, x, y, z );\r\n\t\tcase PerlinFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SinglePerlinFractalFBM( x, y, z );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SinglePerlinFractalBillow( x, y, z );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SinglePerlinFractalRigidMulti( x, y, z );\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\tcase Simplex:\r\n\t\t\treturn SingleSimplex( 0, x, y, z );\r\n\t\tcase SimplexFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SingleSimplexFractalFBM( x, y, z );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SingleSimplexFractalBillow( x, y, z );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SingleSimplexFractalRigidMulti( x, y, z );\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\tcase Cellular:\r\n\t\t\tswitch ( m_cellularReturnType )\r\n\t\t\t{\r\n\t\t\t\tcase CellValue:\r\n\t\t\t\tcase NoiseLookup:\r\n\t\t\t\tcase Distance:\r\n\t\t\t\t\treturn SingleCellular( x, y, z );\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn SingleCellular2Edge( x, y, z );\r\n\t\t\t}\r\n\t\tcase WhiteNoise:\r\n\t\t\treturn GetWhiteNoise( x, y, z );\r\n\t\tcase Cubic:\r\n\t\t\treturn SingleCubic( 0, x, y, z );\r\n\t\tcase CubicFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SingleCubicFractalFBM( x, y, z );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SingleCubicFractalBillow( x, y, z );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SingleCubicFractalRigidMulti( x, y, z );\r\n\t\t\t}\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetNoise( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\tswitch ( m_noiseType )\r\n\t{\r\n\t\tcase Value:\r\n\t\t\treturn SingleValue( 0, x, y );\r\n\t\tcase ValueFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SingleValueFractalFBM( x, y );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SingleValueFractalBillow( x, y );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SingleValueFractalRigidMulti( x, y );\r\n\t\t\t}\r\n\t\tcase Perlin:\r\n\t\t\treturn SinglePerlin( 0, x, y );\r\n\t\tcase PerlinFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SinglePerlinFractalFBM( x, y );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SinglePerlinFractalBillow( x, y );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SinglePerlinFractalRigidMulti( x, y );\r\n\t\t\t}\r\n\t\tcase Simplex:\r\n\t\t\treturn SingleSimplex( 0, x, y );\r\n\t\tcase SimplexFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SingleSimplexFractalFBM( x, y );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SingleSimplexFractalBillow( x, y );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SingleSimplexFractalRigidMulti( x, y );\r\n\t\t\t}\r\n\t\tcase Cellular:\r\n\t\t\tswitch ( m_cellularReturnType )\r\n\t\t\t{\r\n\t\t\t\tcase CellValue:\r\n\t\t\t\tcase NoiseLookup:\r\n\t\t\t\tcase Distance:\r\n\t\t\t\t\treturn SingleCellular( x, y );\r\n\t\t\t\tdefault:\r\n\t\t\t\t\treturn SingleCellular2Edge( x, y );\r\n\t\t\t}\r\n\t\tcase WhiteNoise:\r\n\t\t\treturn GetWhiteNoise( x, y );\r\n\t\tcase Cubic:\r\n\t\t\treturn SingleCubic( 0, x, y );\r\n\t\tcase CubicFractal:\r\n\t\t\tswitch ( m_fractalType )\r\n\t\t\t{\r\n\t\t\t\tcase FBM:\r\n\t\t\t\t\treturn SingleCubicFractalFBM( x, y );\r\n\t\t\t\tcase Billow:\r\n\t\t\t\t\treturn SingleCubicFractalBillow( x, y );\r\n\t\t\t\tcase RigidMulti:\r\n\t\t\t\t\treturn SingleCubicFractalRigidMulti( x, y );\r\n\t\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\n// White Noise\r\nFN_DECIMAL FastNoise::GetWhiteNoise( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w ) const\r\n{\r\n\treturn ValCoord4D( m_seed, *reinterpret_cast<int*>( &x ) ^ ( *reinterpret_cast<int*>( &x ) >> 16 ), *reinterpret_cast<int*>( &y ) ^ ( *reinterpret_cast<int*>( &y ) >> 16 ), *reinterpret_cast<int*>( &z ) ^ ( *reinterpret_cast<int*>( &z ) >> 16 ), *reinterpret_cast<int*>( &w ) ^ ( *reinterpret_cast<int*>( &w ) >> 16 ) );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetWhiteNoise( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\treturn ValCoord3D( m_seed, *reinterpret_cast<int*>( &x ) ^ ( *reinterpret_cast<int*>( &x ) >> 16 ), *reinterpret_cast<int*>( &y ) ^ ( *reinterpret_cast<int*>( &y ) >> 16 ), *reinterpret_cast<int*>( &z ) ^ ( *reinterpret_cast<int*>( &z ) >> 16 ) );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetWhiteNoise( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\treturn ValCoord2D( m_seed, *reinterpret_cast<int*>( &x ) ^ ( *reinterpret_cast<int*>( &x ) >> 16 ), *reinterpret_cast<int*>( &y ) ^ ( *reinterpret_cast<int*>( &y ) >> 16 ) );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetWhiteNoiseInt( int x, int y, int z, int w ) const\r\n{\r\n\treturn ValCoord4D( m_seed, x, y, z, w );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetWhiteNoiseInt( int x, int y, int z ) const\r\n{\r\n\treturn ValCoord3D( m_seed, x, y, z );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetWhiteNoiseInt( int x, int y ) const\r\n{\r\n\treturn ValCoord2D( m_seed, x, y );\r\n}\r\n\r\n// Value Noise\r\nFN_DECIMAL FastNoise::GetValueFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\tz *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SingleValueFractalFBM( x, y, z );\r\n\t\tcase Billow:\r\n\t\t\treturn SingleValueFractalBillow( x, y, z );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SingleValueFractalRigidMulti( x, y, z );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValueFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = SingleValue( m_perm[0], x, y, z );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SingleValue( m_perm[i], x, y, z ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValueFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SingleValue( m_perm[0], x, y, z ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SingleValue( m_perm[i], x, y, z ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValueFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SingleValue( m_perm[0], x, y, z ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SingleValue( m_perm[i], x, y, z ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetValue( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\treturn SingleValue( 0, x * m_frequency, y * m_frequency, z * m_frequency );\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValue( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tint x0 = FastFloor( x );\r\n\tint y0 = FastFloor( y );\r\n\tint z0 = FastFloor( z );\r\n\tint x1 = x0 + 1;\r\n\tint y1 = y0 + 1;\r\n\tint z1 = z0 + 1;\r\n\r\n\tFN_DECIMAL xs, ys, zs;\r\n\tswitch ( m_interp )\r\n\t{\r\n\t\tcase Linear:\r\n\t\t\txs = x - (FN_DECIMAL)x0;\r\n\t\t\tys = y - (FN_DECIMAL)y0;\r\n\t\t\tzs = z - (FN_DECIMAL)z0;\r\n\t\t\tbreak;\r\n\t\tcase Hermite:\r\n\t\t\txs = InterpHermiteFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpHermiteFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tzs = InterpHermiteFunc( z - (FN_DECIMAL)z0 );\r\n\t\t\tbreak;\r\n\t\tcase Quintic:\r\n\t\t\txs = InterpQuinticFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpQuinticFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tzs = InterpQuinticFunc( z - (FN_DECIMAL)z0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tFN_DECIMAL xf00 = Lerp( ValCoord3DFast( offset, x0, y0, z0 ), ValCoord3DFast( offset, x1, y0, z0 ), xs );\r\n\tFN_DECIMAL xf10 = Lerp( ValCoord3DFast( offset, x0, y1, z0 ), ValCoord3DFast( offset, x1, y1, z0 ), xs );\r\n\tFN_DECIMAL xf01 = Lerp( ValCoord3DFast( offset, x0, y0, z1 ), ValCoord3DFast( offset, x1, y0, z1 ), xs );\r\n\tFN_DECIMAL xf11 = Lerp( ValCoord3DFast( offset, x0, y1, z1 ), ValCoord3DFast( offset, x1, y1, z1 ), xs );\r\n\r\n\tFN_DECIMAL yf0 = Lerp( xf00, xf10, ys );\r\n\tFN_DECIMAL yf1 = Lerp( xf01, xf11, ys );\r\n\r\n\treturn Lerp( yf0, yf1, zs );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetValueFractal( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SingleValueFractalFBM( x, y );\r\n\t\tcase Billow:\r\n\t\t\treturn SingleValueFractalBillow( x, y );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SingleValueFractalRigidMulti( x, y );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValueFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = SingleValue( m_perm[0], x, y );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SingleValue( m_perm[i], x, y ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValueFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SingleValue( m_perm[0], x, y ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SingleValue( m_perm[i], x, y ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValueFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SingleValue( m_perm[0], x, y ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SingleValue( m_perm[i], x, y ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetValue( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\treturn SingleValue( 0, x * m_frequency, y * m_frequency );\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleValue( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tint x0 = FastFloor( x );\r\n\tint y0 = FastFloor( y );\r\n\tint x1 = x0 + 1;\r\n\tint y1 = y0 + 1;\r\n\r\n\tFN_DECIMAL xs, ys;\r\n\tswitch ( m_interp )\r\n\t{\r\n\t\tcase Linear:\r\n\t\t\txs = x - (FN_DECIMAL)x0;\r\n\t\t\tys = y - (FN_DECIMAL)y0;\r\n\t\t\tbreak;\r\n\t\tcase Hermite:\r\n\t\t\txs = InterpHermiteFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpHermiteFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tbreak;\r\n\t\tcase Quintic:\r\n\t\t\txs = InterpQuinticFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpQuinticFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tFN_DECIMAL xf0 = Lerp( ValCoord2DFast( offset, x0, y0 ), ValCoord2DFast( offset, x1, y0 ), xs );\r\n\tFN_DECIMAL xf1 = Lerp( ValCoord2DFast( offset, x0, y1 ), ValCoord2DFast( offset, x1, y1 ), xs );\r\n\r\n\treturn Lerp( xf0, xf1, ys );\r\n}\r\n\r\n// Perlin Noise\r\nFN_DECIMAL FastNoise::GetPerlinFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\tz *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SinglePerlinFractalFBM( x, y, z );\r\n\t\tcase Billow:\r\n\t\t\treturn SinglePerlinFractalBillow( x, y, z );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SinglePerlinFractalRigidMulti( x, y, z );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlinFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = SinglePerlin( m_perm[0], x, y, z );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SinglePerlin( m_perm[i], x, y, z ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlinFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SinglePerlin( m_perm[0], x, y, z ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SinglePerlin( m_perm[i], x, y, z ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlinFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SinglePerlin( m_perm[0], x, y, z ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SinglePerlin( m_perm[i], x, y, z ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetPerlin( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\treturn SinglePerlin( 0, x * m_frequency, y * m_frequency, z * m_frequency );\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlin( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tint x0 = FastFloor( x );\r\n\tint y0 = FastFloor( y );\r\n\tint z0 = FastFloor( z );\r\n\tint x1 = x0 + 1;\r\n\tint y1 = y0 + 1;\r\n\tint z1 = z0 + 1;\r\n\r\n\tFN_DECIMAL xs, ys, zs;\r\n\tswitch ( m_interp )\r\n\t{\r\n\t\tcase Linear:\r\n\t\t\txs = x - (FN_DECIMAL)x0;\r\n\t\t\tys = y - (FN_DECIMAL)y0;\r\n\t\t\tzs = z - (FN_DECIMAL)z0;\r\n\t\t\tbreak;\r\n\t\tcase Hermite:\r\n\t\t\txs = InterpHermiteFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpHermiteFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tzs = InterpHermiteFunc( z - (FN_DECIMAL)z0 );\r\n\t\t\tbreak;\r\n\t\tcase Quintic:\r\n\t\t\txs = InterpQuinticFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpQuinticFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tzs = InterpQuinticFunc( z - (FN_DECIMAL)z0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tFN_DECIMAL xd0 = x - (FN_DECIMAL)x0;\r\n\tFN_DECIMAL yd0 = y - (FN_DECIMAL)y0;\r\n\tFN_DECIMAL zd0 = z - (FN_DECIMAL)z0;\r\n\tFN_DECIMAL xd1 = xd0 - 1;\r\n\tFN_DECIMAL yd1 = yd0 - 1;\r\n\tFN_DECIMAL zd1 = zd0 - 1;\r\n\r\n\tFN_DECIMAL xf00 = Lerp( GradCoord3D( offset, x0, y0, z0, xd0, yd0, zd0 ), GradCoord3D( offset, x1, y0, z0, xd1, yd0, zd0 ), xs );\r\n\tFN_DECIMAL xf10 = Lerp( GradCoord3D( offset, x0, y1, z0, xd0, yd1, zd0 ), GradCoord3D( offset, x1, y1, z0, xd1, yd1, zd0 ), xs );\r\n\tFN_DECIMAL xf01 = Lerp( GradCoord3D( offset, x0, y0, z1, xd0, yd0, zd1 ), GradCoord3D( offset, x1, y0, z1, xd1, yd0, zd1 ), xs );\r\n\tFN_DECIMAL xf11 = Lerp( GradCoord3D( offset, x0, y1, z1, xd0, yd1, zd1 ), GradCoord3D( offset, x1, y1, z1, xd1, yd1, zd1 ), xs );\r\n\r\n\tFN_DECIMAL yf0 = Lerp( xf00, xf10, ys );\r\n\tFN_DECIMAL yf1 = Lerp( xf01, xf11, ys );\r\n\r\n\treturn Lerp( yf0, yf1, zs );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetPerlinFractal( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SinglePerlinFractalFBM( x, y );\r\n\t\tcase Billow:\r\n\t\t\treturn SinglePerlinFractalBillow( x, y );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SinglePerlinFractalRigidMulti( x, y );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlinFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = SinglePerlin( m_perm[0], x, y );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SinglePerlin( m_perm[i], x, y ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlinFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SinglePerlin( m_perm[0], x, y ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SinglePerlin( m_perm[i], x, y ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlinFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SinglePerlin( m_perm[0], x, y ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SinglePerlin( m_perm[i], x, y ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetPerlin( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\treturn SinglePerlin( 0, x * m_frequency, y * m_frequency );\r\n}\r\n\r\nFN_DECIMAL FastNoise::SinglePerlin( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tint x0 = FastFloor( x );\r\n\tint y0 = FastFloor( y );\r\n\tint x1 = x0 + 1;\r\n\tint y1 = y0 + 1;\r\n\r\n\tFN_DECIMAL xs, ys;\r\n\tswitch ( m_interp )\r\n\t{\r\n\t\tcase Linear:\r\n\t\t\txs = x - (FN_DECIMAL)x0;\r\n\t\t\tys = y - (FN_DECIMAL)y0;\r\n\t\t\tbreak;\r\n\t\tcase Hermite:\r\n\t\t\txs = InterpHermiteFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpHermiteFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tbreak;\r\n\t\tcase Quintic:\r\n\t\t\txs = InterpQuinticFunc( x - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpQuinticFunc( y - (FN_DECIMAL)y0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tFN_DECIMAL xd0 = x - (FN_DECIMAL)x0;\r\n\tFN_DECIMAL yd0 = y - (FN_DECIMAL)y0;\r\n\tFN_DECIMAL xd1 = xd0 - 1;\r\n\tFN_DECIMAL yd1 = yd0 - 1;\r\n\r\n\tFN_DECIMAL xf0 = Lerp( GradCoord2D( offset, x0, y0, xd0, yd0 ), GradCoord2D( offset, x1, y0, xd1, yd0 ), xs );\r\n\tFN_DECIMAL xf1 = Lerp( GradCoord2D( offset, x0, y1, xd0, yd1 ), GradCoord2D( offset, x1, y1, xd1, yd1 ), xs );\r\n\r\n\treturn Lerp( xf0, xf1, ys );\r\n}\r\n\r\n// Simplex Noise\r\n\r\nFN_DECIMAL FastNoise::GetSimplexFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\tz *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SingleSimplexFractalFBM( x, y, z );\r\n\t\tcase Billow:\r\n\t\t\treturn SingleSimplexFractalBillow( x, y, z );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SingleSimplexFractalRigidMulti( x, y, z );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = SingleSimplex( m_perm[0], x, y, z );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SingleSimplex( m_perm[i], x, y, z ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SingleSimplex( m_perm[0], x, y, z ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SingleSimplex( m_perm[i], x, y, z ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SingleSimplex( m_perm[0], x, y, z ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SingleSimplex( m_perm[i], x, y, z ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetSimplex( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\treturn SingleSimplex( 0, x * m_frequency, y * m_frequency, z * m_frequency );\r\n}\r\n\r\nstatic const FN_DECIMAL F3 = 1 / FN_DECIMAL( 3 );\r\nstatic const FN_DECIMAL G3 = 1 / FN_DECIMAL( 6 );\r\n\r\nFN_DECIMAL FastNoise::SingleSimplex( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL t = ( x + y + z ) * F3;\r\n\tint i        = FastFloor( x + t );\r\n\tint j        = FastFloor( y + t );\r\n\tint k        = FastFloor( z + t );\r\n\r\n\tt             = ( i + j + k ) * G3;\r\n\tFN_DECIMAL X0 = i - t;\r\n\tFN_DECIMAL Y0 = j - t;\r\n\tFN_DECIMAL Z0 = k - t;\r\n\r\n\tFN_DECIMAL x0 = x - X0;\r\n\tFN_DECIMAL y0 = y - Y0;\r\n\tFN_DECIMAL z0 = z - Z0;\r\n\r\n\tint i1, j1, k1;\r\n\tint i2, j2, k2;\r\n\r\n\tif ( x0 >= y0 )\r\n\t{\r\n\t\tif ( y0 >= z0 )\r\n\t\t{\r\n\t\t\ti1 = 1;\r\n\t\t\tj1 = 0;\r\n\t\t\tk1 = 0;\r\n\t\t\ti2 = 1;\r\n\t\t\tj2 = 1;\r\n\t\t\tk2 = 0;\r\n\t\t}\r\n\t\telse if ( x0 >= z0 )\r\n\t\t{\r\n\t\t\ti1 = 1;\r\n\t\t\tj1 = 0;\r\n\t\t\tk1 = 0;\r\n\t\t\ti2 = 1;\r\n\t\t\tj2 = 0;\r\n\t\t\tk2 = 1;\r\n\t\t}\r\n\t\telse // x0 < z0\r\n\t\t{\r\n\t\t\ti1 = 0;\r\n\t\t\tj1 = 0;\r\n\t\t\tk1 = 1;\r\n\t\t\ti2 = 1;\r\n\t\t\tj2 = 0;\r\n\t\t\tk2 = 1;\r\n\t\t}\r\n\t}\r\n\telse // x0 < y0\r\n\t{\r\n\t\tif ( y0 < z0 )\r\n\t\t{\r\n\t\t\ti1 = 0;\r\n\t\t\tj1 = 0;\r\n\t\t\tk1 = 1;\r\n\t\t\ti2 = 0;\r\n\t\t\tj2 = 1;\r\n\t\t\tk2 = 1;\r\n\t\t}\r\n\t\telse if ( x0 < z0 )\r\n\t\t{\r\n\t\t\ti1 = 0;\r\n\t\t\tj1 = 1;\r\n\t\t\tk1 = 0;\r\n\t\t\ti2 = 0;\r\n\t\t\tj2 = 1;\r\n\t\t\tk2 = 1;\r\n\t\t}\r\n\t\telse // x0 >= z0\r\n\t\t{\r\n\t\t\ti1 = 0;\r\n\t\t\tj1 = 1;\r\n\t\t\tk1 = 0;\r\n\t\t\ti2 = 1;\r\n\t\t\tj2 = 1;\r\n\t\t\tk2 = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tFN_DECIMAL x1 = x0 - i1 + G3;\r\n\tFN_DECIMAL y1 = y0 - j1 + G3;\r\n\tFN_DECIMAL z1 = z0 - k1 + G3;\r\n\tFN_DECIMAL x2 = x0 - i2 + 2 * G3;\r\n\tFN_DECIMAL y2 = y0 - j2 + 2 * G3;\r\n\tFN_DECIMAL z2 = z0 - k2 + 2 * G3;\r\n\tFN_DECIMAL x3 = x0 - 1 + 3 * G3;\r\n\tFN_DECIMAL y3 = y0 - 1 + 3 * G3;\r\n\tFN_DECIMAL z3 = z0 - 1 + 3 * G3;\r\n\r\n\tFN_DECIMAL n0, n1, n2, n3;\r\n\r\n\tt = FN_DECIMAL( 0.6 ) - x0 * x0 - y0 * y0 - z0 * z0;\r\n\tif ( t < 0 )\r\n\t\tn0 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn0 = t * t * GradCoord3D( offset, i, j, k, x0, y0, z0 );\r\n\t}\r\n\r\n\tt = FN_DECIMAL( 0.6 ) - x1 * x1 - y1 * y1 - z1 * z1;\r\n\tif ( t < 0 )\r\n\t\tn1 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn1 = t * t * GradCoord3D( offset, i + i1, j + j1, k + k1, x1, y1, z1 );\r\n\t}\r\n\r\n\tt = FN_DECIMAL( 0.6 ) - x2 * x2 - y2 * y2 - z2 * z2;\r\n\tif ( t < 0 )\r\n\t\tn2 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn2 = t * t * GradCoord3D( offset, i + i2, j + j2, k + k2, x2, y2, z2 );\r\n\t}\r\n\r\n\tt = FN_DECIMAL( 0.6 ) - x3 * x3 - y3 * y3 - z3 * z3;\r\n\tif ( t < 0 )\r\n\t\tn3 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn3 = t * t * GradCoord3D( offset, i + 1, j + 1, k + 1, x3, y3, z3 );\r\n\t}\r\n\r\n\treturn 32 * ( n0 + n1 + n2 + n3 );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetSimplexFractal( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SingleSimplexFractalFBM( x, y );\r\n\t\tcase Billow:\r\n\t\t\treturn SingleSimplexFractalBillow( x, y );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SingleSimplexFractalRigidMulti( x, y );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = SingleSimplex( m_perm[0], x, y );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SingleSimplex( m_perm[i], x, y ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SingleSimplex( m_perm[0], x, y ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SingleSimplex( m_perm[i], x, y ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SingleSimplex( m_perm[0], x, y ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SingleSimplex( m_perm[i], x, y ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleSimplexFractalBlend( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = SingleSimplex( m_perm[0], x, y );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum *= SingleSimplex( m_perm[i], x, y ) * amp + 1;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetSimplex( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\treturn SingleSimplex( 0, x * m_frequency, y * m_frequency );\r\n}\r\n\r\n//static const FN_DECIMAL F2 = 1 / FN_DECIMAL(2);\r\n//static const FN_DECIMAL G2 = 1 / FN_DECIMAL(4);\r\n\r\nstatic const FN_DECIMAL SQRT3 = FN_DECIMAL( 1.7320508075688772935274463415059 );\r\nstatic const FN_DECIMAL F2    = FN_DECIMAL( 0.5 ) * ( SQRT3 - FN_DECIMAL( 1.0 ) );\r\nstatic const FN_DECIMAL G2    = ( FN_DECIMAL( 3.0 ) - SQRT3 ) / FN_DECIMAL( 6.0 );\r\n\r\nFN_DECIMAL FastNoise::SingleSimplex( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL t = ( x + y ) * F2;\r\n\tint i        = FastFloor( x + t );\r\n\tint j        = FastFloor( y + t );\r\n\r\n\tt             = ( i + j ) * G2;\r\n\tFN_DECIMAL X0 = i - t;\r\n\tFN_DECIMAL Y0 = j - t;\r\n\r\n\tFN_DECIMAL x0 = x - X0;\r\n\tFN_DECIMAL y0 = y - Y0;\r\n\r\n\tint i1, j1;\r\n\tif ( x0 > y0 )\r\n\t{\r\n\t\ti1 = 1;\r\n\t\tj1 = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ti1 = 0;\r\n\t\tj1 = 1;\r\n\t}\r\n\r\n\tFN_DECIMAL x1 = x0 - (FN_DECIMAL)i1 + G2;\r\n\tFN_DECIMAL y1 = y0 - (FN_DECIMAL)j1 + G2;\r\n\tFN_DECIMAL x2 = x0 - 1 + 2 * G2;\r\n\tFN_DECIMAL y2 = y0 - 1 + 2 * G2;\r\n\r\n\tFN_DECIMAL n0, n1, n2;\r\n\r\n\tt = FN_DECIMAL( 0.5 ) - x0 * x0 - y0 * y0;\r\n\tif ( t < 0 )\r\n\t\tn0 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn0 = t * t * GradCoord2D( offset, i, j, x0, y0 );\r\n\t}\r\n\r\n\tt = FN_DECIMAL( 0.5 ) - x1 * x1 - y1 * y1;\r\n\tif ( t < 0 )\r\n\t\tn1 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn1 = t * t * GradCoord2D( offset, i + i1, j + j1, x1, y1 );\r\n\t}\r\n\r\n\tt = FN_DECIMAL( 0.5 ) - x2 * x2 - y2 * y2;\r\n\tif ( t < 0 )\r\n\t\tn2 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn2 = t * t * GradCoord2D( offset, i + 1, j + 1, x2, y2 );\r\n\t}\r\n\r\n\treturn 70 * ( n0 + n1 + n2 );\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetSimplex( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w ) const\r\n{\r\n\treturn SingleSimplex( 0, x * m_frequency, y * m_frequency, z * m_frequency, w * m_frequency );\r\n}\r\n\r\nstatic const unsigned char SIMPLEX_4D[] = {\r\n\t0, 1, 2, 3, 0, 1, 3, 2, 0, 0, 0, 0, 0, 2, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0,\r\n\t0, 2, 1, 3, 0, 0, 0, 0, 0, 3, 1, 2, 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 2, 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, 0, 0, 0, 0, 0, 0, 0,\r\n\t1, 2, 0, 3, 0, 0, 0, 0, 1, 3, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, 1, 2, 3, 1, 0,\r\n\t1, 0, 2, 3, 1, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 1, 0, 0, 0, 0, 2, 1, 3, 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, 0, 0, 0, 0, 0, 0, 0,\r\n\t2, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1, 2, 3, 0, 2, 1, 0, 0, 0, 0, 3, 1, 2, 0,\r\n\t2, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 0, 2, 0, 0, 0, 0, 3, 2, 0, 1, 3, 2, 1, 0\r\n};\r\n\r\nstatic const FN_DECIMAL F4 = ( sqrt( FN_DECIMAL( 5 ) ) - 1 ) / 4;\r\nstatic const FN_DECIMAL G4 = ( 5 - sqrt( FN_DECIMAL( 5 ) ) ) / 2;\r\n\r\nFN_DECIMAL FastNoise::SingleSimplex( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w ) const\r\n{\r\n\tFN_DECIMAL n0, n1, n2, n3, n4;\r\n\tFN_DECIMAL t  = ( x + y + z + w ) * F4;\r\n\tint i         = FastFloor( x + t );\r\n\tint j         = FastFloor( y + t );\r\n\tint k         = FastFloor( z + t );\r\n\tint l         = FastFloor( w + t );\r\n\tt             = ( i + j + k + l ) * G4;\r\n\tFN_DECIMAL X0 = i - t;\r\n\tFN_DECIMAL Y0 = j - t;\r\n\tFN_DECIMAL Z0 = k - t;\r\n\tFN_DECIMAL W0 = l - t;\r\n\tFN_DECIMAL x0 = x - X0;\r\n\tFN_DECIMAL y0 = y - Y0;\r\n\tFN_DECIMAL z0 = z - Z0;\r\n\tFN_DECIMAL w0 = w - W0;\r\n\r\n\tint c = ( x0 > y0 ) ? 32 : 0;\r\n\tc += ( x0 > z0 ) ? 16 : 0;\r\n\tc += ( y0 > z0 ) ? 8 : 0;\r\n\tc += ( x0 > w0 ) ? 4 : 0;\r\n\tc += ( y0 > w0 ) ? 2 : 0;\r\n\tc += ( z0 > w0 ) ? 1 : 0;\r\n\tc <<= 2;\r\n\r\n\tint i1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;\r\n\tint i2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;\r\n\tint i3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0;\r\n\tint j1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;\r\n\tint j2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;\r\n\tint j3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0;\r\n\tint k1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;\r\n\tint k2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;\r\n\tint k3 = SIMPLEX_4D[c++] >= 1 ? 1 : 0;\r\n\tint l1 = SIMPLEX_4D[c] >= 3 ? 1 : 0;\r\n\tint l2 = SIMPLEX_4D[c] >= 2 ? 1 : 0;\r\n\tint l3 = SIMPLEX_4D[c] >= 1 ? 1 : 0;\r\n\r\n\tFN_DECIMAL x1 = x0 - i1 + G4;\r\n\tFN_DECIMAL y1 = y0 - j1 + G4;\r\n\tFN_DECIMAL z1 = z0 - k1 + G4;\r\n\tFN_DECIMAL w1 = w0 - l1 + G4;\r\n\tFN_DECIMAL x2 = x0 - i2 + 2 * G4;\r\n\tFN_DECIMAL y2 = y0 - j2 + 2 * G4;\r\n\tFN_DECIMAL z2 = z0 - k2 + 2 * G4;\r\n\tFN_DECIMAL w2 = w0 - l2 + 2 * G4;\r\n\tFN_DECIMAL x3 = x0 - i3 + 3 * G4;\r\n\tFN_DECIMAL y3 = y0 - j3 + 3 * G4;\r\n\tFN_DECIMAL z3 = z0 - k3 + 3 * G4;\r\n\tFN_DECIMAL w3 = w0 - l3 + 3 * G4;\r\n\tFN_DECIMAL x4 = x0 - 1 + 4 * G4;\r\n\tFN_DECIMAL y4 = y0 - 1 + 4 * G4;\r\n\tFN_DECIMAL z4 = z0 - 1 + 4 * G4;\r\n\tFN_DECIMAL w4 = w0 - 1 + 4 * G4;\r\n\r\n\tt = FN_DECIMAL( 0.6 ) - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;\r\n\tif ( t < 0 )\r\n\t\tn0 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn0 = t * t * GradCoord4D( offset, i, j, k, l, x0, y0, z0, w0 );\r\n\t}\r\n\tt = FN_DECIMAL( 0.6 ) - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;\r\n\tif ( t < 0 )\r\n\t\tn1 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn1 = t * t * GradCoord4D( offset, i + i1, j + j1, k + k1, l + l1, x1, y1, z1, w1 );\r\n\t}\r\n\tt = FN_DECIMAL( 0.6 ) - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;\r\n\tif ( t < 0 )\r\n\t\tn2 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn2 = t * t * GradCoord4D( offset, i + i2, j + j2, k + k2, l + l2, x2, y2, z2, w2 );\r\n\t}\r\n\tt = FN_DECIMAL( 0.6 ) - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;\r\n\tif ( t < 0 )\r\n\t\tn3 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn3 = t * t * GradCoord4D( offset, i + i3, j + j3, k + k3, l + l3, x3, y3, z3, w3 );\r\n\t}\r\n\tt = FN_DECIMAL( 0.6 ) - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;\r\n\tif ( t < 0 )\r\n\t\tn4 = 0;\r\n\telse\r\n\t{\r\n\t\tt *= t;\r\n\t\tn4 = t * t * GradCoord4D( offset, i + 1, j + 1, k + 1, l + 1, x4, y4, z4, w4 );\r\n\t}\r\n\r\n\treturn 27 * ( n0 + n1 + n2 + n3 + n4 );\r\n}\r\n\r\n// Cubic Noise\r\nFN_DECIMAL FastNoise::GetCubicFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\tz *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SingleCubicFractalFBM( x, y, z );\r\n\t\tcase Billow:\r\n\t\t\treturn SingleCubicFractalBillow( x, y, z );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SingleCubicFractalRigidMulti( x, y, z );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCubicFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = SingleCubic( m_perm[0], x, y, z );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SingleCubic( m_perm[i], x, y, z ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCubicFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SingleCubic( m_perm[0], x, y, z ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SingleCubic( m_perm[i], x, y, z ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCubicFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SingleCubic( m_perm[0], x, y, z ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\t\tz *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SingleCubic( m_perm[i], x, y, z ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetCubic( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\treturn SingleCubic( 0, x * m_frequency, y * m_frequency, z * m_frequency );\r\n}\r\n\r\nconst FN_DECIMAL CUBIC_3D_BOUNDING = 1 / ( FN_DECIMAL( 1.5 ) * FN_DECIMAL( 1.5 ) * FN_DECIMAL( 1.5 ) );\r\n\r\nFN_DECIMAL FastNoise::SingleCubic( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tint x1 = FastFloor( x );\r\n\tint y1 = FastFloor( y );\r\n\tint z1 = FastFloor( z );\r\n\r\n\tint x0 = x1 - 1;\r\n\tint y0 = y1 - 1;\r\n\tint z0 = z1 - 1;\r\n\tint x2 = x1 + 1;\r\n\tint y2 = y1 + 1;\r\n\tint z2 = z1 + 1;\r\n\tint x3 = x1 + 2;\r\n\tint y3 = y1 + 2;\r\n\tint z3 = z1 + 2;\r\n\r\n\tFN_DECIMAL xs = x - (FN_DECIMAL)x1;\r\n\tFN_DECIMAL ys = y - (FN_DECIMAL)y1;\r\n\tFN_DECIMAL zs = z - (FN_DECIMAL)z1;\r\n\r\n\treturn CubicLerp(\r\n\t\t\t   CubicLerp(\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y0, z0 ), ValCoord3DFast( offset, x1, y0, z0 ), ValCoord3DFast( offset, x2, y0, z0 ), ValCoord3DFast( offset, x3, y0, z0 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y1, z0 ), ValCoord3DFast( offset, x1, y1, z0 ), ValCoord3DFast( offset, x2, y1, z0 ), ValCoord3DFast( offset, x3, y1, z0 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y2, z0 ), ValCoord3DFast( offset, x1, y2, z0 ), ValCoord3DFast( offset, x2, y2, z0 ), ValCoord3DFast( offset, x3, y2, z0 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y3, z0 ), ValCoord3DFast( offset, x1, y3, z0 ), ValCoord3DFast( offset, x2, y3, z0 ), ValCoord3DFast( offset, x3, y3, z0 ), xs ),\r\n\t\t\t\t   ys ),\r\n\t\t\t   CubicLerp(\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y0, z1 ), ValCoord3DFast( offset, x1, y0, z1 ), ValCoord3DFast( offset, x2, y0, z1 ), ValCoord3DFast( offset, x3, y0, z1 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y1, z1 ), ValCoord3DFast( offset, x1, y1, z1 ), ValCoord3DFast( offset, x2, y1, z1 ), ValCoord3DFast( offset, x3, y1, z1 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y2, z1 ), ValCoord3DFast( offset, x1, y2, z1 ), ValCoord3DFast( offset, x2, y2, z1 ), ValCoord3DFast( offset, x3, y2, z1 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y3, z1 ), ValCoord3DFast( offset, x1, y3, z1 ), ValCoord3DFast( offset, x2, y3, z1 ), ValCoord3DFast( offset, x3, y3, z1 ), xs ),\r\n\t\t\t\t   ys ),\r\n\t\t\t   CubicLerp(\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y0, z2 ), ValCoord3DFast( offset, x1, y0, z2 ), ValCoord3DFast( offset, x2, y0, z2 ), ValCoord3DFast( offset, x3, y0, z2 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y1, z2 ), ValCoord3DFast( offset, x1, y1, z2 ), ValCoord3DFast( offset, x2, y1, z2 ), ValCoord3DFast( offset, x3, y1, z2 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y2, z2 ), ValCoord3DFast( offset, x1, y2, z2 ), ValCoord3DFast( offset, x2, y2, z2 ), ValCoord3DFast( offset, x3, y2, z2 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y3, z2 ), ValCoord3DFast( offset, x1, y3, z2 ), ValCoord3DFast( offset, x2, y3, z2 ), ValCoord3DFast( offset, x3, y3, z2 ), xs ),\r\n\t\t\t\t   ys ),\r\n\t\t\t   CubicLerp(\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y0, z3 ), ValCoord3DFast( offset, x1, y0, z3 ), ValCoord3DFast( offset, x2, y0, z3 ), ValCoord3DFast( offset, x3, y0, z3 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y1, z3 ), ValCoord3DFast( offset, x1, y1, z3 ), ValCoord3DFast( offset, x2, y1, z3 ), ValCoord3DFast( offset, x3, y1, z3 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y2, z3 ), ValCoord3DFast( offset, x1, y2, z3 ), ValCoord3DFast( offset, x2, y2, z3 ), ValCoord3DFast( offset, x3, y2, z3 ), xs ),\r\n\t\t\t\t   CubicLerp( ValCoord3DFast( offset, x0, y3, z3 ), ValCoord3DFast( offset, x1, y3, z3 ), ValCoord3DFast( offset, x2, y3, z3 ), ValCoord3DFast( offset, x3, y3, z3 ), xs ),\r\n\t\t\t\t   ys ),\r\n\t\t\t   zs ) *\r\n\t\t   CUBIC_3D_BOUNDING;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetCubicFractal( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\tswitch ( m_fractalType )\r\n\t{\r\n\t\tcase FBM:\r\n\t\t\treturn SingleCubicFractalFBM( x, y );\r\n\t\tcase Billow:\r\n\t\t\treturn SingleCubicFractalBillow( x, y );\r\n\t\tcase RigidMulti:\r\n\t\t\treturn SingleCubicFractalRigidMulti( x, y );\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCubicFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = SingleCubic( m_perm[0], x, y );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += SingleCubic( m_perm[i], x, y ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCubicFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = FastAbs( SingleCubic( m_perm[0], x, y ) ) * 2 - 1;\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum += ( FastAbs( SingleCubic( m_perm[i], x, y ) ) * 2 - 1 ) * amp;\r\n\t}\r\n\r\n\treturn sum * m_fractalBounding;\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCubicFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tFN_DECIMAL sum = 1 - FastAbs( SingleCubic( m_perm[0], x, y ) );\r\n\tFN_DECIMAL amp = 1;\r\n\tint i          = 0;\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tx *= m_lacunarity;\r\n\t\ty *= m_lacunarity;\r\n\r\n\t\tamp *= m_gain;\r\n\t\tsum -= ( 1 - FastAbs( SingleCubic( m_perm[i], x, y ) ) ) * amp;\r\n\t}\r\n\r\n\treturn sum;\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetCubic( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\treturn SingleCubic( 0, x, y );\r\n}\r\n\r\nconst FN_DECIMAL CUBIC_2D_BOUNDING = 1 / ( FN_DECIMAL( 1.5 ) * FN_DECIMAL( 1.5 ) );\r\n\r\nFN_DECIMAL FastNoise::SingleCubic( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tint x1 = FastFloor( x );\r\n\tint y1 = FastFloor( y );\r\n\r\n\tint x0 = x1 - 1;\r\n\tint y0 = y1 - 1;\r\n\tint x2 = x1 + 1;\r\n\tint y2 = y1 + 1;\r\n\tint x3 = x1 + 2;\r\n\tint y3 = y1 + 2;\r\n\r\n\tFN_DECIMAL xs = x - (FN_DECIMAL)x1;\r\n\tFN_DECIMAL ys = y - (FN_DECIMAL)y1;\r\n\r\n\treturn CubicLerp(\r\n\t\t\t   CubicLerp( ValCoord2DFast( offset, x0, y0 ), ValCoord2DFast( offset, x1, y0 ), ValCoord2DFast( offset, x2, y0 ), ValCoord2DFast( offset, x3, y0 ), xs ),\r\n\t\t\t   CubicLerp( ValCoord2DFast( offset, x0, y1 ), ValCoord2DFast( offset, x1, y1 ), ValCoord2DFast( offset, x2, y1 ), ValCoord2DFast( offset, x3, y1 ), xs ),\r\n\t\t\t   CubicLerp( ValCoord2DFast( offset, x0, y2 ), ValCoord2DFast( offset, x1, y2 ), ValCoord2DFast( offset, x2, y2 ), ValCoord2DFast( offset, x3, y2 ), xs ),\r\n\t\t\t   CubicLerp( ValCoord2DFast( offset, x0, y3 ), ValCoord2DFast( offset, x1, y3 ), ValCoord2DFast( offset, x2, y3 ), ValCoord2DFast( offset, x3, y3 ), xs ),\r\n\t\t\t   ys ) *\r\n\t\t   CUBIC_2D_BOUNDING;\r\n}\r\n\r\n// Cellular Noise\r\nFN_DECIMAL FastNoise::GetCellular( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\tz *= m_frequency;\r\n\r\n\tswitch ( m_cellularReturnType )\r\n\t{\r\n\t\tcase CellValue:\r\n\t\tcase NoiseLookup:\r\n\t\tcase Distance:\r\n\t\t\treturn SingleCellular( x, y, z );\r\n\t\tdefault:\r\n\t\t\treturn SingleCellular2Edge( x, y, z );\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCellular( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tint xr = FastRound( x );\r\n\tint yr = FastRound( y );\r\n\tint zr = FastRound( z );\r\n\r\n\tFN_DECIMAL distance = 999999;\r\n\tint xc, yc, zc;\r\n\r\n\tswitch ( m_cellularDistanceFunction )\r\n\t{\r\n\t\tcase Euclidean:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int zi = zr - 1; zi <= zr + 1; zi++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char lutPos = Index3D_256( 0, xi, yi, zi );\r\n\r\n\t\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_3D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_3D_Y[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecZ = zi - z + CELL_3D_Z[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\t\tFN_DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;\r\n\r\n\t\t\t\t\t\tif ( newDistance < distance )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdistance = newDistance;\r\n\t\t\t\t\t\t\txc       = xi;\r\n\t\t\t\t\t\t\tyc       = yi;\r\n\t\t\t\t\t\t\tzc       = zi;\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\tbreak;\r\n\t\tcase Manhattan:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int zi = zr - 1; zi <= zr + 1; zi++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char lutPos = Index3D_256( 0, xi, yi, zi );\r\n\r\n\t\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_3D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_3D_Y[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecZ = zi - z + CELL_3D_Z[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\t\tFN_DECIMAL newDistance = FastAbs( vecX ) + FastAbs( vecY ) + FastAbs( vecZ );\r\n\r\n\t\t\t\t\t\tif ( newDistance < distance )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdistance = newDistance;\r\n\t\t\t\t\t\t\txc       = xi;\r\n\t\t\t\t\t\t\tyc       = yi;\r\n\t\t\t\t\t\t\tzc       = zi;\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\tbreak;\r\n\t\tcase Natural:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int zi = zr - 1; zi <= zr + 1; zi++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char lutPos = Index3D_256( 0, xi, yi, zi );\r\n\r\n\t\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_3D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_3D_Y[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecZ = zi - z + CELL_3D_Z[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\t\tFN_DECIMAL newDistance = ( FastAbs( vecX ) + FastAbs( vecY ) + FastAbs( vecZ ) ) + ( vecX * vecX + vecY * vecY + vecZ * vecZ );\r\n\r\n\t\t\t\t\t\tif ( newDistance < distance )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdistance = newDistance;\r\n\t\t\t\t\t\t\txc       = xi;\r\n\t\t\t\t\t\t\tyc       = yi;\r\n\t\t\t\t\t\t\tzc       = zi;\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\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tunsigned char lutPos;\r\n\tswitch ( m_cellularReturnType )\r\n\t{\r\n\t\tcase CellValue:\r\n\t\t\treturn ValCoord3D( m_seed, xc, yc, zc );\r\n\r\n\t\tcase NoiseLookup:\r\n\t\t\tassert( m_cellularNoiseLookup );\r\n\r\n\t\t\tlutPos = Index3D_256( 0, xc, yc, zc );\r\n\t\t\treturn m_cellularNoiseLookup->GetNoise( xc + CELL_3D_X[lutPos] * m_cellularJitter, yc + CELL_3D_Y[lutPos] * m_cellularJitter, zc + CELL_3D_Z[lutPos] * m_cellularJitter );\r\n\r\n\t\tcase Distance:\r\n\t\t\treturn distance;\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCellular2Edge( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const\r\n{\r\n\tint xr = FastRound( x );\r\n\tint yr = FastRound( y );\r\n\tint zr = FastRound( z );\r\n\r\n\tFN_DECIMAL distance[FN_CELLULAR_INDEX_MAX + 1] = { 999999, 999999, 999999, 999999 };\r\n\r\n\tswitch ( m_cellularDistanceFunction )\r\n\t{\r\n\t\tcase Euclidean:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int zi = zr - 1; zi <= zr + 1; zi++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char lutPos = Index3D_256( 0, xi, yi, zi );\r\n\r\n\t\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_3D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_3D_Y[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecZ = zi - z + CELL_3D_Z[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\t\tFN_DECIMAL newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;\r\n\r\n\t\t\t\t\t\tfor ( int i = m_cellularDistanceIndex1; i > 0; i-- )\r\n\t\t\t\t\t\t\tdistance[i] = fmax( fmin( distance[i], newDistance ), distance[i - 1] );\r\n\t\t\t\t\t\tdistance[0] = fmin( distance[0], newDistance );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Manhattan:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int zi = zr - 1; zi <= zr + 1; zi++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char lutPos = Index3D_256( 0, xi, yi, zi );\r\n\r\n\t\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_3D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_3D_Y[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecZ = zi - z + CELL_3D_Z[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\t\tFN_DECIMAL newDistance = FastAbs( vecX ) + FastAbs( vecY ) + FastAbs( vecZ );\r\n\r\n\t\t\t\t\t\tfor ( int i = m_cellularDistanceIndex1; i > 0; i-- )\r\n\t\t\t\t\t\t\tdistance[i] = fmax( fmin( distance[i], newDistance ), distance[i - 1] );\r\n\t\t\t\t\t\tdistance[0] = fmin( distance[0], newDistance );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Natural:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int zi = zr - 1; zi <= zr + 1; zi++ )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned char lutPos = Index3D_256( 0, xi, yi, zi );\r\n\r\n\t\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_3D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_3D_Y[lutPos] * m_cellularJitter;\r\n\t\t\t\t\t\tFN_DECIMAL vecZ = zi - z + CELL_3D_Z[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\t\tFN_DECIMAL newDistance = ( FastAbs( vecX ) + FastAbs( vecY ) + FastAbs( vecZ ) ) + ( vecX * vecX + vecY * vecY + vecZ * vecZ );\r\n\r\n\t\t\t\t\t\tfor ( int i = m_cellularDistanceIndex1; i > 0; i-- )\r\n\t\t\t\t\t\t\tdistance[i] = fmax( fmin( distance[i], newDistance ), distance[i - 1] );\r\n\t\t\t\t\t\tdistance[0] = fmin( distance[0], newDistance );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tswitch ( m_cellularReturnType )\r\n\t{\r\n\t\tcase Distance2:\r\n\t\t\treturn distance[m_cellularDistanceIndex1];\r\n\t\tcase Distance2Add:\r\n\t\t\treturn distance[m_cellularDistanceIndex1] + distance[m_cellularDistanceIndex0];\r\n\t\tcase Distance2Sub:\r\n\t\t\treturn distance[m_cellularDistanceIndex1] - distance[m_cellularDistanceIndex0];\r\n\t\tcase Distance2Mul:\r\n\t\t\treturn distance[m_cellularDistanceIndex1] * distance[m_cellularDistanceIndex0];\r\n\t\tcase Distance2Div:\r\n\t\t\treturn distance[m_cellularDistanceIndex0] / distance[m_cellularDistanceIndex1];\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::GetCellular( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tx *= m_frequency;\r\n\ty *= m_frequency;\r\n\r\n\tswitch ( m_cellularReturnType )\r\n\t{\r\n\t\tcase CellValue:\r\n\t\tcase NoiseLookup:\r\n\t\tcase Distance:\r\n\t\t\treturn SingleCellular( x, y );\r\n\t\tdefault:\r\n\t\t\treturn SingleCellular2Edge( x, y );\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCellular( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tint xr = FastRound( x );\r\n\tint yr = FastRound( y );\r\n\r\n\tFN_DECIMAL distance = 999999;\r\n\tint xc, yc;\r\n\r\n\tswitch ( m_cellularDistanceFunction )\r\n\t{\r\n\t\tdefault:\r\n\t\tcase Euclidean:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char lutPos = Index2D_256( 0, xi, yi );\r\n\r\n\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_2D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_2D_Y[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\tFN_DECIMAL newDistance = vecX * vecX + vecY * vecY;\r\n\r\n\t\t\t\t\tif ( newDistance < distance )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdistance = newDistance;\r\n\t\t\t\t\t\txc       = xi;\r\n\t\t\t\t\t\tyc       = yi;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Manhattan:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char lutPos = Index2D_256( 0, xi, yi );\r\n\r\n\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_2D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_2D_Y[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\tFN_DECIMAL newDistance = ( FastAbs( vecX ) + FastAbs( vecY ) );\r\n\r\n\t\t\t\t\tif ( newDistance < distance )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdistance = newDistance;\r\n\t\t\t\t\t\txc       = xi;\r\n\t\t\t\t\t\tyc       = yi;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Natural:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char lutPos = Index2D_256( 0, xi, yi );\r\n\r\n\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_2D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_2D_Y[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\tFN_DECIMAL newDistance = ( FastAbs( vecX ) + FastAbs( vecY ) ) + ( vecX * vecX + vecY * vecY );\r\n\r\n\t\t\t\t\tif ( newDistance < distance )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdistance = newDistance;\r\n\t\t\t\t\t\txc       = xi;\r\n\t\t\t\t\t\tyc       = yi;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tunsigned char lutPos;\r\n\tswitch ( m_cellularReturnType )\r\n\t{\r\n\t\tcase CellValue:\r\n\t\t\treturn ValCoord2D( m_seed, xc, yc );\r\n\r\n\t\tcase NoiseLookup:\r\n\t\t\tassert( m_cellularNoiseLookup );\r\n\r\n\t\t\tlutPos = Index2D_256( 0, xc, yc );\r\n\t\t\treturn m_cellularNoiseLookup->GetNoise( xc + CELL_2D_X[lutPos] * m_cellularJitter, yc + CELL_2D_Y[lutPos] * m_cellularJitter );\r\n\r\n\t\tcase Distance:\r\n\t\t\treturn distance;\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nFN_DECIMAL FastNoise::SingleCellular2Edge( FN_DECIMAL x, FN_DECIMAL y ) const\r\n{\r\n\tint xr = FastRound( x );\r\n\tint yr = FastRound( y );\r\n\r\n\tFN_DECIMAL distance[FN_CELLULAR_INDEX_MAX + 1] = { 999999, 999999, 999999, 999999 };\r\n\r\n\tswitch ( m_cellularDistanceFunction )\r\n\t{\r\n\t\tdefault:\r\n\t\tcase Euclidean:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char lutPos = Index2D_256( 0, xi, yi );\r\n\r\n\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_2D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_2D_Y[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\tFN_DECIMAL newDistance = vecX * vecX + vecY * vecY;\r\n\r\n\t\t\t\t\tfor ( int i = m_cellularDistanceIndex1; i > 0; i-- )\r\n\t\t\t\t\t\tdistance[i] = fmax( fmin( distance[i], newDistance ), distance[i - 1] );\r\n\t\t\t\t\tdistance[0] = fmin( distance[0], newDistance );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Manhattan:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char lutPos = Index2D_256( 0, xi, yi );\r\n\r\n\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_2D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_2D_Y[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\tFN_DECIMAL newDistance = FastAbs( vecX ) + FastAbs( vecY );\r\n\r\n\t\t\t\t\tfor ( int i = m_cellularDistanceIndex1; i > 0; i-- )\r\n\t\t\t\t\t\tdistance[i] = fmax( fmin( distance[i], newDistance ), distance[i - 1] );\r\n\t\t\t\t\tdistance[0] = fmin( distance[0], newDistance );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase Natural:\r\n\t\t\tfor ( int xi = xr - 1; xi <= xr + 1; xi++ )\r\n\t\t\t{\r\n\t\t\t\tfor ( int yi = yr - 1; yi <= yr + 1; yi++ )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char lutPos = Index2D_256( 0, xi, yi );\r\n\r\n\t\t\t\t\tFN_DECIMAL vecX = xi - x + CELL_2D_X[lutPos] * m_cellularJitter;\r\n\t\t\t\t\tFN_DECIMAL vecY = yi - y + CELL_2D_Y[lutPos] * m_cellularJitter;\r\n\r\n\t\t\t\t\tFN_DECIMAL newDistance = ( FastAbs( vecX ) + FastAbs( vecY ) ) + ( vecX * vecX + vecY * vecY );\r\n\r\n\t\t\t\t\tfor ( int i = m_cellularDistanceIndex1; i > 0; i-- )\r\n\t\t\t\t\t\tdistance[i] = fmax( fmin( distance[i], newDistance ), distance[i - 1] );\r\n\t\t\t\t\tdistance[0] = fmin( distance[0], newDistance );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tswitch ( m_cellularReturnType )\r\n\t{\r\n\t\tcase Distance2:\r\n\t\t\treturn distance[m_cellularDistanceIndex1];\r\n\t\tcase Distance2Add:\r\n\t\t\treturn distance[m_cellularDistanceIndex1] + distance[m_cellularDistanceIndex0];\r\n\t\tcase Distance2Sub:\r\n\t\t\treturn distance[m_cellularDistanceIndex1] - distance[m_cellularDistanceIndex0];\r\n\t\tcase Distance2Mul:\r\n\t\t\treturn distance[m_cellularDistanceIndex1] * distance[m_cellularDistanceIndex0];\r\n\t\tcase Distance2Div:\r\n\t\t\treturn distance[m_cellularDistanceIndex0] / distance[m_cellularDistanceIndex1];\r\n\t\tdefault:\r\n\t\t\treturn 0;\r\n\t}\r\n}\r\n\r\nvoid FastNoise::GradientPerturb( FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z ) const\r\n{\r\n\tSingleGradientPerturb( 0, m_gradientPerturbAmp, m_frequency, x, y, z );\r\n}\r\n\r\nvoid FastNoise::GradientPerturbFractal( FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z ) const\r\n{\r\n\tFN_DECIMAL amp  = m_gradientPerturbAmp * m_fractalBounding;\r\n\tFN_DECIMAL freq = m_frequency;\r\n\tint i           = 0;\r\n\r\n\tSingleGradientPerturb( m_perm[0], amp, m_frequency, x, y, z );\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tfreq *= m_lacunarity;\r\n\t\tamp *= m_gain;\r\n\t\tSingleGradientPerturb( m_perm[i], amp, freq, x, y, z );\r\n\t}\r\n}\r\n\r\nvoid FastNoise::SingleGradientPerturb( unsigned char offset, FN_DECIMAL warpAmp, FN_DECIMAL frequency, FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z ) const\r\n{\r\n\tFN_DECIMAL xf = x * frequency;\r\n\tFN_DECIMAL yf = y * frequency;\r\n\tFN_DECIMAL zf = z * frequency;\r\n\r\n\tint x0 = FastFloor( xf );\r\n\tint y0 = FastFloor( yf );\r\n\tint z0 = FastFloor( zf );\r\n\tint x1 = x0 + 1;\r\n\tint y1 = y0 + 1;\r\n\tint z1 = z0 + 1;\r\n\r\n\tFN_DECIMAL xs, ys, zs;\r\n\tswitch ( m_interp )\r\n\t{\r\n\t\tdefault:\r\n\t\tcase Linear:\r\n\t\t\txs = xf - (FN_DECIMAL)x0;\r\n\t\t\tys = yf - (FN_DECIMAL)y0;\r\n\t\t\tzs = zf - (FN_DECIMAL)z0;\r\n\t\t\tbreak;\r\n\t\tcase Hermite:\r\n\t\t\txs = InterpHermiteFunc( xf - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpHermiteFunc( yf - (FN_DECIMAL)y0 );\r\n\t\t\tzs = InterpHermiteFunc( zf - (FN_DECIMAL)z0 );\r\n\t\t\tbreak;\r\n\t\tcase Quintic:\r\n\t\t\txs = InterpQuinticFunc( xf - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpQuinticFunc( yf - (FN_DECIMAL)y0 );\r\n\t\t\tzs = InterpQuinticFunc( zf - (FN_DECIMAL)z0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tint lutPos0 = Index3D_256( offset, x0, y0, z0 );\r\n\tint lutPos1 = Index3D_256( offset, x1, y0, z0 );\r\n\r\n\tFN_DECIMAL lx0x = Lerp( CELL_3D_X[lutPos0], CELL_3D_X[lutPos1], xs );\r\n\tFN_DECIMAL ly0x = Lerp( CELL_3D_Y[lutPos0], CELL_3D_Y[lutPos1], xs );\r\n\tFN_DECIMAL lz0x = Lerp( CELL_3D_Z[lutPos0], CELL_3D_Z[lutPos1], xs );\r\n\r\n\tlutPos0 = Index3D_256( offset, x0, y1, z0 );\r\n\tlutPos1 = Index3D_256( offset, x1, y1, z0 );\r\n\r\n\tFN_DECIMAL lx1x = Lerp( CELL_3D_X[lutPos0], CELL_3D_X[lutPos1], xs );\r\n\tFN_DECIMAL ly1x = Lerp( CELL_3D_Y[lutPos0], CELL_3D_Y[lutPos1], xs );\r\n\tFN_DECIMAL lz1x = Lerp( CELL_3D_Z[lutPos0], CELL_3D_Z[lutPos1], xs );\r\n\r\n\tFN_DECIMAL lx0y = Lerp( lx0x, lx1x, ys );\r\n\tFN_DECIMAL ly0y = Lerp( ly0x, ly1x, ys );\r\n\tFN_DECIMAL lz0y = Lerp( lz0x, lz1x, ys );\r\n\r\n\tlutPos0 = Index3D_256( offset, x0, y0, z1 );\r\n\tlutPos1 = Index3D_256( offset, x1, y0, z1 );\r\n\r\n\tlx0x = Lerp( CELL_3D_X[lutPos0], CELL_3D_X[lutPos1], xs );\r\n\tly0x = Lerp( CELL_3D_Y[lutPos0], CELL_3D_Y[lutPos1], xs );\r\n\tlz0x = Lerp( CELL_3D_Z[lutPos0], CELL_3D_Z[lutPos1], xs );\r\n\r\n\tlutPos0 = Index3D_256( offset, x0, y1, z1 );\r\n\tlutPos1 = Index3D_256( offset, x1, y1, z1 );\r\n\r\n\tlx1x = Lerp( CELL_3D_X[lutPos0], CELL_3D_X[lutPos1], xs );\r\n\tly1x = Lerp( CELL_3D_Y[lutPos0], CELL_3D_Y[lutPos1], xs );\r\n\tlz1x = Lerp( CELL_3D_Z[lutPos0], CELL_3D_Z[lutPos1], xs );\r\n\r\n\tx += Lerp( lx0y, Lerp( lx0x, lx1x, ys ), zs ) * warpAmp;\r\n\ty += Lerp( ly0y, Lerp( ly0x, ly1x, ys ), zs ) * warpAmp;\r\n\tz += Lerp( lz0y, Lerp( lz0x, lz1x, ys ), zs ) * warpAmp;\r\n}\r\n\r\nvoid FastNoise::GradientPerturb( FN_DECIMAL& x, FN_DECIMAL& y ) const\r\n{\r\n\tSingleGradientPerturb( 0, m_gradientPerturbAmp, m_frequency, x, y );\r\n}\r\n\r\nvoid FastNoise::GradientPerturbFractal( FN_DECIMAL& x, FN_DECIMAL& y ) const\r\n{\r\n\tFN_DECIMAL amp  = m_gradientPerturbAmp * m_fractalBounding;\r\n\tFN_DECIMAL freq = m_frequency;\r\n\tint i           = 0;\r\n\r\n\tSingleGradientPerturb( m_perm[0], amp, m_frequency, x, y );\r\n\r\n\twhile ( ++i < m_octaves )\r\n\t{\r\n\t\tfreq *= m_lacunarity;\r\n\t\tamp *= m_gain;\r\n\t\tSingleGradientPerturb( m_perm[i], amp, freq, x, y );\r\n\t}\r\n}\r\n\r\nvoid FastNoise::SingleGradientPerturb( unsigned char offset, FN_DECIMAL warpAmp, FN_DECIMAL frequency, FN_DECIMAL& x, FN_DECIMAL& y ) const\r\n{\r\n\tFN_DECIMAL xf = x * frequency;\r\n\tFN_DECIMAL yf = y * frequency;\r\n\r\n\tint x0 = FastFloor( xf );\r\n\tint y0 = FastFloor( yf );\r\n\tint x1 = x0 + 1;\r\n\tint y1 = y0 + 1;\r\n\r\n\tFN_DECIMAL xs, ys;\r\n\tswitch ( m_interp )\r\n\t{\r\n\t\tdefault:\r\n\t\tcase Linear:\r\n\t\t\txs = xf - (FN_DECIMAL)x0;\r\n\t\t\tys = yf - (FN_DECIMAL)y0;\r\n\t\t\tbreak;\r\n\t\tcase Hermite:\r\n\t\t\txs = InterpHermiteFunc( xf - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpHermiteFunc( yf - (FN_DECIMAL)y0 );\r\n\t\t\tbreak;\r\n\t\tcase Quintic:\r\n\t\t\txs = InterpQuinticFunc( xf - (FN_DECIMAL)x0 );\r\n\t\t\tys = InterpQuinticFunc( yf - (FN_DECIMAL)y0 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tint lutPos0 = Index2D_256( offset, x0, y0 );\r\n\tint lutPos1 = Index2D_256( offset, x1, y0 );\r\n\r\n\tFN_DECIMAL lx0x = Lerp( CELL_2D_X[lutPos0], CELL_2D_X[lutPos1], xs );\r\n\tFN_DECIMAL ly0x = Lerp( CELL_2D_Y[lutPos0], CELL_2D_Y[lutPos1], xs );\r\n\r\n\tlutPos0 = Index2D_256( offset, x0, y1 );\r\n\tlutPos1 = Index2D_256( offset, x1, y1 );\r\n\r\n\tFN_DECIMAL lx1x = Lerp( CELL_2D_X[lutPos0], CELL_2D_X[lutPos1], xs );\r\n\tFN_DECIMAL ly1x = Lerp( CELL_2D_Y[lutPos0], CELL_2D_Y[lutPos1], xs );\r\n\r\n\tx += Lerp( lx0x, lx1x, ys ) * warpAmp;\r\n\ty += Lerp( ly0x, ly1x, ys ) * warpAmp;\r\n}\r\n"
  },
  {
    "path": "3rdparty/fastnoise/FastNoise.h",
    "content": "// FastNoise.h\r\n//\r\n// MIT License\r\n//\r\n// Copyright(c) 2017 Jordan Peck\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy\r\n// of this software and associated documentation files(the \"Software\"), to deal\r\n// in the Software without restriction, including without limitation the rights\r\n// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is\r\n// furnished to do so, subject to the following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all\r\n// copies or substantial portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE\r\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n// SOFTWARE.\r\n//\r\n// The developer's email is jorzixdan.me2@gzixmail.com (for great email, take\r\n// off every 'zix'.)\r\n//\r\n\r\n// VERSION: 0.4.1\r\n\r\n#ifndef FASTNOISE_H\r\n#define FASTNOISE_H\r\n\r\n// Uncomment the line below to use doubles throughout FastNoise instead of floats\r\n//#define FN_USE_DOUBLES\r\n\r\n#define FN_CELLULAR_INDEX_MAX 3\r\n\r\n#ifdef FN_USE_DOUBLES\r\ntypedef double FN_DECIMAL;\r\n#else\r\ntypedef float FN_DECIMAL;\r\n#endif\r\n\r\nclass FastNoise\r\n{\r\npublic:\r\n\texplicit FastNoise( int seed = 1337 )\r\n\t{\r\n\t\tSetSeed( seed );\r\n\t\tCalculateFractalBounding();\r\n\t}\r\n\r\n\tenum NoiseType\r\n\t{\r\n\t\tValue,\r\n\t\tValueFractal,\r\n\t\tPerlin,\r\n\t\tPerlinFractal,\r\n\t\tSimplex,\r\n\t\tSimplexFractal,\r\n\t\tCellular,\r\n\t\tWhiteNoise,\r\n\t\tCubic,\r\n\t\tCubicFractal\r\n\t};\r\n\tenum Interp\r\n\t{\r\n\t\tLinear,\r\n\t\tHermite,\r\n\t\tQuintic\r\n\t};\r\n\tenum FractalType\r\n\t{\r\n\t\tFBM,\r\n\t\tBillow,\r\n\t\tRigidMulti\r\n\t};\r\n\tenum CellularDistanceFunction\r\n\t{\r\n\t\tEuclidean,\r\n\t\tManhattan,\r\n\t\tNatural\r\n\t};\r\n\tenum CellularReturnType\r\n\t{\r\n\t\tCellValue,\r\n\t\tNoiseLookup,\r\n\t\tDistance,\r\n\t\tDistance2,\r\n\t\tDistance2Add,\r\n\t\tDistance2Sub,\r\n\t\tDistance2Mul,\r\n\t\tDistance2Div\r\n\t};\r\n\r\n\t// Sets seed used for all noise types\r\n\t// Default: 1337\r\n\tvoid SetSeed( int seed );\r\n\r\n\t// Returns seed used for all noise types\r\n\tint GetSeed() const\r\n\t{\r\n\t\treturn m_seed;\r\n\t}\r\n\r\n\t// Sets frequency for all noise types\r\n\t// Default: 0.01\r\n\tvoid SetFrequency( FN_DECIMAL frequency )\r\n\t{\r\n\t\tm_frequency = frequency;\r\n\t}\r\n\r\n\t// Returns frequency used for all noise types\r\n\tFN_DECIMAL GetFrequency() const\r\n\t{\r\n\t\treturn m_frequency;\r\n\t}\r\n\r\n\t// Changes the interpolation method used to smooth between noise values\r\n\t// Possible interpolation methods (lowest to highest quality) :\r\n\t// - Linear\r\n\t// - Hermite\r\n\t// - Quintic\r\n\t// Used in Value, Perlin Noise and Position Warping\r\n\t// Default: Quintic\r\n\tvoid SetInterp( Interp interp )\r\n\t{\r\n\t\tm_interp = interp;\r\n\t}\r\n\r\n\t// Returns interpolation method used for supported noise types\r\n\tInterp GetInterp() const\r\n\t{\r\n\t\treturn m_interp;\r\n\t}\r\n\r\n\t// Sets noise return type of GetNoise(...)\r\n\t// Default: Simplex\r\n\tvoid SetNoiseType( NoiseType noiseType )\r\n\t{\r\n\t\tm_noiseType = noiseType;\r\n\t}\r\n\r\n\t// Returns the noise type used by GetNoise\r\n\tNoiseType GetNoiseType() const\r\n\t{\r\n\t\treturn m_noiseType;\r\n\t}\r\n\r\n\t// Sets octave count for all fractal noise types\r\n\t// Default: 3\r\n\tvoid SetFractalOctaves( int octaves )\r\n\t{\r\n\t\tm_octaves = octaves;\r\n\t\tCalculateFractalBounding();\r\n\t}\r\n\r\n\t// Returns octave count for all fractal noise types\r\n\tint GetFractalOctaves() const\r\n\t{\r\n\t\treturn m_octaves;\r\n\t}\r\n\r\n\t// Sets octave lacunarity for all fractal noise types\r\n\t// Default: 2.0\r\n\tvoid SetFractalLacunarity( FN_DECIMAL lacunarity )\r\n\t{\r\n\t\tm_lacunarity = lacunarity;\r\n\t}\r\n\r\n\t// Returns octave lacunarity for all fractal noise types\r\n\tFN_DECIMAL GetFractalLacunarity() const\r\n\t{\r\n\t\treturn m_lacunarity;\r\n\t}\r\n\r\n\t// Sets octave gain for all fractal noise types\r\n\t// Default: 0.5\r\n\tvoid SetFractalGain( FN_DECIMAL gain )\r\n\t{\r\n\t\tm_gain = gain;\r\n\t\tCalculateFractalBounding();\r\n\t}\r\n\r\n\t// Returns octave gain for all fractal noise types\r\n\tFN_DECIMAL GetFractalGain() const\r\n\t{\r\n\t\treturn m_gain;\r\n\t}\r\n\r\n\t// Sets method for combining octaves in all fractal noise types\r\n\t// Default: FBM\r\n\tvoid SetFractalType( FractalType fractalType )\r\n\t{\r\n\t\tm_fractalType = fractalType;\r\n\t}\r\n\r\n\t// Returns method for combining octaves in all fractal noise types\r\n\tFractalType GetFractalType() const\r\n\t{\r\n\t\treturn m_fractalType;\r\n\t}\r\n\r\n\t// Sets distance function used in cellular noise calculations\r\n\t// Default: Euclidean\r\n\tvoid SetCellularDistanceFunction( CellularDistanceFunction cellularDistanceFunction )\r\n\t{\r\n\t\tm_cellularDistanceFunction = cellularDistanceFunction;\r\n\t}\r\n\r\n\t// Returns the distance function used in cellular noise calculations\r\n\tCellularDistanceFunction GetCellularDistanceFunction() const\r\n\t{\r\n\t\treturn m_cellularDistanceFunction;\r\n\t}\r\n\r\n\t// Sets return type from cellular noise calculations\r\n\t// Note: NoiseLookup requires another FastNoise object be set with SetCellularNoiseLookup() to function\r\n\t// Default: CellValue\r\n\tvoid SetCellularReturnType( CellularReturnType cellularReturnType )\r\n\t{\r\n\t\tm_cellularReturnType = cellularReturnType;\r\n\t}\r\n\r\n\t// Returns the return type from cellular noise calculations\r\n\tCellularReturnType GetCellularReturnType() const\r\n\t{\r\n\t\treturn m_cellularReturnType;\r\n\t}\r\n\r\n\t// Noise used to calculate a cell value if cellular return type is NoiseLookup\r\n\t// The lookup value is acquired through GetNoise() so ensure you SetNoiseType() on the noise lookup, value, Perlin or simplex is recommended\r\n\tvoid SetCellularNoiseLookup( FastNoise* noise )\r\n\t{\r\n\t\tm_cellularNoiseLookup = noise;\r\n\t}\r\n\r\n\t// Returns the noise used to calculate a cell value if the cellular return type is NoiseLookup\r\n\tFastNoise* GetCellularNoiseLookup() const\r\n\t{\r\n\t\treturn m_cellularNoiseLookup;\r\n\t}\r\n\r\n\t// Sets the 2 distance indices used for distance2 return types\r\n\t// Default: 0, 1\r\n\t// Note: index0 should be lower than index1\r\n\t// Both indices must be >= 0, index1 must be < 4\r\n\tvoid SetCellularDistance2Indices( int cellularDistanceIndex0, int cellularDistanceIndex1 );\r\n\r\n\t// Returns the 2 distance indices used for distance2 return types\r\n\tvoid GetCellularDistance2Indices( int& cellularDistanceIndex0, int& cellularDistanceIndex1 ) const;\r\n\r\n\t// Sets the maximum distance a cellular point can move from its grid position\r\n\t// Setting this high will make artifacts more common\r\n\t// Default: 0.45\r\n\tvoid SetCellularJitter( FN_DECIMAL cellularJitter )\r\n\t{\r\n\t\tm_cellularJitter = cellularJitter;\r\n\t}\r\n\r\n\t// Returns the maximum distance a cellular point can move from its grid position\r\n\tFN_DECIMAL GetCellularJitter() const\r\n\t{\r\n\t\treturn m_cellularJitter;\r\n\t}\r\n\r\n\t// Sets the maximum warp distance from original location when using GradientPerturb{Fractal}(...)\r\n\t// Default: 1.0\r\n\tvoid SetGradientPerturbAmp( FN_DECIMAL gradientPerturbAmp )\r\n\t{\r\n\t\tm_gradientPerturbAmp = gradientPerturbAmp;\r\n\t}\r\n\r\n\t// Returns the maximum warp distance from original location when using GradientPerturb{Fractal}(...)\r\n\tFN_DECIMAL GetGradientPerturbAmp() const\r\n\t{\r\n\t\treturn m_gradientPerturbAmp;\r\n\t}\r\n\r\n\t//2D\r\n\tFN_DECIMAL GetValue( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL GetValueFractal( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL GetPerlin( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL GetPerlinFractal( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL GetSimplex( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL GetSimplexFractal( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL GetCellular( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL GetWhiteNoise( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL GetWhiteNoiseInt( int x, int y ) const;\r\n\r\n\tFN_DECIMAL GetCubic( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL GetCubicFractal( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL GetNoise( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tvoid GradientPerturb( FN_DECIMAL& x, FN_DECIMAL& y ) const;\r\n\tvoid GradientPerturbFractal( FN_DECIMAL& x, FN_DECIMAL& y ) const;\r\n\r\n\t//3D\r\n\tFN_DECIMAL GetValue( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL GetValueFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL GetPerlin( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL GetPerlinFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL GetSimplex( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL GetSimplexFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL GetCellular( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL GetWhiteNoise( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL GetWhiteNoiseInt( int x, int y, int z ) const;\r\n\r\n\tFN_DECIMAL GetCubic( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL GetCubicFractal( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL GetNoise( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tvoid GradientPerturb( FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z ) const;\r\n\tvoid GradientPerturbFractal( FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z ) const;\r\n\r\n\t//4D\r\n\tFN_DECIMAL GetSimplex( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w ) const;\r\n\r\n\tFN_DECIMAL GetWhiteNoise( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w ) const;\r\n\tFN_DECIMAL GetWhiteNoiseInt( int x, int y, int z, int w ) const;\r\n\r\nprivate:\r\n\tunsigned char m_perm[512];\r\n\tunsigned char m_perm12[512];\r\n\r\n\tint m_seed             = 1337;\r\n\tFN_DECIMAL m_frequency = FN_DECIMAL( 0.01 );\r\n\tInterp m_interp        = Quintic;\r\n\tNoiseType m_noiseType  = Simplex;\r\n\r\n\tint m_octaves             = 3;\r\n\tFN_DECIMAL m_lacunarity   = FN_DECIMAL( 2 );\r\n\tFN_DECIMAL m_gain         = FN_DECIMAL( 0.5 );\r\n\tFractalType m_fractalType = FBM;\r\n\tFN_DECIMAL m_fractalBounding;\r\n\r\n\tCellularDistanceFunction m_cellularDistanceFunction = Euclidean;\r\n\tCellularReturnType m_cellularReturnType             = CellValue;\r\n\tFastNoise* m_cellularNoiseLookup                    = nullptr;\r\n\tint m_cellularDistanceIndex0                        = 0;\r\n\tint m_cellularDistanceIndex1                        = 1;\r\n\tFN_DECIMAL m_cellularJitter                         = FN_DECIMAL( 0.45 );\r\n\r\n\tFN_DECIMAL m_gradientPerturbAmp = FN_DECIMAL( 1 );\r\n\r\n\tvoid CalculateFractalBounding();\r\n\r\n\t//2D\r\n\tFN_DECIMAL SingleValueFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleValueFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleValueFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleValue( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL SinglePerlinFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SinglePerlinFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SinglePerlinFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SinglePerlin( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL SingleSimplexFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleSimplexFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleSimplexFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleSimplexFractalBlend( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleSimplex( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL SingleCubicFractalFBM( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleCubicFractalBillow( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleCubicFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleCubic( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tFN_DECIMAL SingleCellular( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\tFN_DECIMAL SingleCellular2Edge( FN_DECIMAL x, FN_DECIMAL y ) const;\r\n\r\n\tvoid SingleGradientPerturb( unsigned char offset, FN_DECIMAL warpAmp, FN_DECIMAL frequency, FN_DECIMAL& x, FN_DECIMAL& y ) const;\r\n\r\n\t//3D\r\n\tFN_DECIMAL SingleValueFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleValueFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleValueFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleValue( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL SinglePerlinFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SinglePerlinFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SinglePerlinFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SinglePerlin( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL SingleSimplexFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleSimplexFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleSimplexFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleSimplex( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL SingleCubicFractalFBM( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleCubicFractalBillow( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleCubicFractalRigidMulti( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleCubic( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tFN_DECIMAL SingleCellular( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\tFN_DECIMAL SingleCellular2Edge( FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z ) const;\r\n\r\n\tvoid SingleGradientPerturb( unsigned char offset, FN_DECIMAL warpAmp, FN_DECIMAL frequency, FN_DECIMAL& x, FN_DECIMAL& y, FN_DECIMAL& z ) const;\r\n\r\n\t//4D\r\n\tFN_DECIMAL SingleSimplex( unsigned char offset, FN_DECIMAL x, FN_DECIMAL y, FN_DECIMAL z, FN_DECIMAL w ) const;\r\n\r\n\tinline unsigned char Index2D_12( unsigned char offset, int x, int y ) const;\r\n\tinline unsigned char Index3D_12( unsigned char offset, int x, int y, int z ) const;\r\n\tinline unsigned char Index4D_32( unsigned char offset, int x, int y, int z, int w ) const;\r\n\tinline unsigned char Index2D_256( unsigned char offset, int x, int y ) const;\r\n\tinline unsigned char Index3D_256( unsigned char offset, int x, int y, int z ) const;\r\n\tinline unsigned char Index4D_256( unsigned char offset, int x, int y, int z, int w ) const;\r\n\r\n\tinline FN_DECIMAL ValCoord2DFast( unsigned char offset, int x, int y ) const;\r\n\tinline FN_DECIMAL ValCoord3DFast( unsigned char offset, int x, int y, int z ) const;\r\n\tinline FN_DECIMAL GradCoord2D( unsigned char offset, int x, int y, FN_DECIMAL xd, FN_DECIMAL yd ) const;\r\n\tinline FN_DECIMAL GradCoord3D( unsigned char offset, int x, int y, int z, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd ) const;\r\n\tinline FN_DECIMAL GradCoord4D( unsigned char offset, int x, int y, int z, int w, FN_DECIMAL xd, FN_DECIMAL yd, FN_DECIMAL zd, FN_DECIMAL wd ) const;\r\n};\r\n#endif\r\n"
  },
  {
    "path": "3rdparty/fastnoise/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Jordan Peck\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 all\ncopies 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 THE\nSOFTWARE."
  },
  {
    "path": "3rdparty/fastnoise/README.md",
    "content": "# FastNoise\n\nFastNoise is an open source noise generation library with a large collection of different noise algorithms. This library has been designed for realtime usage from the ground up, so has been optimised for speed without sacrificing noise quality.\n\nThis project started when my search to find a good noise library for procedural terrain generation concluded without an obvious choice. I enjoyed the options and customisation of Accidental Noise Library and the speed of LibNoise, so many of the techniques from these libraries and the knowledge I gained from reading through their source has gone into creating FastNoise.\n\nI have now also created [FastNoise SIMD](https://github.com/Auburns/FastNoiseSIMD), which utilises SIMD CPU instructions to gain huge performance boosts. It is slightly less flexible and cannot be converted to other languages, but if you can I would highly suggest using this for heavy noise generation loads.\n\n### Features\n- Value Noise 2D, 3D\n- Perlin Noise 2D, 3D\n- Simplex Noise 2D, 3D, 4D\n- Cubic Noise 2D, 3D\n- Gradient Perturb 2D, 3D\n- Multiple fractal options for all of the above\n- Cellular (Voronoi) Noise 2D, 3D\n- White Noise 2D, 3D, 4D\n- Supports floats or doubles\n\n### Wiki\nUsage and documentation available in wiki\n\n[Wiki Link](https://github.com/Auburns/FastNoise/wiki)\n\n### Related repositories\n - [FastNoise C#](https://github.com/Auburns/FastNoise_CSharp)\n - [FastNoise Java](https://github.com/Auburns/FastNoise_Java)\n - [FastNoise SIMD](https://github.com/Auburns/FastNoiseSIMD)\n - [FastNoise Unity](https://www.assetstore.unity3d.com/en/#!/content/70706)\n - [Unreal FastNoise](https://github.com/midgen/UnrealFastNoise)\n\nCredit to [CubicNoise](https://github.com/jobtalle/CubicNoise) for the cubic noise algorithm\n\n## FastNoise Preview\n\nI have written a compact testing application for all the features included in FastNoise with a visual representation. I use this for development purposes and testing noise settings used in terrain generation.\n\nDownload links can be found in the [Releases Section](https://github.com/Auburns/FastNoise/releases).\n\n![FastNoise Preview](http://i.imgur.com/uG7Vepc.png)\n\n\n# Performance Comparisons\nUsing default noise settings on FastNoise and matching those settings across the other libraries where possible.\n\nTimings below are x1000 ns to generate 32x32x32 points of noise on a single thread.\n\n- CPU: Intel Xeon Skylake @ 2.0Ghz\n- Compiler: Intel 17.0 x64\n\n| Noise Type  | FastNoise | FastNoiseSIMD AVX2 | LibNoise | FastNoise 2D |\n|-------------|-----------|--------------------|----------|--------------|\n| White Noise | 141       | 9                  |          | 111          |\n| Value       | 642       | 152                |          | 361          |\n| Perlin      | 1002      | 324                | 1368     | 473          |\n| Simplex     | 1194      | 294                |          | 883          |\n| Cellular    | 2979      | 1283               | 58125    | 1074         |\n| Cubic       | 2979      | 952                |          | 858          |\n\nComparision of fractal performance [here](https://github.com/Auburns/FastNoiseSIMD/wiki/In-depth-SIMD-level).\n\n# Examples\n## Cellular Noise\n![Cellular Noise](http://i.imgur.com/quAic8M.png)\n\n![Cellular Noise](http://i.imgur.com/gAd9Y2t.png)\n\n![Cellular Noise](http://i.imgur.com/7kJd4fA.png)\n\n## Fractal Noise\n![Fractal Noise](http://i.imgur.com/XqSD7eR.png)\n\n## Value Noise\n![Value Noise](http://i.imgur.com/X2lbFZR.png)\n\n## White Noise\n![White Noise](http://i.imgur.com/QIlYvyQ.png)\n\n## Gradient Perturb\n![Gradient Perturb](http://i.imgur.com/gOjc1u1.png)\n\n![Gradient Perturb](http://i.imgur.com/ui045Bk.png)\n\n![Gradient Perturb](http://i.imgur.com/JICFypT.png)\n\n\n# Any suggestions or questions welcome\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16.0)\n# Disable release-builds without debug info\nset(CMAKE_CONFIGURATION_TYPES Debug RelWithDebInfo CACHE STRING INTERNAL FORCE)\n\n# Project version, 4 numbers representation\nset(DEFAULT_VERSION \"0.8.11.0\" CACHE STRING \"Version\" FORCE)\n# Set from CI only\nset(BUILD_ID \"0\" CACHE INTERNAL \"\")\nset(GIT_REPO \"\" CACHE INTERNAL \"\")\nset(GIT_REF \"\" CACHE INTERNAL \"\")\nset(GIT_SHA \"\" CACHE INTERNAL \"\")\n\nproject(Ingnomia\n\tVERSION ${DEFAULT_VERSION}\n\tDESCRIPTION \"Gnome city builder\"\n\tHOMEPAGE_URL \"https://github.com/rschurade/Ingnomia\"\n\tLANGUAGES \"CXX\"\n)\n\nlist(APPEND CMAKE_MODULE_PATH \"${CMAKE_CURRENT_LIST_DIR}/cmake/modules\")\n\nfind_package(Qt5 REQUIRED QUIET COMPONENTS Core Xml Sql OpenGL)\n\nfind_package(Steam REQUIRED)\nfind_package(Noesis REQUIRED)\nfind_package(OpenAL REQUIRED)\n# Noesis license\nset(NOESIS_LICENSE_NAME \"\" CACHE STRING \"Name\")\nset(NOESIS_LICENSE_KEY \"\" CACHE STRING \"Key\")\n\nset(BUGSPLAT_DB \"\" CACHE STRING \"BSDB\")\n\n# Without this, paths are not relative in the sources list\ncmake_policy(SET CMP0076 NEW)\n\ninclude(GNUInstallDirs)\n\n# The program itself\nadd_executable(${PROJECT_NAME})\n\n# C++ version\nset_target_properties(${PROJECT_NAME}\n\tPROPERTIES\n\t\tCXX_STANDARD 17\n\t\tAUTOMOC ON\n\t\tINTERPROCEDURAL_OPTIMIZATION ON\n\t\tINSTALL_RPATH \"$ORIGIN\"\n)\nset_property(GLOBAL PROPERTY USE_FOLDERS ON)\nset_property(GLOBAL PROPERTY AUTOGEN_SOURCE_GROUP \"Generated\")\n\nadd_subdirectory(content) # Deployable content\n# Copy content to target directory\nadd_custom_command(TARGET ${PROJECT_NAME}\n\tPOST_BUILD\n\tCOMMAND\n\t\t${CMAKE_COMMAND} -E copy_directory\n\t\t${CMAKE_SOURCE_DIR}/content $<TARGET_FILE_DIR:${PROJECT_NAME}>/content\n)\n\nif(WIN32)\n\tset(RC_SOURCES\n\t\t${PROJECT_NAME}.ico\n\t\twindows/${PROJECT_NAME}.rc\n\t\twindows/${PROJECT_NAME}.manifest\n\t\twindows/resource.h\n\t)\n\ttarget_sources(${PROJECT_NAME}\n\t\tPRIVATE\n\t\t\t${RC_SOURCES}\n\t)\n\nendif()\n\ntarget_sources(${PROJECT_NAME}\n\tPRIVATE\n\t\tChangelog.md\n\t\tREADME.md\n\t\tLICENSE\n)\n\nadd_subdirectory(src) # Sources list\nadd_subdirectory(3rdparty) # 3rd party dependencies\n\n# Linking\ntarget_link_libraries(${PROJECT_NAME}\n\tPRIVATE\n\t\tQt5::Core\n\t\tQt5::Xml\n\t\tQt5::Sql\n\t\tQt5::OpenGL\n\t\tSteam\n\t\tNoesisApp\n\t\tfastnoise\n\t\texprtk\n\t\tOpenAL\n)\n\n# Noesis license\nconfigure_file(\n\t${CMAKE_SOURCE_DIR}/src/gui/license.h.in\n\t${CMAKE_SOURCE_DIR}/src/gui/license.h\n\t@ONLY\n)\n\nconfigure_file(\n\t${CMAKE_SOURCE_DIR}/src/version.h.in\n\t${CMAKE_SOURCE_DIR}/src/version.h\n\t@ONLY\n)\n\ntarget_sources(${PROJECT_NAME}\n\tPRIVATE\n\t\t${CMAKE_SOURCE_DIR}/src/gui/license.h.in\n\t\t${CMAKE_SOURCE_DIR}/src/version.h.in\n)\n\nif(UNIX)\n\t# Qt requires position independent code\n\ttarget_compile_options(${PROJECT_NAME}\n\t\tPRIVATE\n\t\t\t-fPIC\n\t)\nendif()\n\nget_target_property(SOURCE_LIST ${PROJECT_NAME} SOURCES)\nsource_group(TREE \"${CMAKE_CURRENT_SOURCE_DIR}\" FILES ${SOURCE_LIST})\n\nif(UNIX AND NOT (DEFINED ENV{CXXFLAGS} OR CMAKE_CXX_FLAGS))\n\tset(CMAKE_CXX_FLAGS \"-Wall -Wextra -g\")\n\t# Kill some overly verbose warnings\n\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas -Wno-unused-parameter\")\n\t# But treat likely errors as actual errors\n\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Werror=missing-field-initializers -Werror=ignored-qualifiers -Werror=delete-non-virtual-dtor -Werror=unused-value\")\nendif()\n\nif(MSVC)\n\tset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /Gy /Oi /MP /GS- /W3 /permissive- /w24458 /w34456 /w24702\")\n\tset(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS} /CGTHREADS:8 /PROFILE\")\n\tset(CMAKE_CXX_FLAGS_RELWITHDEBINFO \"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ob2\")\n\tset_target_properties(${PROJECT_NAME} PROPERTIES\n\t\tLINK_FLAGS /SUBSYSTEM:WINDOWS\n\t)\n\tset_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME})\nendif()\n\nif(MSVC AND NOT BUGSPLAT_DB STREQUAL \"\")\n\tfind_package(BugSplat REQUIRED)\n\n\ttarget_link_libraries(${PROJECT_NAME}\n\t\tPRIVATE\n\t\t\tBugSplat\n\t)\n\n\tget_target_property(BUGSPLAT_DLL BugSplat LOCATION)\n\tget_target_property(BUGSPLAT_RC_DLL BugSplatRc LOCATION)\n\tget_target_property(BUGSPLAT_SEND_DLL BugSplatSendReport LOCATION)\n\tlist(APPEND RUNTIME_DLLS ${BUGSPLAT_DLL} ${BUGSPLAT_RC_DLL} ${BUGSPLAT_SEND_DLL})\nendif()\n\n# Install target\ninstall(\n\tTARGETS ${PROJECT_NAME}\n\tDESTINATION ${CMAKE_INSTALL_BINDIR}\n)\n\nget_target_property(STEAM_DLL Steam LOCATION)\nget_target_property(NOESIS_DLL Noesis LOCATION)\nlist(APPEND RUNTIME_DLLS ${STEAM_DLL})\nlist(APPEND RUNTIME_DLLS ${NOESIS_DLL})\n\nif(WIN32)\n\t# On Windows, we want to use bundled OpenAL for guaranteed OpenAL Soft support\n\tlist(APPEND RUNTIME_DLLS ${OPENAL_DLL})\nendif(WIN32)\n\ninstall(\n\tFILES\n\t\t${RUNTIME_DLLS}\n\t\tChangelog.md\n\t\tLICENSE\n\tDESTINATION\n\t\t${CMAKE_INSTALL_BINDIR}\n)\n\nif(WIN32)\n\tinstall(\n\t\tFILES $<TARGET_PDB_FILE:${PROJECT_NAME}>\n\t\tDESTINATION ${CMAKE_INSTALL_BINDIR}\n\t\tOPTIONAL\n\t)\nendif()\n\n# Deployment helpers for Windows\nif(WIN32)\n\tinclude(windeployqt)\n\twindeployqt(${PROJECT_NAME})\n\n\tadd_custom_command(TARGET ${PROJECT_NAME}\n\t\tPOST_BUILD\n\t\tCOMMAND\n\t\t\t${CMAKE_COMMAND} -E copy_if_different\n\t\t\t${RUNTIME_DLLS}\n\t\t\t$<TARGET_FILE_DIR:${PROJECT_NAME}>\n\t)\n\n\tINCLUDE_EXTERNAL_MSPROJECT(\"Blend\" ${CMAKE_CURRENT_SOURCE_DIR}/gui/gui.csproj)\n\tset_target_properties(\"Blend\" PROPERTIES EXCLUDE_FROM_ALL TRUE)\nendif()\n"
  },
  {
    "path": "Changelog.md",
    "content": "# Changelog\nAll notable changes to this project will be documented in this file.\n\n\n## [0.8.11]\n\n### Fixed\n- traders now pay the announced price for player owned goods\n\n## [0.8.10]\n\n### Fixed\n- fix workshop getting stuck if job prerequisites are used elsewhere (#182)\n- fix half-height walls being completely flat\n\n## [0.8.9]\n\n### Fixed\n- fix trading of items without quality\n- fix data inconsitencies in trader UI\n- fixed potential failure of event spawns\n\n### Added\n- center camera on event notifications\n\n## [0.8.8]\n\n### Fixed\n- remove job when deleting farm tile\n- fix deconstructing scaffold\n- fix beehive job\n- suspending workshops\n- XpMod can be read from config file (#173)\n- SeedTrader to trade potato & onion seeds.\n- addded missing material name for Panda, Spider, Woodlouse\n\n### Added\n- support for sound\n- add num plots to grove info, \n\n### Changed\n- update Noesis to 3.0.12\n- allow designating grove over existing plants\n- improve auto craft behavior\n- some rebalance of trade values for metal coin, bar and ores. (#171)\n\n## [0.8.7]\n\n### Fixed\n- grape seed on start up\n- game pausing when in mainmenu\n- remove dead gnomes from squads\n- show number of trees in grove window\n- missing textures when loading the game\n- floating items when mining the ramp under a working gnome\n- amount buttons in trader UI\n- partial write back while updating workshop settings\n\n### Added\n- attack on sight combat behavior\n- defend (hold position) combat behavior\n\n### Changed\n- allow corpses outside stockpiles to be butchered\n- can designate groves over existing trees\n- allow jobs in mid-air to be selected\n- reduce number of item categories\n\n### Removed\n\n\n## [0.8.6]\n\n### Fixed\n- crash with missions\n- remove plants on the tile above when digging stairs up\n- gnomes forgetting their rooms on load\n- swapped items getting stuck as constructed when looking for a tool\n- seeds for leaf plants like tea, tobacco, woad and dyers weed\n\n### Added\n- burn recipe for bones in the waste disposal\n- stairs made from stone blocks\n- fisher gui\n- controls for mechanisms\n- controls for automatons\n- full DPI scaling support\n- some statistics\n\n### Changed\n- restructured the tile info window\n- moved all job handling other than hauling jobs to central job manager instance\n- trees can no longer overlapp with each other\n- trees can no longer replace existing tiles\n- onions and potatos produces seeds again and use seeds to plant\n\n### Removed\n\n\n## [0.8.5]\n\n### Fixed\n- moved cursor calculation to game thread\n- cursor detached from selection when using WASD\n- going back to resume screen when selecting settings out of a running game\n- container capacity on stockpiles after load\n- crash because of incorrect data in save folders\n- buildable carry containers\n- crash because of incorrect bitmaps in gnome detail window\n- user presets saving on embark\n- translation string for willow tree\n- willow trees are now plantable\n- fish shouldn't drown anymore\n\n### Added\n- capacity info for stockpile tiles on tile info\n- watched item list\n- 24 new food items with recipes and kitchen integration\n- button to save user presets\n- glass bottle and jar\n- show version on main menu screen\n\n### Changed\n- furniture can now be constructed anywhere and won't get deconstructed when a room designation underneath is removed\n- redesigned inventory overview\n- removed direct mapping of certain ids to databse rows, that should prevent save games breaking in the future when stuff is removed or inserted at the wrong place\n- grain plants produce seeds again and need seeds for planting\n\n### Removed\n\n\n## [0.8.4]\n\n### Fixed\n- large refactor of code base to fix some crashes and memory leaks\n- behavior tree instantiation \n\n### Added\n- Willow trees\n- Info display for selected command and selection size\n\n### Changed\n- Rivers now have sand floor, preventing grass and plants spawning there\n- speed up light updates\n- speed up animal ai  for grazing\n\n### Removed\n\n## [0.8.3]\n\n### Fixed\n- crash in tile info panel due to wrong thread\n- random crash due to use of GPU in wrong context\n- crash with auto craft in waste disposal\n\n### Added\n\n### Changed\n- sped up auto-craft job generation\n- include log file in crash dumps\n\n### Removed\n\n\n## [0.8.2]\n\n### Fixed\n- suboptimal paths due to wrong heuristic in pathfinding\n- gnomes trying to work in deep water\n- missing floor texture for undiscovered areas\n- find new path if target has moved\n- crash with selected dig stairs tool at layer 0\n- build scaffolds on top of each other\n- added check for corrupted config file and load standard config if needed\n- deconstruct workshops sets tile flags correctly, allowing to build on that tile again\n- prevent creatures from walking into deep water\n- constrain camera to actual game area\n- reasonable speed range for WASD\n- load game screen updates without restarting now\n\n### Added\n- ui elements to show state of and toggle certain render options\n- toggle for job sprites\n- added bugsplat crash reporting to windows builds\n\n### Changed\n- improved cursor for building floor on walls\n- optimized pathfinding if multiple gnomes have same goal\n- reduced water pressure on the faucet\n- mining job sprite, first poc for job sprites giving more visual feedback about the job\n\n### Removed\n- old networking code\n\n## [0.8.1]\n\n### Fixed\n- message window not disappearing after clicking an answer button if game is unpaused, \n  game not possible to unpause now when message window is open\n- GUI quickly changing size and back after resizing the window\n- key space for pause\n- text clipping in some menu panels\n- dig stairs and ramps cursor\n- rotating the world keeps view on current location\n- set view to correct position after load\n- added bounds to world movement so it can't be moved out of view accidentally\n- fix keyboard movement for fast speed\n- felling trees in groves requires a felling axe\n- jobs created with no required tool\n- groves not keeping suspend flag\n- killed animals leave corpses again\n- butchering animal corpses\n- explorative mining speed now the same as mining\n- jobs with missing materials not returned to job queue correctly\n- visual corruptions on AMD GPUs\n- some alpha blending issues\n- uiscale reverting to 100%\n- crash when adding or deleting a custom profession\n- building scaffolds\n- dead gnomes give up workshop assignments\n- dead creatures drop their inventory\n- fix crash on startup on some systems\n\n### Added\n- moved text in xamls to resource files as preparation for translations PR#90 Daynvheur\n- added french translation PR#90 Daynvheur\n- settings dialog\n- WASD movement\n- item summary\n- setting for minimum ambient light level\n- colors for skill buttons in population overview\n- colors for population schedule buttons\n- blacksmith recipe for metal needle\n- honey wine\n- fill hole command\n\n### Changed\n- more info for jobs  PR #91 by rivenwyrm\n- updated to Noesis 3.0.6\n- removed key triggers from xamls\n- use only one save game for auto save\n- improved auto craft behavior\n- honey can be stored in barrels\n- greatly reduced bone drops from butchering\n\n\n### Removed\n\n\n\n## [0.8.0]\n### Fixed\n- Isolated simulation thread from UI thread, so they don't share data.\n  UI components are now split into a UI controller living in t he UI thread and a data aggregation component living in the simulation thread.\n  Both parts are connected via the Qt message system, but are not allowed to access state owned by the other thread.\n- Prevent errors in sprite mapping from cascading. The errors themselves are not resolved yet, but will no longer corrupt an entire save game.\n- Always resolve all assets relative to the main executable.\n### Added\n- Added Noesis based UI, replacing the existing UI from scratch. (Work in progress.)\n- Added \"Hunting\" behavior, in addition to legacy \"defend\" behavior.\n  Squads can actively seek out enemies all over the map as they become visible, without user involvement.\n- Added Linux support.\n### Changed\n- Relicense code under [GNU AFFERO GENERAL PUBLIC LICENSE Version 3](LICENSE) and publish as open source.\n- Switch to CMake build system.\n- Switch from C++11 with MSVC legacy extensions to pure C++17.\n- Update Qt to 5.14.1.\n- Refactored rendering.\n\t- Cull empty tiles in vertex rather than fragment shader.\n\t- Split opaque and transparent tiles into distinct render passes.\n\t- Upload data to GPU via compute shader rahter than direct mapping.\n\t- Render dark areas desaturated.\n\t- Improve visibility of designations.\n\t- Cull tiles down to minimal screen space size in order to minimize overdraw.\n\t- Increase required OpenGL version to 4.3.\n\t- Add depth buffer to rendering.\n- Replace explicit squad target control by behavior settings for Squad.\n- Move Uniform assignment from squad position to individual gnome.\n  Gnomes can now have a uniform without being assigned to a squad, but they still need a squad to control their combat behavior.\n- Allow arbitrarily sized squads, up from only 5 slots.\n- Speed up high level pathability tests.\n- Speed up A* pathfinding.\n- Speed up liquid simulation.\n- Speed up spatial item lookup.\n- Switch from file based SQLite DB to pure in-memory SQLite DB.\n- Load SQLite DB from human readable SQL file instead of binary representation.\n- Run as \"native Windows 10 application\" under Windows 10, rather than running in compatibility mode.\n\n### Removed\n- Removed old Qt based UI.\n- Removed RapidJSON from JSON parsing and dependencies. Comments in JSON files are no longer supported.\n- Removed Quazip from dependencies.\n- Removed zLib from dependencies.\n\n## [0.7.5]\n- fix bee hive now craftable at carpenter\n- add wall torch\n- add plank stairs\n- fix furniture not buildable in rooms\n- fix phase shifting gnomes\n- fix deconstructing floors moves items to the worker's position\n- fix item search abandoning too soon\n- added categories to the workshop construction window to make it easier to find a specific workshop\n- add adjustable threshold to item overlay, mark item red if amount is lower than threshold\n- add big torch and brazier, both crafted in the blacksmith workshop\n- add config option to control the render order of layers: \"renderMode\": \"down|up\" up looks better with water transparency but adds more load to the gpu\n- fix rotating dresser\n- fix military widget multiple issues\n- fix gnomes in get job loop when trees not reachable for pick fruit or fell\n- add damage reduction when wearing armor\n- add glass workshops\n- make renderDown the default mode\n\n## [0.7.4]\n- sprite handling rework to allow more sprites in the future\n- added adjustable limit to hay harvesting\n- added water evaporation\n- fix save/load auqifiers and deaquifiers\n- fix building a wall removes water on that tile\n- added setting to set target fps when the game is paused, ( config.json: \"pausedRenderTimer\": # ) higher number = lower fps\n- added setting to adjust the light level at night time\n- added check connection between items and jobs before give the job to a gnome, fixes gnomes getting stuck because of unreachable items\n- fixed workshop tasks showing different materials when a new material appeared after creating the task\n- prospecting now has a 50% success chance\n- prospecting outcome now depends on source material\n- fix constructed wallfloor disappearing when building a wall on top\n- added alarm bell and gnomes retreating to its location when the alarm is raised\n\n## [0.7.3]\n- fix enemy kingdoms not attacking\n- fix goblin aggression being so high it overcomes the peaceful setting\n- fix gnomes changing haircolor depending on the direction they face\n- fix bug with fill trough that would stop gnomes from working\n- fix some weapon crafting recipes\n- added popup and center camera on gnome death\n- when sending several explorers at the same time, they shouldn't find the same kingdom anymore\n- fix endless get job loop when required items aren't reachable\n- added checkbox to pasture widget to toggle harvest jobs (milk, shear), that setting will be off for existing games so please check your pastures\n- improved auto crafting behavior\n- fix saving of embark presets\n- fix prospector making stone slivers\n- added fill hole command\n- fix crafting of metal bars when source material \"any\" is selected\n- fix reset mission list wehn starting a new game\n- fix crash with removing stockpile filter items\n- added checkbox to world size slider to enable map sizes greater than 300\n- added harvesting grass for hay from pastures\n- building a structure like fence that removes the WALKABLE flag will also remove the designation (farm, stockpile...) on that tile\n- improved (hopefully) stockpiling performance\n- goblins should no longer target gnomes that are on a mission\n- workshop and stockpile windows now remember their size and position\n- added new sprites for rough stone walls\n- split rendering into two passes for floor and everything above, sprites overlapping tile borders won't get cut off by neighboring floor sprite anymore\n\n## [0.7.2]\n- fix building workshops over the edge\n- fix automaton removing cores\n- fix automaton list reset on load\n- added quick save\n- fixed crash with non existant mission\n- added check if gnome can reach workshop when gettings jobs\n- some animals now drop hides on butcher\n- item info now shows tool level if item is a tool\n- job info in the tile info widget now shows required tool level if the job requires a tool\n- added flintstone pickaxe head\n- fix wood bed frame \n- fix wall floor construction\n- grain plants (wheat, oat, millet, barley) no longer produce seeds, the seed item is grain, they now produce 2 grain per harvest with a 50% chance of a third\n- fix giving out jobs when required items not exist, this will reduce many loops of getJob-dropJob\n- fix when building a wall it sets the embedded material and item spriteID to zero\n- fix when building a wall it moves items and creatures out of that tile.\n- fix unreachable material preventing some crafting\n- removed the constraint that all items have to be the same material when selecting \"any\" material for crafting\n- stopped eggs from walking around\n- added beehives and honey\n- added flowers\n- added waste disposal workshop\n\n## [0.7.1]\n- fixed some definitions, flour, bone table\n- fix saving/loading for larger data size\n- fixed crash with removing stockpiles under constructed containers\n- fixed workshops creating auto craft jobs even when they shouldn't\n- fixed crash with deleting stockpiles\n- fixed crash with too many gnomes on the profession overview list\n- fixed crafting of automaton parts\n- fix auto harvester for vegetables\n- it's now possible to toggle the debug overlay, default key O\n- added on screen item counts\n- quadrupled move speed of gnomes\n\n## [0.7.0]\n- added death from drowning\n- added automatons\n- fixed floor disappearing when deconstructing workshops\n- fixed replacing fancy floors and walls\n- added windmill\n- add bone and skull walls\n- adjusted all item prices (wip)\n- fixed mod support\n- prepared main menu and the new game widget for translations\n- added neighbor kingdoms and interactions with them\n- made the ocean front uneven\n- added rivers\n\n## [0.6.9]\n- added profession selection to profession overview\n- lowered required tool level for felling trees so wooden felling axes work now\n- added sheep dyeing\n- add sort by profession to profession overview\n- checking for default profession on start and add it if it's missing\n- improved random movement\n- added hard limit of 1000 creatures per type\n- fix creature breeding when limit is reached\n- fix deconstructing doors\n- fix a crash with pastures\n- improved grass spreading\n- added birch trees\n- improved water handling\n- added engineer and machine workshops\n- fixed a bug with digging ramps down\n\n## [0.6.8]\n- added metal pickaxe heads\n- added peaceful mode\n- added octree to item management\n- fixed floor sprite rotation for stone stairs\n- added toggle for stockpile limit modes\n- assign workshop, sort gnomes by name\n- fixed super fast cows\n- fix crash with deleting a stockpile\n- added deleting of save games\n- add priorities to farms, groves and pastures\n- build containers with multi selection\n- fix traders having no inventory after load\n- fix beds sometimes not released properly\n- fix crash with dyers workshop and auto generating craft plank jobs\n- fix dyer workshop, save/load created materials and names\n\n## [0.6.7]\n- possible fix for wrong material crafts\n- fix double tile definition for tailor workshops\n- add saving of monsters\n- add saving of event manager state\n- fix saving time and day with first auto save on new game\n- added occupied tile flag to prevent building into trees\n- fix clear reserved items on hauling job abortion\n- stockpile limits only uses item type now\n- fix replace wall being able to be applied to workshops\n- improved replacing of walls and floors\n- improved deconstructing\n- prevent digging ramps under fishery\n- add workshop craft to by material\n\n## [0.6.6]\n- add target assignment for squads\n- fixed freeze with auto craft\n- fixed crash when pressing keys while in the menu\n- fix deconstructing workshops\n- fix lockup with butcher workshop\n- fix releasing carried items when a wheelbarrow job gets interrupted. \n- fix traders having no items\n- fix job selection test tile when clicking different job while one is already selected\n- switched sacks and bags, sacks are nor buildable and bags the carry container\n- added container info to item info widget\n- fix remove items from containers too when taking them from a stockpile\n- fix building sacks outside of stockpiles\n- fix building walls on doors\n- fix item count in trade widgte for items with quality\n\n## [0.6.5]\n- fixed crash when changing workhop priority\n- fixed setting uniform and squad names\n- fixed missing entry in material to tool level table for platinum\n- added auto save\n- fixed tools not getting release properly when interupted (this time for real hopefully)\n- reworked light handling, allow gnomes to carry torches\n\n## [0.6.4]\n- fixed build palisade, not possible anymore with floor above\n- fixed loading of installed crates on stockpiles\n- reduced DB calls for farms and groves\n- fixed stockpiles generating hauling jobs for fields with containers that don't accept that item\n- fix workshop crafting now costs time accoring to the crafting recipe\n- fix designating a grove also set farm flag\n- added armor and weapon crafting\n- added armor equipping\n- added military settings window\n- added training grounds\n- fixed crash when clicking the tailor workshop, error in mattress sprite\n- fixed crash when clicking an A button in the skill overview window\n- fixed soil corner ramp orientation\n- fixed crash when restarting the game\n- fix stone stair rotation\n- fix undefined job state when a gnome was working a job and a need kicked in\n- fix grass-soil uramps showing the winter sprite all season\n- fix another instance of tools not releasing properly when sleep hits\n\n## [0.6.3]\n- added scheduling\n- cached some more db values to reduce reoccurring db access\n- added ingame bug report\n- fixed fences not showing up\n- fixed animals procreating\n- fixed stockpile stacksize when installing container\n- first goblins won't appear before summer year two\n- increased gnome move speed\n- clear log on start now clears log on start\n- fixed oak tree rotation - nobody noticed wtf\n- reduced grow time for most plants significantly\n\n## [0.6.2]\n- added prospecting recipes\n- fix building fisheries\n- fix crash with dirt floor sprites after loading\n- fix materials not registering for crafts\n- fix tech gain for crafting at workshops\n- fix tool pick up for dig jobs\n- fix planks and blocks not recognized for floor construction\n\n## [0.6.1]\n- added default material to sprite definition, no more bone table as default sprite when building workshops\n- fixed material2 for combined items at startup\n- redesigned the stockpile filter tab\n- added workshop priority\n- added assign gnome to workshops\n\n## [0.6.0]\n- added indicator to butcher list if animal is young\n- added job sprite to upper wall tile for DigStairs\n- fix renaming groves\n- fix adding tiles to existing groves\n- added oak trees\n- added combat - this is ongoing development\n- added auto butchering of corpses\n- added mushroom biome\n- added keybinding options for actions\n- added oaks for oak tree planting\n- replaced the external data storage with a SQLite database\n\n## [0.5.9]\n- talked to some unreliable onions and straightened them out\n- fix build thatch outer ramp works again\n- mine stairs up now removes the wall in the tile above\n- added more walls with floor on top\n- fix pine cones defs for stockpiles and containers\n- add buildable soil and stone outer corner ramps\n- clicking the gnome list to open a gnome window that is already open now brings that window to front\n- fixed crash with opening item info when the maker has died\n- dead gnomes disappear after two days\n- fix animal state change tick doesn't reset on load\n- fix animals grow up again\n- disallow setting designations on tiles occupied by tree leaves\n- reinstated groves\n- added some dyes\n- added hair dyeing\n- improved lighting\n\n## [0.5.8]\n- creatures will now evade trees suddenly growing up below them\n- fixed priorities for different job types with same skill requirement\n- newly built workshops now accept generated jobs by default\n- reinstated death from hunger and thirst\n- gnomes now eat and drink up to full once they started\n- auto craft items for build jobs\n- plant tree now checks for other trees in range\n- plant tree now checks for other plant tree jobs in range\n- adjusted sunrise and sunset times for seasons\n- fix missing fish bones in stockpile filter\n- fix claim items for workshop craft jobs, when a linked stockpile exists but the item is not in that stockpile\n- fix job priorities when there are farming jobs around\n- fix deconstructing workhops only creates on deconstruct job even if more tiles are selected\n- fix deconstructing scaffolds deconstructs all scaffolds above\n- felling pine trees now produces 1-3 pine cones that can be used to plant new trees\n- fix plants growing in seasons they shouldn't when planted in that season\n- now also expel items from the trunk tile when a tree grows up\n- digging stairs down should create raw materials at \"0, 0, 0\" anymore\n- added indirect sunlight to neighboring tiles\n- fixed trader no appearing\n\n## [0.5.7]\nNew save game required\n- fix some settings not saving their changes\n- harvesting trees is now a Horticulture job\n- dig hole now creates ramps at the outer tiles of the hole\n- improved get best drink, get best food\n- improved constructing ramps\n- fixed crash with removing a farm while paused\n- fix adding tiles to existing designations open the wrong window\n- added job priorities\n- fixed crash when removing linked stockpiles\n- raised drink value of wine to 40\n- carpenters can now craft fishing rods\n- changed saving items so that adding new items won't break saves anymore (breaks save games one last time)\n\n## [0.5.6]\n- fix reset the behavior tree when aborting a job through skill deactivation\n- fix render depth in settings is an INT not a BOOL\n- fix harvesting trees\n- reactivated wheelbarrows to work with behavior tree\n- fix workshop widget checkbox showing the correct state for accept jobs\n- fix BT for aborting jobs\n- fix deconstructing stuff \n- fix deconstructing workshops returns items now\n\n## [0.5.5]\nNew save game required\n- fix deconstructing built ramps\n- fixed checkboxes not visible\n- added behavior trees for creature AI\n- added sheds, troughs and beehives\n\n## [0.5.4]\n- added seed and animal trader\n- added migration, 1-5 gnomes will arrive each season\n- tile info window doesn't reveal undiscovered tiles anymore\n- fix crash with population overview clicking skill button after sorting\n- added bone furniture\n- added wall paintings\n\n## [0.5.3]\n- fixed animals not following gnomes\n- added support for stylesheet mods\n- improved job sprite rendering\n- improved job sprites for wall and floor constructions\n- seperated stone and brick blocks\n\n## [0.5.2]\n- fix duplicate sprite creations\n- debug mode disable fow\n- started implementing basic magic features\n- added job info to tile info widget\n- UI overhaul\n- fix not possible to build walls on ramp tiles anymore\n- fix floor replacement on grass tiles turning out as raw soil floor\n\n## [0.5.1]\nNew save game required\n- fixed workshop crafting queue behaving strangely\n- abort jobs when required skill gets deactivated\n- can activate stockpile filter categories even with no items in that category present so that newly created items go to that stockpile\n- added trading\n\n## [0.5.0]\n- add buckets and sacks as carry containers\n- added fishery workshop\n- added item history\n\n## [0.4.9]\n- fixed missing check for pasture when designating areas\n- added wheelbarrows\n- added gui for game settings\n- added auto generate jobs\n\n## [0.4.8]\n- added checkbox to gnome window to let them ignore no pass zones\n- removed seperate render passes for floor and wall tiles\n\n## [0.4.7]\n- added no pass designation \n- fix falling gnomes discover their new location\n- remove floor - improve job selection to avoid getting trapped\n- build wall - improve job selection to avoid getting trapped\n- add renaming of gnomes\n\n## [0.4.6]\nNew save game required\n- added dig ramps down\n- water flows down now\n- wild animals no longer spawn in the starting zone\n- animals now getting hungry\n- some animals on pastures eat grass\n- fix dig hole\n- fixed gravity for dropped tools\n- fixed path finding/move order not correctly aborting in in some cases\n- remove dead gnomes from lists\n\n## [0.4.5]\n- tiles with non wall neighbors are discovered at game start\n- grass spreads now to dirt tiles\n- fixed beer and bread recipes taking grain\n- reinstated water\n- added fish\n\n## [0.4.4]\n- improved check if item is allowed in a container\n- fixed items in containers being rendered after load\n- built soil and rough stone walls and floors will be mined rather than deconstructed\n- added cabinet, dresser, statues to funiture options\n- fixed a workshop crafting related crash\n- animals no longer randomly wander through doors that are blocked for them\n- fix: pasture onle show collect eggs checkbox for egg laying animals\n- separated selection rendering from main render\n\n## [0.4.3]\n- update lights in range when mining a wall\n- open stockpile window at stockpile creation\n- goats give milk now\n- eggs can now be collected, omelette!\n- removed glFinish in the main render function, this might improve things on some systems\n- fixed a stockpile related crash\n\n## [0.4.2]\n- fix Gnome list showing the right now after sorting\n- another fix for initial gnome speed\n- fixed brewing recipes to use brewing skill instead of cooking\n- building/replacing floor tiles with ramp tops is no longer possible\n- prevent logs created by felling a tree at map border to float in limbo\n\n## [0.4.1]\n- shift leftclick now forces the tile info widget to open even if only one thing is on the tile\n- made gnomes less blinking\n- added cheese\n- added move top/bottom buttons to stockpile widgets\n- fixed bug that caused craft jobs with materials set to \"any\" not being started\n- add \"fow\" option to configs when missing\n\n## [0.4.0]\n- stockpiling, tiles with containers are handled first\n- job queue: craft# the number to craft will count down now\n- job queue: craft to, jobs will not disappear anymore when the number is reached but suspend\n- slowed down fast runners\n- sun loving plants no longer grow underground\n- fixed crash when removing a pasture\n- fixed selection checking for zLevel to only stop at walls and floors\n\n## [0.3.9]\n- fix: update selection z level when changing level\n- added chisel to stone mason\n- added 3 pixel to mouse y for better tile selection\n- skill system overhaul (first part) - needs new game\n- gnome move speed now depends on hauling skill\n- added save button to profession management to prevent unwanted changes to professions\n\n## [0.3.8]\n- fix: saving keeps stockpile order now\n- no more duplicate gnome names, Ulf Ulfson son of Ulf disagrees\n- gnomes on gnome list and profession overview are now sorted by name\n- population overview can now be sorted by skill\n- fixed keyboard zoom not working\n- population overview and gnome widgets now update each other in real time\n\n## [0.3.7]\n- improved world rotation\n- added keybinding ctrl + / ctrl - for changing z levels\n- made key bindings configurable\n\n## [0.3.6]\n- added missing translation strings for some item groups\n- fix replace floor to work under designations\n- fixed a crash with multiple butchers butchering the same animals\n- fix missing item definition for sausage and sandwich causing pink boxes\n- fixed messed up sprites for constructed items on load (double beds)\n- fix missing definitions ammo pouch\n- fix workshop craft# and craft to\n\n## [0.3.5]\n- fixed canceling workshop constructions leaving job sprites behind\n- show stair orientation when digging stairs down\n- fixed creatures and gnomes flashing when on the same tile\n- reworked the workshop gui\n- stockpiles: initial suspend threshold per item is now 0, if it's 0 the suspend threshold is ignored\n- fixed some items not possible to stockpile - please report if an item doesn't appear in the stockpile filter\n\n## [0.3.4]\n- fixed some crashes with butchering animals\n- added short walls, hotkey H - will need new game\n- added bones to all butchering results\n- added animals: duck, goose, dog, cat, fox, wolf, deer, goat, squirrel\n- fixed sand short wall\n\n## [0.3.3]\n- if embark items is empty medium preset will be selected\n- fixed crash when clicking on certain tiles of a rotated crude workbench\n\n## [0.3.2]\n- replacing walls now return materials\n- moved the log file to C:\\Users\\<User>\\Documents\\My Games\\Ingnomia\n- tweaked cursor positioning if there is a wall structure in the tile in front of it\n- fix space bar for toggle pause\n- added keyboard plus and minus for zoom\n\n## [0.3.1]\n- abort jobs now correctly unclaims items\n- hunger and thirst now only abort jobs if food/drink items are available\n- fixed a crash with aborting jobs\n- made the new game screen more friendly for lower resolutions\n- added button to create a random gnome\n- fixed saving of job sprites\n- added status messages to loading screen\n- fixed gnomes freezing after load\n\n## [0.3.0]\n- added check if required items exist before handing out jobs, should reduce green/yellow flashing of jobs\n- fixed memory leak with jobs\n- added message box when opengl init fails\n- reduced sleep, hunger, thirst\n- renamed the build door widget to build utility so people stop asking why torches are doors\n- fix stockpile filter settings for loading/saving copy&paste\n- big windows like Population Overview, Stocks and Kingdom now have a max size of the game window\n\n## [0.2.9]\n- fixed crash with butcher when pressing cancel on empty list\n- fixed crash with deconstructing a torch\n- fixed removing rooms\n- fixed deconstructing furniture in rooms\n- fixed ghosts of felling axes making it to the next game\n\n## [0.2.8]\n- fixed creation of ghost items at position (0,0,0)\n- added tooltip to construct workshop button listing crafts\n- fix crash with deconstructing fences\n- added butcher excess lifestock\n- lowered food intake and doubled the time before gnomes die from thirst and starvation\n- added mine stairs up\n- fixed deconstruction stairs\n\n## [0.2.7]\n- fixed crashes with removing stockpiles and pasture\n- fixed domr stuff carrying over after new game\n- improved eating and drinking\n- added highlight to selected item in right click menu\n\n## [0.2.6]\n- fences\n- added cows, moo\n- fixed rotating workhop job sprites\n- fixed crash when loading constructions without sprite\n- add remove floor, replace wall/floor commands\n- added remove plant command\n\n## [0.2.5]\n- require felling axe for tree cutting\n- added baby animals\n- fixed crash with workshops with empty recipe lists\n- gnomes now die from hunger and thirst\n- updated to Qt5.11.1\n\n## [0.2.4]\n- menu option continue loads last save game now\n- when using a container to build a workshop it now drops its items\n- added metals and gems to underground\n- added config option for fow\n- reordered farm job priorities\n- fix gnome widget professions\n- added embark item presets\n\n## [0.2.3]\n- added random kingdom name generation\n- added support for multiple save games\n- added status screen for messages during world generation\n- screenshots\n- added keyboard support ( 1 - 0 ) for commands\n- hide undiscovered tiles\n\n## [0.2.2] \n- added butchering animals from pastures\n\n## [0.2.1]\n- added pasture\n- rework of animal actions\n\n## [0.2.0]\n- part two of stockpile rework, per item suspends\n- added copy&paste for stockpile settings\n- fix work sprites disappearing on escape\n- added right click menu\n\n## [0.1.9]\n- when only one entity is present on a tile, clicking it skips the tile info window and opens the respective window\n- part one of stockpile rework\n\n## [0.1.8]\n- added wall build mode that auto builds floor tiles below\n- added outer ramp corners\n- added checkbox to farmwidget to shown only types with available seed item\n- improved renderer\n\n## [0.1.7]\n- added digHole command\n- added building of most wall and floor types\n- added scaffold\n- added gravity to gnomes and items when removing floor tiles\n\n## [0.1.6]\n- fixed placement of starting items\n- added dyers workshop\n\n## [0.1.5]\n- fixed cursor pos for rotated views\n- paint job sprite green after required tool is picked up\n- seasonal sprites for slopes\n\n## [0.1.4]\n- added new game screen\n- fix #81 changing profession for gnome created additional need bars and attribs\n\n## [0.1.3]\n- added water processing and rendering\n- added many workshops and craftable items\n- added distillery workshop\n- containers which require the same item and material type now do so\n\n## [0.1.2]\n- added item info widget\n- added light handling to renderer\n- added day/night mode\n- saving/loading of lights\n- animated torches\n- added personal room assignment\n- added beds to rooms and dorms, gnomes need sleep now\n- added eating and drinking\n\n## [0.1.1]\n- added exprtk for math formula parsing\n- fixed seasonal sprites for opengl renderer\n- added clearLogOnStart option to config\n- added enableScaling option to config\n- added value bars for needs to gnome widget\n- added value decay per minute for needs\n- added activity log for gnomes\n- possible fix for black background in some windows\n\n## [0.1.0]\n- updated to Qt 5.10.0\n- added lots of plants\n- added \"enableLog\" option to config.cfg\n- added changelog.txt\n\n## [0.0.9]\n- new OpenGL based renderer\n- reworked stockpile item filtering\n\n## [0.0.8]\n- reworked sprite handling\n- gnome sprites generated from parts\n- reworked the workshop construction window\n- added high dpi scaling and font size adjustment\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU AFFERO GENERAL PUBLIC LICENSE\n                       Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n  A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n  The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n  An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Remote Network Interaction; Use with the GNU General Public License.\n\n  Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as published\n    by the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<https://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.md",
    "content": "# Ingnomia #\n\nJust looking for the game itself?\n\nPrebuilt binaries are available in the [release section](https://github.com/rschurade/Ingnomia/releases) or on \n[Steam](https://store.steampowered.com/app/709240/Ingnomia/).\n\nThe active community for this game can be found on our [Discord server](https://discord.gg/y5GygwY).\n\n## What is this? ##\n\nIngnomia started out as an independent remake of the older [Gnomoria](https://store.steampowered.com/app/224500/Gnomoria/) colony simulator, from which it was permitted to borrow some of the assets.\nWhile the graphics look similar, all of the engine was rewritten from scratch. Compared to the reference, Ingnomias engine scales significantly better with large colonies.\n\nIn terms of features, balancing, user interface design etc. Ingnomia has since given its own spin to many of the core game elements.\n\nWhile already in a playable state, it's still under heavy development and truly, by all means, \"Early Access\".\nNot all game components have been implemented yet and some bugs are to be expected.\n\nIngnomia is a pure hobby project, and true free-to-play. With \"free\" spelled as in \"free beer\".\n\n## How do I get set up for development? ##\n\nThe following steps describe how to compile the code locally and get the game running on Windows and Linux.\n\nNote! Building on Mac is currently not possible. Certain features in the renderer require OpenGL4.3.\n\n### Dependencies ###\n\n#### Windows specific ####\n* Microsoft Visual Studio 2019, the community edition is free\n* Qt [vs addin](http://download.qt.io/official_releases/vsaddin/2.5.2/) (optional)\n#### All Platforms ####\n* OpenGL 4.3 - Mac is not a supported compilation platform since it has deprecated OpenGL\n* Qt 5.14.1 or newer\n* [Noesis Gui](https://www.noesisengine.com/developers/downloads.php) 3.0.12\\\n  For using Noesis in a local development build, you need to get a [trial license](https://www.noesisengine.com/trial/).\n* [Steam SDK](https://partner.steamgames.com/doc/sdk)\n* [SFML 2.5.1](https://www.sfml-dev.org/download/sfml/2.5.1/)\n* CMake 3.16 or newer\n\n### Build ###\n\n```bash\ncp -r \"<EXISTING_INGOMIA_INSTALLATION>/content/tilesheet\" content/\n\ncmake -S . -B \"<BUILD_DIR>\" \\\n-DQt5_DIR=\"<QTINSTALLDIR>/<ARCH>/lib/cmake/Qt5\" \\\n-DSTEAM_SDK_ROOT=\"<STEAMSDKDIR>/sdk\" \\\n-DNOESIS_ROOT=\"<NOESISDIR>\" \\\n-DNOESIS_LICENSE_NAME=\"<NOESIS_TRIAL_LICENSE_NAME>\" \\\n-DNOESIS_LICENSE_KEY=\"<NOESIS_TRIAL_LICENSE_KEY>\"\n-DSFML_DIR=\"<SFMLDIR>/lib/cmake/SFML\"\n```\n\nIf no errors have occured, proceed by building the project with the chosen build system or open the generated project in an IDE of your choice.\n\n```bash\ncmake --build \"<BUILD_DIR>\"\n```\n\n### Building the documentation ###\n\nDocumentation building scripts are in the `docs/` directory. To rebuild documentation you will need:\n\n* Python 3.9\n* Pipenv\n* Tilesheets from an existing installation (in the `content/tilesheet` directory, as when building the game)\n\nFrom the `docs/` directory, run:\n\n```bash\npipenv install\npipenv run ./generate.py\n```\n\nOutput is generated in `docs/html`. You can specify a different output by passing `--output path/to/dir` to the generation script.\n\nGeneration will fail when the output directory exists. Use the `--overwrite` option in that case, but be warned that it will wipe the output directory completely.\n\n### Forks on Github ###\n\nWhen forking the project on Github, you should add `NOESIS_LICENSE_KEY` and `NOESIS_LICENSE_NAME` as secrets in your repositories configuration under Settings/Secrets. If not provided, CI builds will fail for your fork.\n\nIngnomia comes with automatic builds via GitHub Actions, triggered on push to repository.\nAs long as you have forked Ingnomia as a **public** repository, these are expected to be free-of-charge for your GitHub account.\n\n## Contribution guidelines ##\n\nHelp with Ignomia is always welcome.\n\n### Making suggestions ###\n\nWe love to hear about your ideas on this game! Please head straight to our [Discord](https://discord.gg/DCSmxVD) server and discuss them in the #suggestions channel. You might see them realized at some point.\n\nPlease don't open tickets for suggestions on your own. That is reserved for already planed features.\n\n### Reporting bugs ###\n\nEven if you can't contribute in code, testing and reporting bugs is just as important to us. If you find something which doesn't behave right, or even crashes, feel free to open a ticket in the bugtracker.\n\nPlease include only one bug per ticket, with a precise step-by-step instruction how to trigger, and search for open tickets on the same subject first.\n\nIf you prefer, you may also try to reproduce bugs reported by other users. The more precise informations on a bug are, the higher the chance it can be fixed.\n\n### Code contributions ###\n\nIf you know any of C++ or XAML you can help right away! Feel free to check for open bugs, and hop over to our [Discord](https://discord.gg/DCSmxVD) channel to get you sorted in.\n\nPlease provide your contributions in the form of a pull request, rebased onto the current head of development.\n\n#### License ####\n\nThe contents of this repository are licensed under [GNU AFFERO GENERAL PUBLIC LICENSE Version 3](LICENSE). All contributions must adhere to the terms and conditions of this license. By submitting a pull request, you attest that you own the necessary rights on the code and you will abide to the AGPL3 license.\n\n### Who do I talk to? ###\n\nHop over to our [Discord](https://discord.gg/DCSmxVD) server or open a ticket please.\n"
  },
  {
    "path": "cmake/modules/FindBugSplat.cmake",
    "content": "set(BUGSPLAT_SDK_ROOT \"\" CACHE PATH \"Root to the bugsplat sdk\")\n\nfind_path(BUGSPLAT_INCLUDE_DIR\n\tNAMES\n\t\tBugSplat.h\n\tHINTS\n\t\t${BUGSPLAT_SDK_ROOT}/inc\n)\n\nfind_library(BUGSPLAT_LIBRARY\n\tNAMES\n\t\tBugSplat64\n\tHINTS\n\t\t${BUGSPLAT_SDK_ROOT}/lib64\n)\n\nfind_file(BUGSPLAT_DLL\n\tNAMES\n\t\tBugSplat64.dll\n\tHINTS\n\t\t${BUGSPLAT_SDK_ROOT}/bin64\n)\n\nfind_file(BUGSPLAT_RC_DLL\n\tNAMES\n\t\tBugSplatRc64.dll\n\tHINTS\n\t\t${BUGSPLAT_SDK_ROOT}/bin64\n)\n\nfind_file(BUGSPLAT_SEND_REPORT\n\tNAMES\n\t\tBsSndRpt64.exe\n\tHINTS\n\t\t${BUGSPLAT_SDK_ROOT}/bin64\n)\n\ninclude(FindPackageHandleStandardArgs)\n# handle the QUIETLY and REQUIRED arguments and set BUGSPLAT_FOUND to TRUE\n# if all listed variables are TRUE\nfind_package_handle_standard_args(BugSplat\n\tDEFAULT_MSG\n\tBUGSPLAT_LIBRARY BUGSPLAT_INCLUDE_DIR BUGSPLAT_DLL BUGSPLAT_RC_DLL BUGSPLAT_SEND_REPORT)\n\nmark_as_advanced(BUGSPLAT_INCLUDE_DIR BUGSPLAT_LIBRARY BUGSPLAT_DLL BUGSPLAT_RC_DLL BUGSPLAT_SEND_REPORT)\n\nif(BUGSPLAT_FOUND AND NOT TARGET BugSplat)\n\tadd_executable(BugSplatSendReport IMPORTED)\n\tset_target_properties(BugSplatSendReport\n\t\tPROPERTIES\n\t\t\tIMPORTED_LOCATION\n\t\t\t\t\"${BUGSPLAT_SEND_REPORT}\"\n\t)\n\tadd_library(BugSplatRc SHARED IMPORTED)\n\tset_target_properties(BugSplatRc\n\t\tPROPERTIES\n\t\t\tIMPORTED_LOCATION\n\t\t\t\t\"${BUGSPLAT_RC_DLL}\"\n\t)\n\tadd_library(BugSplat SHARED IMPORTED)\n\tset_target_properties(BugSplat\n\t\tPROPERTIES\n\t\t\tINTERFACE_INCLUDE_DIRECTORIES\n\t\t\t\t\"${BUGSPLAT_INCLUDE_DIR}\"\n\t\t\tIMPORTED_LINK_DEPENDENT_LIBRARIES\n\t\t\t\tBugSplatRc\n\t\t\tIMPORTED_LOCATION\n\t\t\t\t\"${BUGSPLAT_DLL}\"\n\t\t\tIMPORTED_IMPLIB\n\t\t\t\t\"${BUGSPLAT_LIBRARY}\"\n\t)\n\ttarget_compile_definitions(\n\t\tBugSplat\n\t\tINTERFACE\n\t\t\tHAVE_BUGSPLAT=1\n\t)\nendif()\n"
  },
  {
    "path": "cmake/modules/FindNoesis.cmake",
    "content": "set(NOESIS_ROOT \"\" CACHE PATH \"Root to the NoesisGui sdk\")\n\nfind_path(NOESIS_INCLUDE_DIR\n\tNAMES\n\t\tNoesisPCH.h\n\tHINTS\n\t\t${NOESIS_ROOT}/Include\n)\n\nfind_library(NOESIS_LIBRARY\n\tNAMES\n\t\tlibNoesis Noesis\n\tHINTS\n\t\t${NOESIS_ROOT}/Bin/linux_x86_64\n\t\t${NOESIS_ROOT}/Lib/windows_x86_64\n)\n\nif(WIN32)\n\tfind_file(NOESIS_DLL\n\t\tNAMES\n\t\t\tNoesis.dll\n\t\tHINTS\n\t\t\t${NOESIS_ROOT}/Bin/windows_x86_64\n\t)\nelse()\n\tset(NOESIS_DLL ${NOESIS_LIBRARY})\nendif()\n\ninclude(FindPackageHandleStandardArgs)\n# handle the QUIETLY and REQUIRED arguments and set NOESIS_FOUND to TRUE\n# if all listed variables are TRUE\nfind_package_handle_standard_args(Noesis\n\tDEFAULT_MSG\n\tNOESIS_LIBRARY NOESIS_INCLUDE_DIR NOESIS_DLL)\n\nmark_as_advanced(NOESIS_INCLUDE_DIR NOESIS_LIBRARY NOESIS_DLL)\n\nif(NOESIS_FOUND AND NOT TARGET Noesis)\n\tadd_library(Noesis SHARED IMPORTED)\n\tset_target_properties(Noesis\n\t\tPROPERTIES\n\t\t\tINTERFACE_INCLUDE_DIRECTORIES \"${NOESIS_INCLUDE_DIR}\"\n\t\t\tIMPORTED_LOCATION \"${NOESIS_DLL}\"\n\t\t\tIMPORTED_IMPLIB \"${NOESIS_LIBRARY}\"\n\t)\nendif()"
  },
  {
    "path": "cmake/modules/FindOpenAL.cmake",
    "content": "# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying\n# file Copyright.txt or https://cmake.org/licensing for details.\n\n#[=======================================================================[.rst:\nFindOpenAL\n----------\n\nFinds Open Audio Library (OpenAL).\n\nProjects using this module should use ``#include \"al.h\"`` to include the OpenAL\nheader file, **not** ``#include <AL/al.h>``.  The reason for this is that the\nlatter is not entirely portable.  Windows/Creative Labs does not by default put\ntheir headers in ``AL/`` and macOS uses the convention ``<OpenAL/al.h>``.\n\nHints\n^^^^^\n\nEnvironment variable ``$OPENALDIR`` can be used to set the prefix of OpenAL\ninstallation to be found.\n\nBy default on macOS, system framework is search first.  In other words,\nOpenAL is searched in the following order:\n\n1. System framework: ``/System/Library/Frameworks``, whose priority can be\n   changed via setting the :variable:`CMAKE_FIND_FRAMEWORK` variable.\n2. Environment variable ``$OPENALDIR``.\n3. System paths.\n4. User-compiled framework: ``~/Library/Frameworks``.\n5. Manually compiled framework: ``/Library/Frameworks``.\n6. Add-on package: ``/opt``.\n\nResult Variables\n^^^^^^^^^^^^^^^^\n\nThis module defines the following variables:\n\n``OPENAL_FOUND``\n  If false, do not try to link to OpenAL\n``OPENAL_INCLUDE_DIR``\n  OpenAL include directory\n``OPENAL_LIBRARY``\n  Path to the OpenAL library\n``OPENAL_VERSION_STRING``\n  Human-readable string containing the version of OpenAL\n#]=======================================================================]\n\n# For Windows, Creative Labs seems to have added a registry key for their\n# OpenAL 1.1 installer. I have added that key to the list of search paths,\n# however, the key looks like it could be a little fragile depending on\n# if they decide to change the 1.00.0000 number for bug fix releases.\n# Also, they seem to have laid down groundwork for multiple library platforms\n# which puts the library in an extra subdirectory. Currently there is only\n# Win32 and I have hardcoded that here. This may need to be adjusted as\n# platforms are introduced.\n# The OpenAL 1.0 installer doesn't seem to have a useful key I can use.\n# I do not know if the Nvidia OpenAL SDK has a registry key.\n\nset(OPENAL_ROOT \"\" CACHE PATH \"Root to the OpenAL sdk\")\n\nfind_path(OPENAL_INCLUDE_DIR al.h\n  HINTS\n    ENV OPENALDIR\n    ${OPENAL_ROOT}\n  PATHS\n    ~/Library/Frameworks\n    /Library/Frameworks\n    /opt\n    [HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Creative\\ Labs\\\\OpenAL\\ 1.1\\ Software\\ Development\\ Kit\\\\1.00.0000;InstallDir]\n  PATH_SUFFIXES include/AL include/OpenAL include AL OpenAL\n  )\n\nif(CMAKE_SIZEOF_VOID_P EQUAL 8)\n  set(_OpenAL_ARCH_DIR Win64)\nelse()\n  set(_OpenAL_ARCH_DIR Win32)\nendif()\n\nfind_library(OPENAL_LIBRARY\n  NAMES OpenAL al openal OpenAL32\n  HINTS\n    ENV OPENALDIR\n    ${OPENAL_ROOT}\n  PATHS\n    ~/Library/Frameworks\n    /Library/Frameworks\n    /opt\n    [HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Creative\\ Labs\\\\OpenAL\\ 1.1\\ Software\\ Development\\ Kit\\\\1.00.0000;InstallDir]\n  PATH_SUFFIXES libx32 lib64 lib libs64 libs libs/${_OpenAL_ARCH_DIR}\n  )\n\nif(WIN32)\n\tfind_file(OPENAL_DLL\n\t\tNAMES\n\t\t\tOpenAL32.dll\n\t\tHINTS\n\t\t\t${OPENAL_ROOT}\n\t\tPATH_SUFFIXES libx32 lib64 lib libs64 libs bin/${_OpenAL_ARCH_DIR}\n\t)\nelse()\n\tset(OPENAL_DLL ${OPENAL_LIBRARY})\nendif()\n\nunset(_OpenAL_ARCH_DIR)\n\ninclude(FindPackageHandleStandardArgs)\nfind_package_handle_standard_args(\n  OpenAL\n  REQUIRED_VARS OPENAL_LIBRARY OPENAL_INCLUDE_DIR OPENAL_DLL\n  VERSION_VAR OPENAL_VERSION_STRING\n  )\n\nmark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)\n\nif(OPENAL_FOUND AND NOT TARGET OpenAL)\n\tadd_library(OpenAL SHARED IMPORTED)\n\tset_target_properties(OpenAL\n\t\tPROPERTIES\n\t\t\tINTERFACE_INCLUDE_DIRECTORIES \"${OPENAL_INCLUDE_DIR}\"\n\t\t\tIMPORTED_LOCATION \"${OPENAL_DLL}\"\n\t\t\tIMPORTED_IMPLIB \"${OPENAL_LIBRARY}\")\nendif()"
  },
  {
    "path": "cmake/modules/FindSteam.cmake",
    "content": "set(STEAM_SDK_ROOT \"\" CACHE PATH \"Root to the steam sdk\")\n\nfind_path(STEAM_INCLUDE_DIR\n\tNAMES\n\t\tsteam/steam_api.h\n\tHINTS\n\t\t${STEAM_SDK_ROOT}/public\n)\n\nif(UNIX)\n\tfind_library(STEAM_LIBRARY\n\t\tNAMES\n\t\t\tsteam_api\n\t\tHINTS\n\t\t\t${STEAM_SDK_ROOT}/redistributable_bin/linux64\n\t)\n\tset(STEAM_DLL ${STEAM_LIBRARY})\nelse()\n\tfind_library(STEAM_LIBRARY\n\t\tNAMES\n\t\t\tsteam_api64\n\t\tHINTS\n\t\t\t${STEAM_SDK_ROOT}/redistributable_bin/win64\n\t)\n\tfind_file(STEAM_DLL\n\t\tNAMES\n\t\t\tsteam_api64.dll\n\t\tHINTS\n\t\t\t${STEAM_SDK_ROOT}/redistributable_bin/win64\n\t)\nendif()\n\ninclude(FindPackageHandleStandardArgs)\n# handle the QUIETLY and REQUIRED arguments and set STEAM_FOUND to TRUE\n# if all listed variables are TRUE\nfind_package_handle_standard_args(Steam\n\tDEFAULT_MSG\n\tSTEAM_LIBRARY STEAM_INCLUDE_DIR STEAM_DLL)\n\nmark_as_advanced(STEAM_INCLUDE_DIR STEAM_LIBRARY STEAM_DLL)\n\nif(STEAM_FOUND AND NOT TARGET Steam)\n\tadd_library(Steam SHARED IMPORTED)\n\tset_target_properties(Steam\n\t\tPROPERTIES\n\t\t\tINTERFACE_INCLUDE_DIRECTORIES \"${STEAM_INCLUDE_DIR}\"\n\t\t\tIMPORTED_LOCATION \"${STEAM_DLL}\"\n\t\t\tIMPORTED_IMPLIB \"${STEAM_LIBRARY}\")\nendif()"
  },
  {
    "path": "cmake/modules/windeployqt.cmake",
    "content": "find_package(Qt5 REQUIRED QUIET COMPONENTS Core)\nif(TARGET Qt5::qmake AND NOT TARGET Qt5::windeployqt)\n\tget_target_property(_qt5_qmake_location Qt5::qmake IMPORTED_LOCATION)\n\n\texecute_process(\n\t\tCOMMAND \"${_qt5_qmake_location}\" -query QT_INSTALL_PREFIX\n\t\tRESULT_VARIABLE return_code\n\t\tOUTPUT_VARIABLE qt5_install_prefix\n\t\tOUTPUT_STRIP_TRAILING_WHITESPACE\n\t)\n\n\tset(imported_location \"${qt5_install_prefix}/bin/windeployqt.exe\")\n\n\tif(EXISTS ${imported_location})\n\t\tadd_executable(Qt5::windeployqt IMPORTED)\n\n\t\tset_target_properties(Qt5::windeployqt PROPERTIES\n\t\t\tIMPORTED_LOCATION ${imported_location}\n\t\t)\n\tendif()\nendif()\n\nfunction(windeployqt foo)\n\tif(TARGET Qt5::windeployqt)\n\t\t# execute windeployqt in a tmp directory after build\n\t\tadd_custom_command(TARGET ${foo}\n\t\t\tPOST_BUILD\n\t\t\tCOMMAND ${CMAKE_COMMAND} -E remove_directory \"${CMAKE_CURRENT_BINARY_DIR}/windeployqt_$<CONFIG>\"\n\t\t\tCOMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin\n\t\t\t# for deployment\n\t\t\tCOMMAND Qt5::windeployqt --pdb --no-translations --no-webkit2 --no-system-d3d-compiler --no-opengl-sw --dir \"${CMAKE_CURRENT_BINARY_DIR}/windeployqt_$<CONFIG>\" \"$<TARGET_FILE_DIR:${foo}>/$<TARGET_FILE_NAME:${foo}>\"\n\t\t\tCOMMAND\n\t\t\t\t${CMAKE_COMMAND} -E copy_directory\n\t\t\t\t\"${CMAKE_CURRENT_BINARY_DIR}/windeployqt_$<CONFIG>/\"\n\t\t\t\t$<TARGET_FILE_DIR:${PROJECT_NAME}>\n\t\t)\n\n\t\t# copy deployment directory during installation\n\t\tinstall(\n\t\t\tDIRECTORY\n\t\t\t\"${CMAKE_CURRENT_BINARY_DIR}/windeployqt_$<CONFIG>/\"\n\t\t\tDESTINATION ${CMAKE_INSTALL_BINDIR}\n\t\t)\n\tendif()\nendfunction()"
  },
  {
    "path": "content/CMakeLists.txt",
    "content": "file(\n\tGLOB_RECURSE SOURCE_LIST\n\tRELATIVE ${CMAKE_CURRENT_SOURCE_DIR}\n\t\"*.xml\"\n\t\"*.json\"\n\t\"*.glsl\"\n\t\"*.xaml\"\n\t\"*.ttf\"\n\t\"*.otf\"\n\t\"*.png\"\n\t\"*.sql\"\n\t\"*.wav\"\n\t\"*License*\"\n)\n\ntarget_sources(${PROJECT_NAME}\n\tPRIVATE\n\t\t${SOURCE_LIST}\n\t\t${CMAKE_CURRENT_LIST_FILE}\n)\n\nforeach ( FILE ${SOURCE_LIST} )\n    get_filename_component( DIR ${FILE} DIRECTORY )\n    install(\n\t\tFILES ${FILE}\n\t\tDESTINATION \"${CMAKE_INSTALL_BINDIR}/content/${DIR}\"\n\t)\nendforeach()\n"
  },
  {
    "path": "content/JSON/config.json",
    "content": "{\n    \"AutoSaveInterval\": 3,\n    \"CurrentVersion\": \"0.7.5.0\",\n    \"DaysToNextAutoSave\": 1,\n    \"GUIScale\": 1.0,\n    \"LastRunVersion\": \"0.7.5.0\",\n    \"MaxArrayTextures\": \"2048\",\n    \"Pause\": true,\n    \"WindowHeight\": 1631,\n    \"WindowPosX\": 604,\n    \"WindowPosY\": 53,\n    \"WindowWidth\": 3231,\n    \"XpMod\": 250,\n    \"clearLogOnStart\": \"true\",\n    \"crosshair\": \"false\",\n    \"dataPath\": \"content/\",\n    \"enableLog\": \"true\",\n    \"enableScaling\": \"true\",\n    \"fontSize\": \"12\",\n    \"fow\": \"true\",\n    \"framelessWindow\": \"false\",\n    \"gfxPath\": \"content/tilesheet\",\n    \"keyboardMoveSpeed\": \"100\",\n    \"language\": \"english\",\n    \"lightDecay\": \"3\",\n    \"maxThreads\": \"20\",\n    \"modDev\": \"true\",\n    \"moveX\": 0,\n    \"moveY\": -800,\n    \"oldMoveX\": 0,\n    \"oldMoveY\": -800,\n    \"overlay\": true,\n    \"playerName\": \"Player\",\n    \"port\": \"55555\",\n    \"random\": 133,\n    \"renderCreatures\": true,\n    \"renderDepth\": \"20\",\n    \"renderMode\": \"up\",\n    \"rotation\": 0,\n    \"scale\": 1,\n    \"server\": \"127.0.0.1\",\n    \"viewLevel\": 108,\n    \"waterQuality\": 1,\n    \"windowSizeX\": 1600,\n    \"windowSizeY\": 900\n}"
  },
  {
    "path": "content/JSON/embarkpresets.json",
    "content": "[\r\n{\r\n\t\"Name\": \"Gnomoria\",\r\n\t\"startingItems\": [{\r\n\t\t\t\"Amount\": 2,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"Pickaxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"FellingAxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 128,\r\n\t\t\t\"ItemID\": \"Wine\",\r\n\t\t\t\"MaterialID\": \"Apple\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 32,\r\n\t\t\t\"ItemID\": \"Bread\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 32,\r\n\t\t\t\"ItemID\": \"Fruit\",\r\n\t\t\t\"MaterialID\": \"Strawberry\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 32,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 32,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Strawberry\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Gender\": \"male\",\r\n\t\t\t\"ItemID\": \"Yak\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Gender\": \"female\",\r\n\t\t\t\"ItemID\": \"Yak\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t}\r\n\t]\r\n},\r\n{\r\n\t\"Name\": \"Easy\",\r\n\t\"startingItems\": [{\r\n\t\t\t\"Amount\": 4,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"Pickaxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 4,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"FellingAxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 4,\r\n\t\t\t\"ItemID\": \"Chisel\",\r\n\t\t\t\"MaterialID\": \"Granite\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 4,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"KnifeBlade\",\r\n\t\t\t\t\t\"MaterialID\": \"Copper\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"KnifeHilt\",\r\n\t\t\t\t\t\"MaterialID\": \"Copper\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"Knife\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 100,\r\n\t\t\t\"ItemID\": \"Wine\",\r\n\t\t\t\"MaterialID\": \"Apple\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 100,\r\n\t\t\t\"ItemID\": \"Bread\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 100,\r\n\t\t\t\"ItemID\": \"Beer\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 20,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 30,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Strawberry\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 20,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Barley\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 20,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Cotton\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"ItemID\": \"Needle\",\r\n\t\t\t\"MaterialID\": \"Copper\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 5,\r\n\t\t\t\"Gender\": \"female\",\r\n\t\t\t\"ItemID\": \"Chicken\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Gender\": \"male\",\r\n\t\t\t\"ItemID\": \"Cow\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 2,\r\n\t\t\t\"Gender\": \"female\",\r\n\t\t\t\"ItemID\": \"Cow\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t}\r\n\t]\r\n},\r\n{\r\n\t\"Name\": \"Medium\",\r\n\t\"startingItems\": [{\r\n\t\t\t\"Amount\": 2,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Granite\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"Pickaxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 2,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"FellingAxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 50,\r\n\t\t\t\"ItemID\": \"Wine\",\r\n\t\t\t\"MaterialID\": \"Apple\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 50,\r\n\t\t\t\"ItemID\": \"Bread\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 50,\r\n\t\t\t\"ItemID\": \"Beer\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 20,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 30,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Strawberry\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Gender\": \"male\",\r\n\t\t\t\"ItemID\": \"Cow\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Gender\": \"female\",\r\n\t\t\t\"ItemID\": \"Cow\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t}\r\n\t]\r\n},\r\n{\r\n\t\"Name\": \"Hard\",\r\n\t\"startingItems\": [{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"PickaxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"Pickaxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Components\": [{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeHead\",\r\n\t\t\t\t\t\"MaterialID\": \"Granite\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"ItemID\": \"FellingAxeBase\",\r\n\t\t\t\t\t\"MaterialID\": \"Pine\"\r\n\t\t\t\t}\r\n\t\t\t],\r\n\t\t\t\"ItemID\": \"FellingAxe\",\r\n\t\t\t\"Type\": \"CombinedItem\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 50,\r\n\t\t\t\"ItemID\": \"Wine\",\r\n\t\t\t\"MaterialID\": \"Apple\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 50,\r\n\t\t\t\"ItemID\": \"Bread\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 50,\r\n\t\t\t\"ItemID\": \"Beer\",\r\n\t\t\t\"MaterialID\": \"Wheat\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 30,\r\n\t\t\t\"ItemID\": \"Seed\",\r\n\t\t\t\"MaterialID\": \"Strawberry\",\r\n\t\t\t\"Type\": \"Item\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Amount\": 1,\r\n\t\t\t\"Gender\": \"female\",\r\n\t\t\t\"ItemID\": \"Cow\",\r\n\t\t\t\"Type\": \"Animal\"\r\n\t\t}\r\n\t]\r\n}\r\n]"
  },
  {
    "path": "content/JSON/menusettings.json",
    "content": "[\r\n  {\r\n\t\"Text\": \"Terrain\",\r\n\t\"Icon\": \":/resources/icons/terrain.png\",\r\n\t\"MenuItem\": [\r\n\t  {\r\n\t\t\"Text\": \"Mine\",\r\n\t\t\"Icon\": \":/resources/icons/mine.png\",\r\n\t\t\"MenuItem\": [\r\n\t\t  {\r\n\t\t\t\"Text\": \"Wall\",\r\n\t\t\t\"Icon\": \":/resources/icons/mine_wall.png\",\r\n\t\t\t\"ToolTip\": \"Remove wall\",\r\n\t\t\t\"Action\": \"Mine\"\r\n\t\t  },\r\n\t\t  {\r\n\t\t\t\"Text\": \"Stairs Up\",\r\n\t\t\t\"Icon\": \":/resources/icons/mine_stairs.png\",\r\n\t\t\t\"ToolTip\": \"Mine the wall into stairs going up\",\r\n\t\t\t\"Action\": \"MineStairsUp\"\r\n\t\t  },\r\n\t\t  {\r\n\t\t\t\"Text\": \"Ramp Up\",\r\n\t\t\t\"Icon\": \":/resources/icons/mine_ramp.png\",\r\n\t\t\t\"ToolTip\": \"Mine the wall into a ramp going up\",\r\n\t\t\t\"Disable\": true,\r\n\t\t\t\"Action\": \"MineRampUp\"\r\n\t\t  },\r\n\t\t  {\r\n\t\t\t\"Text\": \"Explorative Mine Wall\",\r\n\t\t\t\"Icon\": \":/resources/icons/mine_wall.png\",\r\n\t\t\t\"ToolTip\": \"Remove wall and continue mining if there are embedded materials in neighboring tiles\",\r\n\t\t\t\"Action\": \"ExplorativeMine\"\r\n\t\t  },\r\n\t\t  {\r\n\t\t\t\"Text\": \"Fill Hole\",\r\n\t\t\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\t\t\"ToolTip\": \"Build wall in the tile below\",\r\n\t\t\t\"Action\": \"FillHole\"\r\n\t\t  }\r\n\t\t]\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Dig\",\r\n\t\t\"Icon\": \":/resources/icons/dig.png\",\r\n\t\t\"MenuItem\": [\r\n\t\t  {\r\n\t\t\t\"Text\": \"Hole\",\r\n\t\t\t\"Icon\": \":/resources/icons/dig_hole\",\r\n\t\t\t\"ToolTip\": \"Remove floor and section below\",\r\n\t\t\t\"Action\": \"DigHole\"\r\n\t\t  },\r\n\t\t  {\r\n\t\t\t\"Text\": \"Stairs Down\",\r\n\t\t\t\"Icon\": \":/resources/icons/dig_stairs\",\r\n\t\t\t\"ToolTip\": \"Remove floor and mine section below into stairs\",\r\n\t\t\t\"Action\": \"DigStairsDown\"\r\n\t\t  },\r\n\t\t  {\r\n\t\t\t\"Text\": \"Ramp Down\",\r\n\t\t\t\"Icon\": \":/resources/icons/dig_ramp\",\r\n\t\t\t\"ToolTip\": \"Remove floor and mine section below into a ramp\",\r\n\t\t\t\"Action\": \"DigRampDown\"\r\n\t\t  }\r\n\t\t]\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Remove Floor\",\r\n\t\t\"Icon\": \":/resources/icons/remove_floor.png\",\r\n\t\t\"ToolTip\": \"Remove floor leaving the section below untouched\",\r\n\t\t\"Action\": \"RemoveFloor\"\r\n\t  },\r\n\t  /*\r\n\t  {\r\n\t\t\"Text\": \"Remove Ramp\",\r\n\t\t\"Icon\": \":/resources/icons/remove_ramp.png\",\r\n\t\t\"ToolTip\": \"Remove ramp\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Action\": \"RemoveRamp\"\r\n\t  },\r\n\t  */\r\n\t  {\r\n\t\t\"Text\": \"Replace Wall\",\r\n\t\t\"Icon\": \":/resources/icons/replace_wall.png\",\r\n\t\t\"ToolTip\": \"Replaces an existing wall with a new one\",\r\n\t\t\"Action\": \"ReplaceWindowWall\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Replace Floor\",\r\n\t\t\"Icon\": \":/resources/icons/replace_floor.png\",\r\n\t\t\"ToolTip\": \"Replaces an existing floor with a new one\",\r\n\t\t\"Action\": \"ReplaceWindowFloor\"\r\n\t  }/*,\r\n\t  {\r\n\t\t\"Text\": \"Fill Hole\",\r\n\t\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\t\"ToolTip\": \"Build a wall from above\",\r\n\t\t\"Action\": \"BuildWall\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Hide\",\r\n\t\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\t\"ToolTip\": \"Set terrain to Hidden\",\r\n\t\t\"Action\": \"Hide\"\r\n\t  }*/\r\n\t]\r\n  },\r\n  {\r\n\t\"Text\": \"Agriculture\",\r\n\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\"MenuItem\": [\r\n\t  {\r\n\t\t\"Text\": \"Farm\",\r\n\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\"ToolTip\": \"Grow crops\",\r\n\t\t\"Action\": \"CreateFarm\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Underground Farm\",\r\n\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\"ToolTip\": \"Grow underground crops\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Action\": \"CreateUndergroundFarm\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Pasture\",\r\n\t\t\"Icon\": \":/resources/icons/pasture.png\",\r\n\t\t\"ToolTip\": \"Livestock graze in a pasture\",\r\n\t\t\"Action\": \"CreatePasture\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Grove\",\r\n\t\t\"Icon\": \":/resources/icons/grove.png\",\r\n\t\t\"ToolTip\": \"Grow and harvest trees\",\r\n\t\t\"Disable\": false,\r\n\t\t\"Action\": \"CreateGrove\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Plant Trees\",\r\n\t\t\"Icon\": \":/resources/icons/grove.png\",\r\n\t\t\"ToolTip\": \"Plant trees\",\r\n\t\t\"Action\": \"PlantTreeWidget\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Fell Trees\",\r\n\t\t\"Icon\": \":/resources/icons/fell_trees.png\",\r\n\t\t\"ToolTip\": \"Cut trees down\",\r\n\t\t\"Action\": \"FellTree\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Pick Fruit\",\r\n\t\t\"Icon\": \":/resources/icons/cut_clipping.png\",\r\n\t\t\"ToolTip\": \"Pick a fruit from a tree\",\r\n\t\t\"Action\": \"HarvestTree\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Forage\",\r\n\t\t\"Icon\": \":/resources/icons/forage.png\",\r\n\t\t\"ToolTip\": \"Forage for food\",\r\n\t\t\"Action\": \"Forage\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Remove Plant\",\r\n\t\t\"Icon\": \":/resources/icons/cancel.png\",\r\n\t\t\"ToolTip\": \"Remove plant\",\r\n\t\t\"Action\": \"RemovePlant\"\r\n\t  }\r\n\t]\r\n  },\r\n  {\r\n\t\"Text\": \"Build\",\r\n\t\"Icon\": \":/resources/icons/build.png\",\r\n\t\"MenuItem\": [\r\n\t\t{\r\n\t\t\t\"Text\": \"Workshop\",\r\n\t\t\t\"Icon\": \":/resources/icons/workshop.png\",\r\n\t\t\t\"ToolTip\": \"Workshop\",\r\n\t\t\t\"Action\": \"BuildWorkshopWindow\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Mechanism\",\r\n\t\t\t\"Icon\": \":/resources/icons/gear.png\",\r\n\t\t\t\"ToolTip\": \"Mechanism\",\r\n\t\t\t\"MenuItem\": [\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Build Mechanism\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/engineering.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Build Mechanism\",\r\n\t\t\t\t\t\"Action\": \"BuildMechanismWidget\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Build Hydraulics\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/hydraulics.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Build Hydraulics\",\r\n\t\t\t\t\t\"Action\": \"BuildHydraulicsWidget\"\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Furniture\",\r\n\t\t\t\"Icon\": \":/resources/icons/furniture.png\",\r\n\t\t\t\"ToolTip\": \"Furniture\",\r\n\t\t\t\"Action\": \"BuildFurnitureWidget\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Storage\",\r\n\t\t\t\"Icon\": \":/resources/icons/chest.png\",\r\n\t\t\t\"ToolTip\": \"Storage\",\r\n\t\t\t\"Action\": \"BuildStorageWidget\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Terrain\",\r\n\t\t\t\"Icon\": \":/resources/icons/terrain.png\",\r\n\t\t\t\"ToolTip\": \"Terrain\",\r\n\t\t\t\"MenuItem\": [\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Build Wall\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Build Wall\",\r\n\t\t\t\t\t\"Action\": \"BuildWindowWall\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Build Floor\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/dig_hole.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Build Floor\",\r\n\t\t\t\t\t\"Action\": \"BuildWindowFloor\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Build Stairs\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/stair.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Build Stairs\",\r\n\t\t\t\t\t\"Action\": \"BuildWindowStairs\"\r\n\t\t\t\t},\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Build Ramps\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/mine_ramp.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Build Ramps\",\r\n\t\t\t\t\t\"Action\": \"BuildWindowRamp\"\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Utility\",\r\n\t\t\t\"Icon\": \":/resources/icons/door.png\",\r\n\t\t\t\"ToolTip\": \"Utility\",\r\n\t\t\t\"Action\": \"BuildUtilityWidget\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Farm untils\",\r\n\t\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\t\"ToolTip\": \"FarmUtil\",\r\n\t\t\t\"Action\": \"BuildFarmUtilWidget\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Build Scaffold\",\r\n\t\t\t\"Icon\": \":/resources/icons/scaffolding.png\",\r\n\t\t\t\"ToolTip\": \"Build Scaffold\",\r\n\t\t\t\"Action\": \"BuildWindowScaffold\"\r\n\t\t},\r\n\t]\r\n  },\r\n  {\r\n\t\"Text\": \"Designate Area\",\r\n\t\"Icon\": \":/resources/icons/designate_area.png\",\r\n\t\"MenuItem\": [\r\n\t  {\r\n\t\t\"Text\": \"Stockpile\",\r\n\t\t\"Icon\": \":/resources/icons/chest.png\",\r\n\t\t\"ToolTip\": \"Store items\",\r\n\t\t\"Action\": \"CreateStockpile\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Agriculture\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\"ToolTip\": \"Agriculture\",\r\n\t\t\"MenuItem\": [\r\n\t\t\t{\r\n\t\t\t\t\"Text\": \"Farm\",\r\n\t\t\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\t\t\"ToolTip\": \"Grow crops\",\r\n\t\t\t\t\"Action\": \"CreateFarm\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"Text\": \"Underground Farm\",\r\n\t\t\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\t\t\"ToolTip\": \"Grow underground crops\",\r\n\t\t\t\t\"Disable\": true,\r\n\t\t\t\t\"Action\": \"CreateUndergroundFarm\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"Text\": \"Pasture\",\r\n\t\t\t\t\"Icon\": \":/resources/icons/pasture.png\",\r\n\t\t\t\t\"ToolTip\": \"Livestock graze in a pasture\",\r\n\t\t\t\t\"Disable\": true,\r\n\t\t\t\t\"Action\": \"CreatePasture\"\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"Text\": \"Grove\",\r\n\t\t\t\t\"Icon\": \":/resources/icons/grove.png\",\r\n\t\t\t\t\"ToolTip\": \"Grow and harvest trees\",\r\n\t\t\t\t\"Disable\": true,\r\n\t\t\t\t\"Action\": \"CreateGrove\"\r\n\t\t\t}\r\n\t\t]\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Room\",\r\n\t\t\"Icon\": \":/resources/icons/room.png\",\r\n\t\t\"ToolTip\": \"Room\",\r\n\t\t\"Action\": \"CreateRoom\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Guard Area\",\r\n\t\t\"Icon\": \":/resources/icons/guard.png\",\r\n\t\t\"ToolTip\": \"Designate area to guard\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Action\": \"CreateGuardArea\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Patrol Route\",\r\n\t\t\"Icon\": \":/resources/icons/patrol.png\",\r\n\t\t\"ToolTip\": \"Designate waypoints to patrol\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Action\": \"CreatePatrolRoute\"\r\n\t  },\r\n\t  {\r\n\t\t\t\"Text\": \"No pass\",\r\n\t\t\t\"Icon\": \":/resources/icons/remove_designation.png\",\r\n\t\t\t\"ToolTip\": \"Designate area gnomes will not walk on.\",\r\n\t\t\t\"Action\": \"CreateNoPass\"\r\n\t\t}\r\n\t]\r\n  },\r\n  {\r\n\t\"Text\": \"Magic\",\r\n\t\"Icon\": \":/resources/icons/patrol.png\",\r\n\t\"ToolTip\": \"Magic\",\r\n\t\"MenuItem\": [\r\n\t\t{\r\n\t\t\t\"Text\": \"Nature Magic\",\r\n\t\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\t\"ToolTip\": \"Nature magic\",\r\n\t\t\t\"MenuItem\": [\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Speed up growth\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/agriculture.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Speed up growth\",\r\n\t\t\t\t\t\"Action\": \"MagicNatureSpeedGrowth\"\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"Text\": \"Geomancy\",\r\n\t\t\t\"Icon\": \":/resources/icons/mine.png\",\r\n\t\t\t\"ToolTip\": \"Geomancy\",\r\n\t\t\t\"MenuItem\": [\r\n\t\t\t\t{\r\n\t\t\t\t\t\"Text\": \"Reveal ore\",\r\n\t\t\t\t\t\"Icon\": \":/resources/icons/mine.png\",\r\n\t\t\t\t\t\"ToolTip\": \"Reveal ore\",\r\n\t\t\t\t\t\"Action\": \"MagicGeomancyRevealOre\"\r\n\t\t\t\t}\r\n\t\t\t]\r\n\t\t}\r\n\t]\r\n  },\r\n  {\r\n\t\"Text\": \"Job\",\r\n\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\"MenuItem\": [\r\n\t  {\r\n\t\t\"Text\": \"Suspend\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\t\"ToolTip\": \"Suspend\",\r\n\t\t\"Action\": \"SuspendJob\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Resume\",\r\n\t\t\"Disable\": true,\r\n\t\t\"Icon\": \":/resources/icons/job.png\",\r\n\t\t\"ToolTip\": \"Resume\",\r\n\t\t\"Action\": \"ResumeJob\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Cancel\",\r\n\t\t\"Icon\": \":/resources/icons/cancel.png\",\r\n\t\t\"ToolTip\": \"Cancel\",\r\n\t\t\"Action\": \"CancelJob\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Raise priority\",\r\n\t\t\"Icon\": \":/resources/icons/arrow_up.png\",\r\n\t\t\"ToolTip\": \"Raise the priority of a job.\",\r\n\t\t\"Action\": \"RaisePrio\"\r\n\t  },\r\n\t  {\r\n\t\t\"Text\": \"Lower priority\",\r\n\t\t\"Icon\": \":/resources/icons/arrow_down.png\",\r\n\t\t\"ToolTip\": \"Lower the priority of a job.\",\r\n\t\t\"Action\": \"LowerPrio\"\r\n\t  }\r\n\t]\r\n  },\r\n  {\r\n\t\"Text\": \"Clean Floor\",\r\n\t\"Icon\": \":/resources/icons/chest.png\",\r\n\t\"ToolTip\": \"Stock items on this floor next if possible\",\r\n\t\"Disable\": true,\r\n\t\"Action\": \"CleanFloor\"\r\n  },\r\n  {\r\n\t\"Text\": \"Deconstruct\",\r\n\t\"Icon\": \":/resources/icons/deconstruct.png\",\r\n\t\"ToolTip\": \"Deconstruct\",\r\n\t\"Action\": \"Deconstruct\"\r\n  },\r\n  {\r\n\t\"Text\": \"Remove Designation\",\r\n\t\"Icon\": \":/resources/icons/remove_designation.png\",\r\n\t\"ToolTip\": \"Remove Designation\",\r\n\t\"Action\": \"RemoveDesignation\"\r\n  }\r\n]\r\n"
  },
  {
    "path": "content/JSON/newgame.json",
    "content": "{\n    \"allowedAnimals\": {\n        \"Badger\": 2,\n        \"Beetle\": 0,\n        \"BeetleEgg\": 0,\n        \"BlackBear\": 2,\n        \"Duck\": 0,\n        \"Fox\": 1,\n        \"Goat\": 0,\n        \"GreenFish\": 0,\n        \"GreyFish\": 0,\n        \"Lizzard\": 0,\n        \"Panda\": 0,\n        \"Porcupine\": 2,\n        \"Rabbit\": 0,\n        \"Roe\": 0,\n        \"Snake\": 0,\n        \"Spider\": 0,\n        \"Squirrel\": 2,\n        \"Stag\": 0,\n        \"Wolf\": 1,\n        \"Woodlouse\": 0\n    },\n    \"allowedPlants\": {\n        \"Blackberry\": true,\n        \"Carrot\": true,\n        \"Cotton\": true,\n        \"Flower1\": false,\n        \"Flower2\": false,\n        \"Flower3\": false,\n        \"Flower4\": false,\n        \"Flower5\": false,\n        \"Flower6\": false,\n        \"Flower7\": false,\n        \"Flower8\": false,\n        \"Onion\": true,\n        \"Strawberry\": true\n    },\n    \"allowedTrees\": {\n        \"AppleTree\": true,\n        \"BirchTree\": true,\n        \"OakTree\": true,\n        \"OrangeTree\": true,\n        \"PineTree\": true\n    },\n    \"dimX\": 100,\n    \"dimY\": 100,\n    \"dimZ\": 130,\n    \"flatness\": 0,\n    \"groundLevel\": 100,\n    \"maxPerType\": 30,\n    \"numAnimals\": 473,\n    \"numGnomes\": 1,\n    \"oceanSize\": 5,\n    \"peaceful\": true,\n    \"plantDensity\": 50,\n    \"riverSize\": 1,\n    \"rivers\": 0,\n    \"seed\": \"532879058\",\n    \"startingItems\": [\n        {\n            \"Amount\": 2,\n            \"Components\": [\n                {\n                    \"ItemID\": \"PickaxeHead\",\n                    \"MaterialID\": \"Pine\"\n                },\n                {\n                    \"ItemID\": \"PickaxeBase\",\n                    \"MaterialID\": \"Pine\"\n                }\n            ],\n            \"ItemID\": \"Pickaxe\",\n            \"Type\": \"CombinedItem\"\n        },\n        {\n            \"Amount\": 1,\n            \"Components\": [\n                {\n                    \"ItemID\": \"FellingAxeHead\",\n                    \"MaterialID\": \"Pine\"\n                },\n                {\n                    \"ItemID\": \"FellingAxeBase\",\n                    \"MaterialID\": \"Pine\"\n                }\n            ],\n            \"ItemID\": \"FellingAxe\",\n            \"Type\": \"CombinedItem\"\n        },\n        {\n            \"Amount\": 128,\n            \"ItemID\": \"Wine\",\n            \"MaterialID\": \"Apple\",\n            \"Type\": \"Item\"\n        },\n        {\n            \"Amount\": 32,\n            \"ItemID\": \"Bread\",\n            \"MaterialID\": \"Wheat\",\n            \"Type\": \"Item\"\n        },\n        {\n            \"Amount\": 32,\n            \"ItemID\": \"Fruit\",\n            \"MaterialID\": \"Strawberry\",\n            \"Type\": \"Item\"\n        },\n        {\n            \"Amount\": 32,\n            \"ItemID\": \"Grain\",\n            \"MaterialID\": \"Wheat\",\n            \"Type\": \"Item\"\n        },\n        {\n            \"Amount\": 32,\n            \"ItemID\": \"Seed\",\n            \"MaterialID\": \"Strawberry\",\n            \"Type\": \"Item\"\n        },\n        {\n            \"Amount\": 1,\n            \"Gender\": \"Male\",\n            \"ItemID\": \"Yak\",\n            \"Type\": \"Animal\"\n        },\n        {\n            \"Amount\": 1,\n            \"Gender\": \"Female\",\n            \"ItemID\": \"Yak\",\n            \"Type\": \"Animal\"\n        }\n    ],\n    \"startingZone\": 10,\n    \"treeDensity\": 51\n}\n"
  },
  {
    "path": "content/JSON/profs.json",
    "content": "[\n\t{\n        \"Name\": \"Gnomad\",\n        \"Skills\": [\n\t\t\t\"Mining\",\n\t\t\t\"Masonry\",\n\t\t\t\"Stonecarving\",\n\t\t\t\"Woodcutting\",\n\t\t\t\"Carpentry\",\n\t\t\t\"Woodcarving\",\n\t\t\t\"Smelting\",\n\t\t\t\"Blacksmithing\",\n\t\t\t\"Metalworking\",\n\t\t\t\"WeaponCrafting\",\n\t\t\t\"ArmorCrafting\",\n\t\t\t\"Gemcutting\",\n\t\t\t\"JewelryMaking\",\n\t\t\t\"Weaving\",\n\t\t\t\"Tailoring\",\n\t\t\t\"Dying\",\n\t\t\t\"Pottery\",\n\t\t\t\"Leatherworking\",\n\t\t\t\"Bonecarving\",\n\t\t\t\"Prospecting\",\n\t\t\t\"Tinkering\",\n\t\t\t\"Machining\",\n\t\t\t\"Engineering\",\n\t\t\t\"Mechanic\",\n\t\t\t\"AnimalHusbandry\",\n\t\t\t\"Butchery\",\n\t\t\t\"Fishing\",\n\t\t\t\"Horticulture\",\n\t\t\t\"Farming\",\n\t\t\t\"Cooking\",\n\t\t\t\"Brewing\",\n\t\t\t\"Construction\",\n\t\t\t\"Hauling\"\n\t\t]\n\t},\n    {\n        \"Name\": \"Miner\",\n        \"Skills\": [\n            \"Mining\",\n            \"Construction\",\n            \"Hauling\"\n        ]\n    },\n    {\n        \"Name\": \"Farmer\",\n        \"Skills\": [\n            \"Horticulture\",\n            \"Farming\",\n            \"Hauling\"\n        ]\n    },\n    {\n        \"Name\": \"Woodcutter\",\n        \"Skills\": [\n            \"Woodcutting\",\n            \"Carpentry\",\n            \"Woodcarving\",\n            \"Hauling\"\n        ]\n    },\n    {\n        \"Name\": \"Mason\",\n        \"Skills\": [\n            \"Masonry\",\n            \"Construction\",\n            \"Hauling\"\n        ]\n    }\n]\n"
  },
  {
    "path": "content/ai/animal_big.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <FallbackStar name=\"AnimalStandard\">\n            <Action ID=\"RandomMoveBig\"/>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"ShedTree\">\n        <FallbackStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsDay\"/>\n                <Condition ID=\"IsInShed\"/>\n                <Action ID=\"LeaveShed\"/>\n                <Action ID=\"FindRandomPastureField\"/>\n                <Action ID=\"Move\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsNight\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"FindShed\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EnterShed\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsDay\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"RandomMove\"/>\n            </SequenceStar>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"EnterShed\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"FindRandomPastureField\"/>\n        <Action ID=\"FindRetreat\"/>\n        <Action ID=\"FindShed\"/>\n        <Action ID=\"GiveBirth\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInShed\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Condition ID=\"IsOnPasture\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"LeaveShed\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"RandomMoveBig\"/>\n        <SubTree ID=\"ShedTree\"/>\n        <Action ID=\"Sleep\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/animal_guard_dog.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Sequence>\n            <SequenceStar>\n                <Fallback>\n                    <Action ID=\"GuardDogGetTarget\"/>\n\t\t\t\t\t<Action ID=\"GetTarget\"/>\n                </Fallback>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n        </Sequence>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AttackTarget\"/>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"EnterShed\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"FindRandomPastureField\"/>\n        <Action ID=\"FindRetreat\"/>\n        <Action ID=\"FindShed\"/>\n        <Action ID=\"GiveBirth\"/>\n\t\t<Action ID=\"GetTarget\"/>\n        <Action ID=\"GuardDogGetTarget\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInShed\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Condition ID=\"IsOnPasture\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"LeaveShed\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <SubTree ID=\"ShedTree\"/>\n        <Action ID=\"Sleep\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/animal_hunter.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Fallback>\n            <SequenceStar>\n                <Action ID=\"GetTarget\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n            <FallbackStar name=\"AnimalHunter\">\n                <SequenceStar name=\"Hunt\">\n                    <Condition ID=\"IsHungry\"/>\n                    <Action ID=\"FindPrey\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"KillPrey\"/>\n                    <Action ID=\"EatPrey\"/>\n                </SequenceStar>\n                <Action ID=\"RandomMove\"/>\n            </FallbackStar>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Condition ID=\"\"/>\n        <Action ID=\"AttackTarget\"/>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"GetTarget\"/>\n        <Action ID=\"GiveBirth\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/animal_nighthunter.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <FallbackStar>\n            <SequenceStar>\n                <Action ID=\"GetTarget\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n            <SequenceStar name=\"Hunt\">\n                <Condition ID=\"IsNight\"/>\n                <Condition ID=\"IsHungry\"/>\n                <Action ID=\"FindPrey\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"KillPrey\"/>\n                <Action ID=\"EatPrey\"/>\n            </SequenceStar>\n            <SequenceStar name=\"Retreat\">\n                <Condition ID=\"IsDay\"/>\n                <Action ID=\"FindRetreat\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"IsDay\"/>\n                    <Action ID=\"Sleep\"/>\n                </Sequence>\n            </SequenceStar>\n            <Action ID=\"RandomMove\"/>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AttackTarget\"/>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"FindRetreat\"/>\n        <Action ID=\"GetTarget\"/>\n        <Action ID=\"GiveBirth\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"Sleep\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/animal_small_pasture.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <FallbackStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsDay\"/>\n                <Condition ID=\"IsInShed\"/>\n                <Action ID=\"LeaveShed\"/>\n                <Action ID=\"FindRandomPastureField\"/>\n                <Action ID=\"Move\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsNight\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"FindShed\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EnterShed\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsDay\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"RandomMove\"/>\n            </SequenceStar>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"EnterShed\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"FindRandomPastureField\"/>\n        <Action ID=\"FindRetreat\"/>\n        <Action ID=\"FindShed\"/>\n        <Action ID=\"GiveBirth\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInShed\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Condition ID=\"IsOnPasture\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"LeaveShed\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"Sleep\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/animal_standard.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <FallbackStar name=\"AnimalStandard\">\n            <SequenceStar name=\"Sex\">\n                <Condition ID=\"IsMale\"/>\n                <Condition ID=\"IsAdult\"/>\n                <Action ID=\"TryHaveSex\"/>\n            </SequenceStar>\n            <SequenceStar name=\"Birth\">\n                <Condition ID=\"IsFemale\"/>\n                <Condition ID=\"IsReadyToGiveBirth\"/>\n                <Action ID=\"GiveBirth\"/>\n            </SequenceStar>\n            <SequenceStar name=\"EggLayer\">\n                <Condition ID=\"IsEggLayer\"/>\n                <Action ID=\"LayEgg\"/>\n            </SequenceStar>\n            <SequenceStar name=\"Producer\">\n                <Condition ID=\"IsProducer\"/>\n                <Action ID=\"Produce\"/>\n            </SequenceStar>\n            <SubTree ID=\"ShedTree\"/>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"ShedTree\">\n        <FallbackStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsDay\"/>\n                <Condition ID=\"IsInShed\"/>\n                <Action ID=\"LeaveShed\"/>\n                <Action ID=\"FindRandomPastureField\"/>\n                <Action ID=\"Move\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsNight\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"FindShed\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EnterShed\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsDay\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"RandomMove\"/>\n                <Action ID=\"Graze\"/>\n            </SequenceStar>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"EnterShed\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"FindRandomPastureField\"/>\n        <Action ID=\"FindRetreat\"/>\n        <Action ID=\"FindShed\"/>\n        <Action ID=\"GiveBirth\"/>\n        <Action ID=\"Graze\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInShed\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Condition ID=\"IsOnPasture\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"LeaveShed\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <SubTree ID=\"ShedTree\"/>\n        <Action ID=\"Sleep\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/automaton_mark1.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Combat\">\n        <SequenceStar>\n            <Condition ID=\"IsInCombat\"/>\n            <Action ID=\"AbortJob\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"GetTarget\"/>\n                    <Action ID=\"Move\"/>\n                    <Sequence>\n                        <Condition ID=\"TargetAdjacent\"/>\n                        <Action ID=\"AttackTarget\"/>\n                    </Sequence>\n                </SequenceStar>\n            </ForceSuccess>\n            <Condition ID=\"IsInCombat\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"GetUniform\">\n        <SequenceStar name=\"GetUniform\">\n            <Action ID=\"CheckUniform\"/>\n            <Fallback>\n                <Action ID=\"Move\"/>\n                <Action ID=\"UniformCleanUp\"/>\n            </Fallback>\n            <Action ID=\"EquipUniform\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Hunger\">\n        <SequenceStar>\n            <Condition ID=\"IsHungry\"/>\n            <Sequence>\n                <SequenceStar name=\"Hunger\">\n                    <Action ID=\"FindFood\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"PickUpItem\"/>\n                    <ForceSuccess>\n                        <SequenceStar>\n                            <Action ID=\"FindDining\"/>\n                            <Action ID=\"Move\"/>\n                        </SequenceStar>\n                    </ForceSuccess>\n                    <Action ID=\"Eat\"/>\n                </SequenceStar>\n                <Condition ID=\"IsFull\"/>\n            </Sequence>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobButcherAnimal\">\n        <BB_Precondition expected=\"ButcherAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ButcherAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobDyeAnimal\">\n        <BB_Precondition expected=\"DyeAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitJob\"/>\n                    <Action ID=\"ClaimItems\"/>\n                    <SubTree ID=\"MoveAllItemsToJob\"/>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"DyeAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobHarvestAnimal\">\n        <BB_Precondition expected=\"HarvestAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"HarvestAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobHaulMultiple\">\n        <BB_Precondition expected=\"HauleMultipleItems\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitJob\"/>\n                    <Action ID=\"FindTool\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"EquipTool\"/>\n                    <Inverter>\n                        <Sequence>\n                            <Inverter>\n                                <Condition ID=\"AllPickedUp\"/>\n                            </Inverter>\n                            <Sequence>\n                                <Action ID=\"Move\"/>\n                                <Action ID=\"PickUpItem\"/>\n                            </Sequence>\n                            <Action ID=\"ReturnAlwaysRunning\"/>\n                        </Sequence>\n                    </Inverter>\n                    <Condition ID=\"AllPickedUp\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"DropAllItems\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobLeadAnimalToPasture\">\n        <BB_Precondition expected=\"LeadAnimalToPasture\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobStandard\">\n        <Fallback>\n            <SequenceStar name=\"StandardJobs\">\n                <Action ID=\"InitJob\"/>\n                <Action ID=\"ClaimItems\"/>\n                <Action ID=\"FindTool\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EquipTool\"/>\n                <SubTree ID=\"MoveAllItemsToJob\"/>\n                <Action ID=\"GetWorkPosition\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"Work\"/>\n                <Action ID=\"FinishJob\"/>\n            </SequenceStar>\n            <Action ID=\"AbortJob\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobTameAnimal\">\n        <BB_Precondition expected=\"TameAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"TameAnimal\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Jobs\">\n        <SequenceStar>\n            <Action ID=\"GetJob\"/>\n            <FallbackStar>\n                <SubTree ID=\"JobButcherAnimal\"/>\n                <SubTree ID=\"JobDyeAnimal\"/>\n                <SubTree ID=\"JobLeadAnimalToPasture\"/>\n                <SubTree ID=\"JobHarvestAnimal\"/>\n                <SubTree ID=\"JobTameAnimal\"/>\n                <SubTree ID=\"JobHaulMultiple\"/>\n                <SubTree ID=\"JobStandard\"/>\n            </FallbackStar>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <SubTree ID=\"Jobs\"/>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MoveAllItemsToJob\">\n        <Sequence>\n            <Inverter>\n                <Sequence>\n                    <Inverter>\n                        <Condition ID=\"AllItemsInPlaceForJob\"/>\n                    </Inverter>\n                    <SequenceStar>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Action ID=\"GetItemDropPosition\"/>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                    <Action ID=\"ReturnAlwaysRunning\"/>\n                </Sequence>\n            </Inverter>\n            <Condition ID=\"AllItemsInPlaceForJob\"/>\n        </Sequence>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"OldMoveAllItemsToJob\">\n        <FallbackStar>\n            <Condition ID=\"AllItemsInPlaceForJob\"/>\n            <RetryUntilSuccesful num_attempts=\"20\">\n                <Sequence>\n                    <SequenceStar>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Fallback>\n                            <Action ID=\"GetItemDropPosition\"/>\n                            <Action ID=\"DropItem\"/>\n                        </Fallback>\n                        <Fallback>\n                            <Action ID=\"Move\"/>\n                            <Action ID=\"DropItem\"/>\n                        </Fallback>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                    <Condition ID=\"AllItemsInPlaceForJob\"/>\n                </Sequence>\n            </RetryUntilSuccesful>\n            <ForceFailure>\n                <Action ID=\"AbortJob\"/>\n            </ForceFailure>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Sleepy\">\n        <SequenceStar name=\"Sleep\">\n            <Condition ID=\"IsSleepy\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"FindBed\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </ForceSuccess>\n            <Action ID=\"Sleep\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Thirst\">\n        <SequenceStar>\n            <Condition ID=\"IsThirsty\"/>\n            <Sequence>\n                <SequenceStar name=\"Thirst\">\n                    <Action ID=\"FindDrink\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"PickUpItem\"/>\n                    <ForceSuccess>\n                        <SequenceStar>\n                            <Action ID=\"FindDining\"/>\n                            <Action ID=\"Move\"/>\n                        </SequenceStar>\n                    </ForceSuccess>\n                    <Action ID=\"Drink\"/>\n                </SequenceStar>\n                <Condition ID=\"IsDrinkFull\"/>\n            </Sequence>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Trainer\">\n        <SequenceStar name=\"Trainer\">\n            <Condition ID=\"IsTrainer\"/>\n            <Action ID=\"FindTrainerPosition\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"SuperviseTraining\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Training\">\n        <SequenceStar name=\"Training\">\n            <Condition ID=\"IsTrainingTime\"/>\n            <Action ID=\"FindTrainingGround\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"Train\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AbortJob\"/>\n        <Condition ID=\"AllItemsInPlaceForJob\"/>\n        <Condition ID=\"AllPickedUp\"/>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"ButcherAnimal\"/>\n        <Action ID=\"CheckUniform\"/>\n        <Action ID=\"ClaimItems\"/>\n        <SubTree ID=\"Combat\"/>\n        <Action ID=\"Drink\"/>\n        <Action ID=\"DropAllItems\"/>\n        <Action ID=\"DropItem\"/>\n        <Action ID=\"DyeAnimal\"/>\n        <Action ID=\"Eat\"/>\n        <Action ID=\"EquipTool\"/>\n        <Action ID=\"EquipUniform\"/>\n        <Action ID=\"FinalMoveAnimal\"/>\n        <Action ID=\"FindBed\"/>\n        <Action ID=\"FindDining\"/>\n        <Action ID=\"FindDrink\"/>\n        <Action ID=\"FindFood\"/>\n        <Action ID=\"FindTool\"/>\n        <Action ID=\"FindTrainerPosition\"/>\n        <Action ID=\"FindTrainingGround\"/>\n        <Action ID=\"FinishJob\"/>\n        <Action ID=\"GetItemDropPosition\"/>\n        <Action ID=\"GetJob\"/>\n        <Action ID=\"GetTarget\"/>\n        <SubTree ID=\"GetUniform\"/>\n        <Action ID=\"GetWorkPosition\"/>\n        <Action ID=\"GrabAnimal\"/>\n        <Action ID=\"HarvestAnimal\"/>\n        <SubTree ID=\"Hunger\"/>\n        <Action ID=\"InitAnimalJob\"/>\n        <Action ID=\"InitButcherJob\"/>\n        <Action ID=\"InitJob\"/>\n        <Condition ID=\"IsButcherJob\"/>\n        <Condition ID=\"IsDrinkFull\"/>\n        <Condition ID=\"IsFull\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInCombat\"/>\n        <Condition ID=\"IsSleepy\"/>\n        <Condition ID=\"IsThirsty\"/>\n        <Condition ID=\"IsTrainer\"/>\n        <Condition ID=\"IsTrainingTime\"/>\n        <Condition ID=\"IsVeryHungry\"/>\n        <Condition ID=\"IsVeryThirsty\"/>\n        <SubTree ID=\"JobButcherAnimal\"/>\n        <SubTree ID=\"JobDyeAnimal\"/>\n        <SubTree ID=\"JobHarvestAnimal\"/>\n        <SubTree ID=\"JobHaulMultiple\"/>\n        <SubTree ID=\"JobLeadAnimalToPasture\"/>\n        <SubTree ID=\"JobStandard\"/>\n        <SubTree ID=\"JobTameAnimal\"/>\n        <SubTree ID=\"Jobs\"/>\n        <Action ID=\"Move\"/>\n        <SubTree ID=\"MoveAllItemsToJob\"/>\n        <SubTree ID=\"OldMoveAllItemsToJob\"/>\n        <Action ID=\"PickUpItem\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"ReleaseAnimal\"/>\n        <Action ID=\"ReturnAlwaysRunning\"/>\n        <Action ID=\"Sleep\"/>\n        <SubTree ID=\"Sleepy\"/>\n        <Action ID=\"SuperviseTraining\"/>\n        <Action ID=\"TameAnimal\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n        <SubTree ID=\"Thirst\"/>\n        <Action ID=\"Train\"/>\n        <SubTree ID=\"Trainer\"/>\n        <SubTree ID=\"Training\"/>\n        <Action ID=\"UniformCleanUp\"/>\n        <Action ID=\"Work\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/automaton_mark2.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Combat\">\n        <SequenceStar>\n            <Condition ID=\"IsInCombat\"/>\n            <Action ID=\"AbortJob\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"GetTarget\"/>\n                    <Action ID=\"Move\"/>\n                    <Sequence>\n                        <Condition ID=\"TargetAdjacent\"/>\n                        <Action ID=\"AttackTarget\"/>\n                    </Sequence>\n                </SequenceStar>\n            </ForceSuccess>\n            <Condition ID=\"IsInCombat\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"GetUniform\">\n        <SequenceStar name=\"GetUniform\">\n            <Action ID=\"CheckUniform\"/>\n            <Fallback>\n                <Action ID=\"Move\"/>\n                <Action ID=\"UniformCleanUp\"/>\n            </Fallback>\n            <Action ID=\"EquipUniform\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Hunger\">\n        <SequenceStar>\n            <Condition ID=\"IsHungry\"/>\n            <Sequence>\n                <SequenceStar name=\"Hunger\">\n                    <Action ID=\"FindFood\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"PickUpItem\"/>\n                    <ForceSuccess>\n                        <SequenceStar>\n                            <Action ID=\"FindDining\"/>\n                            <Action ID=\"Move\"/>\n                        </SequenceStar>\n                    </ForceSuccess>\n                    <Action ID=\"Eat\"/>\n                </SequenceStar>\n                <Condition ID=\"IsFull\"/>\n            </Sequence>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobButcherAnimal\">\n        <BB_Precondition expected=\"ButcherAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ButcherAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobDyeAnimal\">\n        <BB_Precondition expected=\"DyeAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitJob\"/>\n                    <Action ID=\"ClaimItems\"/>\n                    <SubTree ID=\"MoveAllItemsToJob\"/>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"DyeAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobHarvestAnimal\">\n        <BB_Precondition expected=\"HarvestAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"HarvestAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobHaulMultiple\">\n        <BB_Precondition expected=\"HauleMultipleItems\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitJob\"/>\n                    <Action ID=\"FindTool\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"EquipTool\"/>\n                    <Inverter>\n                        <Sequence>\n                            <Inverter>\n                                <Condition ID=\"AllPickedUp\"/>\n                            </Inverter>\n                            <Sequence>\n                                <Action ID=\"Move\"/>\n                                <Action ID=\"PickUpItem\"/>\n                            </Sequence>\n                            <Action ID=\"ReturnAlwaysRunning\"/>\n                        </Sequence>\n                    </Inverter>\n                    <Condition ID=\"AllPickedUp\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"DropAllItems\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobLeadAnimalToPasture\">\n        <BB_Precondition expected=\"LeadAnimalToPasture\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobStandard\">\n        <Fallback>\n            <SequenceStar name=\"StandardJobs\">\n                <Action ID=\"InitJob\"/>\n                <Action ID=\"ClaimItems\"/>\n                <Action ID=\"FindTool\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EquipTool\"/>\n                <SubTree ID=\"MoveAllItemsToJob\"/>\n                <Action ID=\"GetWorkPosition\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"Work\"/>\n                <Action ID=\"FinishJob\"/>\n            </SequenceStar>\n            <Action ID=\"AbortJob\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobTameAnimal\">\n        <BB_Precondition expected=\"TameAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"TameAnimal\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Jobs\">\n        <SequenceStar>\n            <Action ID=\"GetJob\"/>\n            <FallbackStar>\n                <SubTree ID=\"JobButcherAnimal\"/>\n                <SubTree ID=\"JobDyeAnimal\"/>\n                <SubTree ID=\"JobLeadAnimalToPasture\"/>\n                <SubTree ID=\"JobHarvestAnimal\"/>\n                <SubTree ID=\"JobTameAnimal\"/>\n                <SubTree ID=\"JobHaulMultiple\"/>\n                <SubTree ID=\"JobStandard\"/>\n            </FallbackStar>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <SubTree ID=\"Jobs\"/>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MoveAllItemsToJob\">\n        <Sequence>\n            <Inverter>\n                <Sequence>\n                    <Inverter>\n                        <Condition ID=\"AllItemsInPlaceForJob\"/>\n                    </Inverter>\n                    <SequenceStar>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Action ID=\"GetItemDropPosition\"/>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                    <Action ID=\"ReturnAlwaysRunning\"/>\n                </Sequence>\n            </Inverter>\n            <Condition ID=\"AllItemsInPlaceForJob\"/>\n        </Sequence>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"OldMoveAllItemsToJob\">\n        <FallbackStar>\n            <Condition ID=\"AllItemsInPlaceForJob\"/>\n            <RetryUntilSuccesful num_attempts=\"20\">\n                <Sequence>\n                    <SequenceStar>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Fallback>\n                            <Action ID=\"GetItemDropPosition\"/>\n                            <Action ID=\"DropItem\"/>\n                        </Fallback>\n                        <Fallback>\n                            <Action ID=\"Move\"/>\n                            <Action ID=\"DropItem\"/>\n                        </Fallback>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                    <Condition ID=\"AllItemsInPlaceForJob\"/>\n                </Sequence>\n            </RetryUntilSuccesful>\n            <ForceFailure>\n                <Action ID=\"AbortJob\"/>\n            </ForceFailure>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Sleepy\">\n        <SequenceStar name=\"Sleep\">\n            <Condition ID=\"IsSleepy\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"FindBed\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </ForceSuccess>\n            <Action ID=\"Sleep\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Thirst\">\n        <SequenceStar>\n            <Condition ID=\"IsThirsty\"/>\n            <Sequence>\n                <SequenceStar name=\"Thirst\">\n                    <Action ID=\"FindDrink\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"PickUpItem\"/>\n                    <ForceSuccess>\n                        <SequenceStar>\n                            <Action ID=\"FindDining\"/>\n                            <Action ID=\"Move\"/>\n                        </SequenceStar>\n                    </ForceSuccess>\n                    <Action ID=\"Drink\"/>\n                </SequenceStar>\n                <Condition ID=\"IsDrinkFull\"/>\n            </Sequence>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Trainer\">\n        <SequenceStar name=\"Trainer\">\n            <Condition ID=\"IsTrainer\"/>\n            <Action ID=\"FindTrainerPosition\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"SuperviseTraining\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Training\">\n        <SequenceStar name=\"Training\">\n            <Condition ID=\"IsTrainingTime\"/>\n            <Action ID=\"FindTrainingGround\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"Train\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AbortJob\"/>\n        <Condition ID=\"AllItemsInPlaceForJob\"/>\n        <Condition ID=\"AllPickedUp\"/>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"ButcherAnimal\"/>\n        <Action ID=\"CheckUniform\"/>\n        <Action ID=\"ClaimItems\"/>\n        <SubTree ID=\"Combat\"/>\n        <Action ID=\"Drink\"/>\n        <Action ID=\"DropAllItems\"/>\n        <Action ID=\"DropItem\"/>\n        <Action ID=\"DyeAnimal\"/>\n        <Action ID=\"Eat\"/>\n        <Action ID=\"EquipTool\"/>\n        <Action ID=\"EquipUniform\"/>\n        <Action ID=\"FinalMoveAnimal\"/>\n        <Action ID=\"FindBed\"/>\n        <Action ID=\"FindDining\"/>\n        <Action ID=\"FindDrink\"/>\n        <Action ID=\"FindFood\"/>\n        <Action ID=\"FindTool\"/>\n        <Action ID=\"FindTrainerPosition\"/>\n        <Action ID=\"FindTrainingGround\"/>\n        <Action ID=\"FinishJob\"/>\n        <Action ID=\"GetItemDropPosition\"/>\n        <Action ID=\"GetJob\"/>\n        <Action ID=\"GetTarget\"/>\n        <SubTree ID=\"GetUniform\"/>\n        <Action ID=\"GetWorkPosition\"/>\n        <Action ID=\"GrabAnimal\"/>\n        <Action ID=\"HarvestAnimal\"/>\n        <SubTree ID=\"Hunger\"/>\n        <Action ID=\"InitAnimalJob\"/>\n        <Action ID=\"InitButcherJob\"/>\n        <Action ID=\"InitJob\"/>\n        <Condition ID=\"IsButcherJob\"/>\n        <Condition ID=\"IsDrinkFull\"/>\n        <Condition ID=\"IsFull\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInCombat\"/>\n        <Condition ID=\"IsSleepy\"/>\n        <Condition ID=\"IsThirsty\"/>\n        <Condition ID=\"IsTrainer\"/>\n        <Condition ID=\"IsTrainingTime\"/>\n        <Condition ID=\"IsVeryHungry\"/>\n        <Condition ID=\"IsVeryThirsty\"/>\n        <SubTree ID=\"JobButcherAnimal\"/>\n        <SubTree ID=\"JobDyeAnimal\"/>\n        <SubTree ID=\"JobHarvestAnimal\"/>\n        <SubTree ID=\"JobHaulMultiple\"/>\n        <SubTree ID=\"JobLeadAnimalToPasture\"/>\n        <SubTree ID=\"JobStandard\"/>\n        <SubTree ID=\"JobTameAnimal\"/>\n        <SubTree ID=\"Jobs\"/>\n        <Action ID=\"Move\"/>\n        <SubTree ID=\"MoveAllItemsToJob\"/>\n        <SubTree ID=\"OldMoveAllItemsToJob\"/>\n        <Action ID=\"PickUpItem\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"ReleaseAnimal\"/>\n        <Action ID=\"ReturnAlwaysRunning\"/>\n        <Action ID=\"Sleep\"/>\n        <SubTree ID=\"Sleepy\"/>\n        <Action ID=\"SuperviseTraining\"/>\n        <Action ID=\"TameAnimal\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n        <SubTree ID=\"Thirst\"/>\n        <Action ID=\"Train\"/>\n        <SubTree ID=\"Trainer\"/>\n        <SubTree ID=\"Training\"/>\n        <Action ID=\"UniformCleanUp\"/>\n        <Action ID=\"Work\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/egg.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <ForceSuccess/>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"ShedTree\">\n        <FallbackStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsDay\"/>\n                <Condition ID=\"IsInShed\"/>\n                <Action ID=\"LeaveShed\"/>\n                <Action ID=\"FindRandomPastureField\"/>\n                <Action ID=\"Move\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsOnPasture\"/>\n                <Condition ID=\"IsNight\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"FindShed\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EnterShed\"/>\n            </SequenceStar>\n            <SequenceStar>\n                <Condition ID=\"IsDay\"/>\n                <Inverter>\n                    <Condition ID=\"IsInShed\"/>\n                </Inverter>\n                <Action ID=\"RandomMove\"/>\n                <Action ID=\"Graze\"/>\n            </SequenceStar>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Condition ID=\"CanHaveSex\"/>\n        <Action ID=\"EatPrey\"/>\n        <Action ID=\"EnterShed\"/>\n        <Action ID=\"FindPrey\"/>\n        <Action ID=\"FindRandomPastureField\"/>\n        <Action ID=\"FindRetreat\"/>\n        <Action ID=\"FindShed\"/>\n        <Action ID=\"GiveBirth\"/>\n        <Action ID=\"Graze\"/>\n        <Condition ID=\"IsAdult\"/>\n        <Condition ID=\"IsCarnivore\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsEgg\"/>\n        <Condition ID=\"IsEggLayer\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHerbivore\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInShed\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Condition ID=\"IsOnPasture\"/>\n        <Condition ID=\"IsPregnant\"/>\n        <Condition ID=\"IsProducer\"/>\n        <Condition ID=\"IsReadyToGiveBirth\"/>\n        <Condition ID=\"IsWoodVermin\"/>\n        <Condition ID=\"IsYoung\"/>\n        <Action ID=\"KillPrey\"/>\n        <Action ID=\"LayEgg\"/>\n        <Action ID=\"LeaveShed\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"Produce\"/>\n        <Action ID=\"RandomMove\"/>\n        <SubTree ID=\"ShedTree\"/>\n        <Action ID=\"Sleep\"/>\n        <Action ID=\"TryHaveSex\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/gnome_standard.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"AlarmTree\">\n        <SequenceStar>\n            <Condition ID=\"Alarm\"/>\n            <Condition ID=\"IsCivilian\"/>\n            <Action ID=\"AbortJob\"/>\n            <Fallback>\n                <SequenceStar>\n                    <Condition ID=\"IsInSafeRoom\"/>\n                    <Action ID=\"RandomMove\"/>\n                </SequenceStar>\n                <SequenceStar>\n                    <Action ID=\"GetSafeRoomPosition\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </Fallback>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Combat\">\n        <SequenceStar>\n            <Fallback>\n                <Condition ID=\"IsInCombat\"/>\n                <Condition ID=\"HasHuntTarget\"/>\n            </Fallback>\n            <Action ID=\"AbortJob\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"GetTarget\"/>\n                    <Action ID=\"Move\"/>\n                    <Sequence>\n                        <Condition ID=\"TargetAdjacent\"/>\n                        <Action ID=\"AttackTarget\"/>\n                    </Sequence>\n                </SequenceStar>\n            </ForceSuccess>\n            <Condition ID=\"IsInCombat\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"GetUniform\">\n        <SequenceStar name=\"GetUniform\">\n            <Action ID=\"CheckUniform\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Hunger\">\n        <SequenceStar>\n            <Condition ID=\"IsHungry\"/>\n            <Sequence>\n                <SequenceStar name=\"Hunger\">\n                    <Action ID=\"FindFood\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"PickUpItem\"/>\n                    <ForceSuccess>\n                        <SequenceStar>\n                            <Action ID=\"FindDining\"/>\n                            <Action ID=\"Move\"/>\n                        </SequenceStar>\n                    </ForceSuccess>\n                    <Action ID=\"Eat\"/>\n                </SequenceStar>\n                <Condition ID=\"IsFull\"/>\n            </Sequence>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobButcherAnimal\">\n        <BB_Precondition expected=\"ButcherAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ButcherAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobDyeAnimal\">\n        <BB_Precondition expected=\"DyeAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitJob\"/>\n                    <Action ID=\"ClaimItems\"/>\n                    <SubTree ID=\"MoveAllItemsToJob\"/>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"DyeAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobHarvestAnimal\">\n        <BB_Precondition expected=\"HarvestAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"HarvestAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobHaulMultiple\">\n        <BB_Precondition expected=\"HauleMultipleItems\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitJob\"/>\n                    <Action ID=\"FindTool\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"EquipTool\"/>\n                    <Inverter>\n                        <Sequence>\n                            <Inverter>\n                                <Condition ID=\"AllPickedUp\"/>\n                            </Inverter>\n                            <Sequence>\n                                <Action ID=\"Move\"/>\n                                <Action ID=\"PickUpItem\"/>\n                            </Sequence>\n                            <Action ID=\"ReturnAlwaysRunning\"/>\n                        </Sequence>\n                    </Inverter>\n                    <Condition ID=\"AllPickedUp\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"DropAllItems\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobLeadAnimalToPasture\">\n        <BB_Precondition expected=\"LeadAnimalToPasture\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobStandard\">\n        <Fallback>\n            <SequenceStar name=\"StandardJobs\">\n                <Action ID=\"InitJob\"/>\n                <Action ID=\"ClaimItems\"/>\n                <Action ID=\"FindTool\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"EquipTool\"/>\n                <SubTree ID=\"MoveAllItemsToJob\"/>\n                <Action ID=\"GetWorkPosition\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"Work\"/>\n                <Action ID=\"FinishJob\"/>\n            </SequenceStar>\n            <Action ID=\"AbortJob\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobTameAnimal\">\n        <BB_Precondition expected=\"TameAnimal\" key=\"JobType\">\n            <Fallback>\n                <SequenceStar>\n                    <Action ID=\"InitAnimalJob\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"TameAnimal\"/>\n                    <Action ID=\"GrabAnimal\"/>\n                    <Action ID=\"GetItemDropPosition\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"FinalMoveAnimal\"/>\n                    <Action ID=\"ReleaseAnimal\"/>\n                    <Action ID=\"FinishJob\"/>\n                </SequenceStar>\n                <Action ID=\"AbortJob\"/>\n            </Fallback>\n        </BB_Precondition>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Jobs\">\n        <SequenceStar>\n            <Fallback>\n                <Action ID=\"CheckUniform\"/>\n                <Action ID=\"GetJob\"/>\n            </Fallback>\n            <FallbackStar>\n                <SubTree ID=\"JobButcherAnimal\"/>\n                <SubTree ID=\"JobDyeAnimal\"/>\n                <SubTree ID=\"JobLeadAnimalToPasture\"/>\n                <SubTree ID=\"JobHarvestAnimal\"/>\n                <SubTree ID=\"JobTameAnimal\"/>\n                <SubTree ID=\"JobHaulMultiple\"/>\n                <SubTree ID=\"JobStandard\"/>\n            </FallbackStar>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Fallback>\n            <SubTree ID=\"AlarmTree\"/>\n            <SubTree ID=\"Combat\"/>\n            <SubTree ID=\"Mission\"/>\n            <FallbackStar name=\"Needs\">\n                <SubTree ID=\"Hunger\"/>\n                <SubTree ID=\"Thirst\"/>\n                <SubTree ID=\"Sleepy\"/>\n            </FallbackStar>\n            <FallbackStar name=\"GnomeStandard\">\n                <FallbackStar>\n                    <SubTree ID=\"PickUpBandages\"/>\n                    <SubTree ID=\"Training\"/>\n                    <SubTree ID=\"Trainer\"/>\n                </FallbackStar>\n                <SubTree ID=\"Jobs\"/>\n                <Action ID=\"RandomMove\"/>\n            </FallbackStar>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Mission\">\n        <SequenceStar>\n            <Condition ID=\"IsOnMission\"/>\n            <Action ID=\"AbortJob\"/>\n            <Action ID=\"GetExitPosition\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"LeaveForMission\"/>\n            <Action ID=\"DoMission\"/>\n            <Action ID=\"ReturnFromMission\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MoveAllItemsToJob\">\n        <Sequence>\n            <Inverter>\n                <Sequence>\n                    <Inverter>\n                        <Condition ID=\"AllItemsInPlaceForJob\"/>\n                    </Inverter>\n                    <SequenceStar>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Action ID=\"GetItemDropPosition\"/>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                    <Action ID=\"ReturnAlwaysRunning\"/>\n                </Sequence>\n            </Inverter>\n            <Condition ID=\"AllItemsInPlaceForJob\"/>\n        </Sequence>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"OldMoveAllItemsToJob\">\n        <FallbackStar>\n            <Condition ID=\"AllItemsInPlaceForJob\"/>\n            <RetryUntilSuccesful num_attempts=\"20\">\n                <Sequence>\n                    <SequenceStar>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Fallback>\n                            <Action ID=\"GetItemDropPosition\"/>\n                            <Action ID=\"DropItem\"/>\n                        </Fallback>\n                        <Fallback>\n                            <Action ID=\"Move\"/>\n                            <Action ID=\"DropItem\"/>\n                        </Fallback>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                    <Condition ID=\"AllItemsInPlaceForJob\"/>\n                </Sequence>\n            </RetryUntilSuccesful>\n            <ForceFailure>\n                <Action ID=\"AbortJob\"/>\n            </ForceFailure>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"PickUpBandages\">\n        <SequenceStar>\n            <Action ID=\"CheckBandages\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"PickUpItem\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Sleepy\">\n        <SequenceStar name=\"Sleep\">\n            <Condition ID=\"IsSleepy\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"FindBed\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </ForceSuccess>\n            <Action ID=\"Sleep\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Thirst\">\n        <SequenceStar>\n            <Condition ID=\"IsThirsty\"/>\n            <Sequence>\n                <SequenceStar name=\"Thirst\">\n                    <Action ID=\"FindDrink\"/>\n                    <Action ID=\"Move\"/>\n                    <Action ID=\"PickUpItem\"/>\n                    <ForceSuccess>\n                        <SequenceStar>\n                            <Action ID=\"FindDining\"/>\n                            <Action ID=\"Move\"/>\n                        </SequenceStar>\n                    </ForceSuccess>\n                    <Action ID=\"Drink\"/>\n                </SequenceStar>\n                <Condition ID=\"IsDrinkFull\"/>\n            </Sequence>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Trainer\">\n        <SequenceStar name=\"Trainer\">\n            <Condition ID=\"IsTrainer\"/>\n            <Action ID=\"FindTrainerPosition\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"SuperviseTraining\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Training\">\n        <SequenceStar name=\"Training\">\n            <Condition ID=\"IsTrainingTime\"/>\n            <Action ID=\"FindTrainingGround\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"Train\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AbortJob\"/>\n        <Condition ID=\"Alarm\"/>\n        <SubTree ID=\"AlarmTree\"/>\n        <Condition ID=\"AllItemsInPlaceForJob\"/>\n        <Condition ID=\"AllPickedUp\"/>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"ButcherAnimal\"/>\n        <Action ID=\"CheckBandages\"/>\n        <Action ID=\"CheckUniform\"/>\n        <Action ID=\"ClaimItems\"/>\n        <SubTree ID=\"Combat\"/>\n        <Action ID=\"DoMission\"/>\n        <Action ID=\"Drink\"/>\n        <Action ID=\"DropAllItems\"/>\n        <Action ID=\"DropItem\"/>\n        <Action ID=\"DyeAnimal\"/>\n        <Action ID=\"Eat\"/>\n        <Action ID=\"EnterMap\"/>\n        <Action ID=\"EquipTool\"/>\n        <Action ID=\"EquipUniform\"/>\n        <Action ID=\"FinalMoveAnimal\"/>\n        <Action ID=\"FindBed\"/>\n        <Action ID=\"FindDining\"/>\n        <Action ID=\"FindDrink\"/>\n        <Action ID=\"FindFood\"/>\n        <Action ID=\"FindTool\"/>\n        <Action ID=\"FindTrainerPosition\"/>\n        <Action ID=\"FindTrainingGround\"/>\n        <Action ID=\"FinishJob\"/>\n        <Action ID=\"GetExitPosition\"/>\n        <Action ID=\"GetItemDropPosition\"/>\n        <Action ID=\"GetJob\"/>\n        <Action ID=\"GetSafeRoomPosition\"/>\n        <Action ID=\"GetTarget\"/>\n        <SubTree ID=\"GetUniform\"/>\n        <Action ID=\"GetWorkPosition\"/>\n        <Action ID=\"GrabAnimal\"/>\n        <Action ID=\"HarvestAnimal\"/>\n        <Condition ID=\"HasHuntTarget\"/>\n        <SubTree ID=\"Hunger\"/>\n        <Action ID=\"InitAnimalJob\"/>\n        <Action ID=\"InitButcherJob\"/>\n        <Action ID=\"InitJob\"/>\n        <Condition ID=\"IsButcherJob\"/>\n        <Condition ID=\"IsCivilian\"/>\n        <Condition ID=\"IsDrinkFull\"/>\n        <Condition ID=\"IsFull\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsInCombat\"/>\n        <Condition ID=\"IsInSafeRoom\"/>\n        <Condition ID=\"IsOnMission\"/>\n        <Condition ID=\"IsSleepy\"/>\n        <Condition ID=\"IsThirsty\"/>\n        <Condition ID=\"IsTrainer\"/>\n        <Condition ID=\"IsTrainingTime\"/>\n        <Condition ID=\"IsVeryHungry\"/>\n        <Condition ID=\"IsVeryThirsty\"/>\n        <SubTree ID=\"JobButcherAnimal\"/>\n        <SubTree ID=\"JobDyeAnimal\"/>\n        <SubTree ID=\"JobHarvestAnimal\"/>\n        <SubTree ID=\"JobHaulMultiple\"/>\n        <SubTree ID=\"JobLeadAnimalToPasture\"/>\n        <SubTree ID=\"JobStandard\"/>\n        <SubTree ID=\"JobTameAnimal\"/>\n        <SubTree ID=\"Jobs\"/>\n        <Action ID=\"LeaveForMission\"/>\n        <Action ID=\"LeaveMap\"/>\n        <SubTree ID=\"Mission\"/>\n        <Action ID=\"Move\"/>\n        <SubTree ID=\"MoveAllItemsToJob\"/>\n        <SubTree ID=\"OldMoveAllItemsToJob\"/>\n        <SubTree ID=\"PickUpBandages\"/>\n        <Action ID=\"PickUpItem\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"ReleaseAnimal\"/>\n        <Action ID=\"ReturnAlwaysRunning\"/>\n        <Action ID=\"ReturnFromMission\"/>\n        <Action ID=\"Sleep\"/>\n        <SubTree ID=\"Sleepy\"/>\n        <Action ID=\"SuperviseTraining\"/>\n        <Action ID=\"TameAnimal\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n        <SubTree ID=\"Thirst\"/>\n        <Action ID=\"Train\"/>\n        <SubTree ID=\"Trainer\"/>\n        <SubTree ID=\"Training\"/>\n        <Action ID=\"UniformCleanUp\"/>\n        <Action ID=\"Work\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/gnome_trader.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Hunger\">\n        <SequenceStar name=\"Hunger\">\n            <FallbackStar>\n                <Sequence>\n                    <Condition ID=\"IsHungry\"/>\n                    <Action ID=\"FindFood\"/>\n                </Sequence>\n            </FallbackStar>\n            <Action ID=\"Move\"/>\n            <Action ID=\"PickUpItem\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"FindDining\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </ForceSuccess>\n            <Action ID=\"Eat\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"JobStandard\">\n        <SequenceStar name=\"StandardJobs\">\n            <Action ID=\"InitJob\"/>\n            <Action ID=\"ClaimItems\"/>\n            <Action ID=\"FindTool\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"EquipTool\"/>\n            <RetryUntilSuccesful num_attempts=\"20\">\n                <Inverter>\n                    <SequenceStar>\n                        <Inverter>\n                            <Condition ID=\"AllItemsInPlaceForJob\"/>\n                        </Inverter>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"PickUpItem\"/>\n                        <Action ID=\"GetItemDropPosition\"/>\n                        <Action ID=\"Move\"/>\n                        <Action ID=\"DropItem\"/>\n                    </SequenceStar>\n                </Inverter>\n            </RetryUntilSuccesful>\n            <Action ID=\"GetWorkPosition\"/>\n            <Action ID=\"Move\"/>\n            <Action ID=\"Work\"/>\n            <Action ID=\"FinishJob\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Jobs\">\n        <FallbackStar>\n            <SequenceStar name=\"Leave\">\n                <Condition ID=\"IsTimeToLeave\"/>\n                <Action ID=\"GetExitPosition\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"LeaveMap\"/>\n            </SequenceStar>\n            <SequenceStar name=\"WorkAtMarketStall\">\n                <Action ID=\"GetMarketStallPosition\"/>\n                <Action ID=\"Move\"/>\n                <Action ID=\"Trade\"/>\n            </SequenceStar>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <FallbackStar name=\"GnomeTrader\">\n            <FallbackStar name=\"Needs\">\n                <SubTree ID=\"Hunger\"/>\n                <SubTree ID=\"Thirst\"/>\n                <SubTree ID=\"Sleepy\"/>\n            </FallbackStar>\n            <SubTree ID=\"Jobs\"/>\n        </FallbackStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Sleepy\">\n        <SequenceStar name=\"Sleep\">\n            <Condition ID=\"IsSleepy\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"FindBed\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </ForceSuccess>\n            <Action ID=\"Sleep\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"Thirst\">\n        <SequenceStar name=\"Thirst\">\n            <FallbackStar>\n                <Sequence>\n                    <Condition ID=\"IsThirsty\"/>\n                    <Action ID=\"FindDrink\"/>\n                </Sequence>\n            </FallbackStar>\n            <Action ID=\"Move\"/>\n            <Action ID=\"PickUpItem\"/>\n            <ForceSuccess>\n                <SequenceStar>\n                    <Action ID=\"FindDining\"/>\n                    <Action ID=\"Move\"/>\n                </SequenceStar>\n            </ForceSuccess>\n            <Action ID=\"Drink\"/>\n        </SequenceStar>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Condition ID=\"AllItemsInPlaceForJob\"/>\n        <Action ID=\"ButcherAnimal\"/>\n        <Action ID=\"ClaimItems\"/>\n        <Action ID=\"Drink\"/>\n        <Action ID=\"DropItem\"/>\n        <Action ID=\"Eat\"/>\n        <Action ID=\"EquipTool\"/>\n        <Action ID=\"FindBed\"/>\n        <Action ID=\"FindDrink\"/>\n        <Action ID=\"FindFood\"/>\n        <Action ID=\"FindDining\"/>\n        <Action ID=\"FindTool\"/>\n        <Action ID=\"FinishJob\"/>\n        <Action ID=\"GetExitPosition\"/>\n        <Action ID=\"GetItemDropPosition\"/>\n        <Action ID=\"GetJob\"/>\n        <Action ID=\"GetMarketStallPosition\"/>\n        <Action ID=\"GetWorkPosition\"/>\n        <Action ID=\"GrabAnimal\"/>\n        <Action ID=\"HarvestAnimal\"/>\n        <SubTree ID=\"Hunger\"/>\n        <Action ID=\"InitAnimalJob\"/>\n        <Action ID=\"InitButcherJob\"/>\n        <Action ID=\"InitJob\"/>\n        <Condition ID=\"IsButcherJob\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsSleepy\"/>\n        <Condition ID=\"IsThirsty\"/>\n        <Condition ID=\"IsTimeToLeave\"/>\n        <Condition ID=\"IsVeryHungry\"/>\n        <Condition ID=\"IsVeryThirsty\"/>\n        <SubTree ID=\"JobStandard\"/>\n        <SubTree ID=\"Jobs\"/>\n        <Action ID=\"LeaveMap\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"PickUpItem\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"ReleaseAnimal\"/>\n        <Action ID=\"Sleep\"/>\n        <SubTree ID=\"Sleepy\"/>\n        <SubTree ID=\"Thirst\"/>\n        <Action ID=\"Trade\"/>\n        <Action ID=\"Work\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/monster_mant_queen.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Fallback>\n            <SequenceStar name=\"Main\">\n                <Action ID=\"GetTarget\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n            <Action ID=\"RandomMove\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"GetTarget\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"Sleep\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/monster_mant_soldier.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Fallback>\n            <SequenceStar name=\"Main\">\n                <Action ID=\"GetTarget\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n            <Action ID=\"RandomMove\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"GetTarget\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"Sleep\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/monster_mant_worker.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Fallback>\n            <SequenceStar name=\"Main\">\n                <Action ID=\"GetTarget\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n            <Action ID=\"RandomMove\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"GetTarget\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"Sleep\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/ai/monster_standard.xml",
    "content": "<root main_tree_to_execute=\"MainTree\">\n    <!--  ===================================  -->\n    <BehaviorTree ID=\"MainTree\">\n        <Fallback>\n            <SequenceStar name=\"Main\">\n                <Action ID=\"GetTarget\"/>\n                <Action ID=\"Move\"/>\n                <Sequence>\n                    <Condition ID=\"TargetAdjacent\"/>\n                    <Action ID=\"AttackTarget\"/>\n                </Sequence>\n            </SequenceStar>\n            <Action ID=\"RandomMove\"/>\n        </Fallback>\n    </BehaviorTree>\n    <!--  ===================================  -->\n    <TreeNodesModel>\n        <Action ID=\"AttackTarget\"/>\n        <Action ID=\"GetTarget\"/>\n        <Condition ID=\"IsDay\"/>\n        <Condition ID=\"IsFemale\"/>\n        <Condition ID=\"IsHungry\"/>\n        <Condition ID=\"IsMale\"/>\n        <Condition ID=\"IsNight\"/>\n        <Action ID=\"Move\"/>\n        <Action ID=\"RandomMove\"/>\n        <Action ID=\"Sleep\"/>\n        <Condition ID=\"TargetAdjacent\"/>\n    </TreeNodesModel>\n    <!--  ===================================  -->\n</root>\n\n"
  },
  {
    "path": "content/db/ingnomia.db.sql",
    "content": "BEGIN TRANSACTION;\r\nDROP TABLE IF EXISTS \"Workshops_Components\";\r\nCREATE TABLE IF NOT EXISTS \"Workshops_Components\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Amount\"\tDOUBLE,\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"MaterialItem\"\tVARCHAR(50),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Required\"\tVARCHAR(50),\r\n\t\"Forbidden\"\tVARCHAR(50),\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"SpriteID2\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"WallRotation\"\tVARCHAR(30),\r\n\t\"IsFloor\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Workshops\";\r\nCREATE TABLE IF NOT EXISTS \"Workshops\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Crafts\"\tSTRING,\r\n\t\"GUI\"\tSTRING,\r\n\t\"InputTile\"\tSTRING,\r\n\t\"OutputTile\"\tSTRING,\r\n\t\"Size\"\tSTRING,\r\n\t\"NoAutoGenerate\"\tBOOLEAN,\r\n\t\"Icon\"\tSTRING,\r\n\t\"Tab\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Words_Verb\";\r\nCREATE TABLE IF NOT EXISTS \"Words_Verb\" (\r\n\t\"PastParticiple\"\tVARCHAR(30),\r\n\t\"PresentParticiple\"\tVARCHAR(30),\r\n\t\"SimplePast\"\tVARCHAR(30),\r\n\t\"SimplePresent\"\tVARCHAR(30),\r\n\t\"Word\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Words_Numbers\";\r\nCREATE TABLE IF NOT EXISTS \"Words_Numbers\" (\r\n\t\"Word\"\tSTRING,\r\n\t\"Number\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Words_Noun\";\r\nCREATE TABLE IF NOT EXISTS \"Words_Noun\" (\r\n\t\"Plural\"\tVARCHAR(30),\r\n\t\"Word\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Words_Adjective\";\r\nCREATE TABLE IF NOT EXISTS \"Words_Adjective\" (\r\n\t\"Word\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Words_ActionNoun\";\r\nCREATE TABLE IF NOT EXISTS \"Words_ActionNoun\" (\r\n\t\"Plural\"\tVARCHAR(30),\r\n\t\"Word\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Words\";\r\nCREATE TABLE IF NOT EXISTS \"Words\" (\r\n\t\"Word\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"v_Items\";\r\nCREATE TABLE IF NOT EXISTS \"v_Items\" (\r\n\t\"UID\"\tBIGINT,\r\n\t\"position\"\tVARCHAR,\r\n\t\"spriteID\"\tBIGINT,\r\n\t\"itemUID\"\tINTEGER,\r\n\t\"materialUID\"\tINTEGER,\r\n\t\"itemSID\"\tVARCHAR,\r\n\t\"materialSID\"\tVARCHAR,\r\n\t\"category\"\tVARCHAR,\r\n\t\"group\"\tVARCHAR,\r\n\t\"pickedUp\"\tBOOLEAN,\r\n\t\"isConstructed\"\tBOOLEAN,\r\n\t\"inStockpile\"\tBIGINT,\r\n\t\"inJob\"\tBIGINT,\r\n\t\"isContainer\"\tBOOLEAN,\r\n\t\"inContainer\"\tBIGINT,\r\n\t\"madeBy\"\tBIGINT,\r\n\t\"quality\"\tINTEGER,\r\n\t\"value\"\tINTEGER,\r\n\t\"eatValue\"\tINTEGER,\r\n\t\"drinkValue\"\tINTEGER,\r\n\t\"color\"\tVARCHAR,\r\n\t\"hasComponents\"\tBOOLEAN,\r\n\t\"componentOf\"\tBIGINT,\r\n\t\"isTool\"\tBOOLEAN,\r\n\t\"lightIntensity\"\tINTEGER,\r\n\t\"stackSize\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Utility\";\r\nCREATE TABLE IF NOT EXISTS \"Utility\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Buildable\"\tBOOLEAN,\r\n\t\"Item\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Uniforms\";\r\nCREATE TABLE IF NOT EXISTS \"Uniforms\" (\r\n\t\"ID\"\tINTEGER,\r\n\t\"Name\"\tSTRING,\r\n\t\"UserDefined\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Uniform_Slots\";\r\nCREATE TABLE IF NOT EXISTS \"Uniform_Slots\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Type\"\tSTRING,\r\n\t\"ItemID\"\tSTRING,\r\n\t\"MaterialType\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Uniform\";\r\nCREATE TABLE IF NOT EXISTS \"Uniform\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Sides\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"TreeLayouts_Layout\";\r\nCREATE TABLE IF NOT EXISTS \"TreeLayouts_Layout\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"FruitPos\"\tBOOLEAN,\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Rotation\"\tVARCHAR(30),\r\n\t\"SpriteID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"TreeLayouts\";\r\nCREATE TABLE IF NOT EXISTS \"TreeLayouts\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Translation\";\r\nCREATE TABLE IF NOT EXISTS \"Translation\" (\r\n\t\"ID\"\tVARCHAR NOT NULL UNIQUE,\r\n\t\"Text\"\tVARCHAR,\r\n\tPRIMARY KEY(\"ID\")\r\n);\r\nDROP TABLE IF EXISTS \"Traders_Items\";\r\nCREATE TABLE IF NOT EXISTS \"Traders_Items\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Gender\"\tVARCHAR(30),\r\n\t\"Item\"\tVARCHAR(30),\r\n\t\"Material\"\tVARCHAR(30),\r\n\t\"Max_\"\tINTEGER,\r\n\t\"Min_\"\tINTEGER,\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"Value_\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Traders\";\r\nCREATE TABLE IF NOT EXISTS \"Traders\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Time\";\r\nCREATE TABLE IF NOT EXISTS \"Time\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Value_\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"TerrainMaterials\";\r\nCREATE TABLE IF NOT EXISTS \"TerrainMaterials\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"FloorSprite\"\tVARCHAR(30),\r\n\t\"Highest\"\tDOUBLE,\r\n\t\"Lowest\"\tDOUBLE,\r\n\t\"ShortWallSprite\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"WallSprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Tech\";\r\nCREATE TABLE IF NOT EXISTS \"Tech\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_Seasons_Rotations\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_Seasons_Rotations\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"Rotation\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_Seasons\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_Seasons\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"Season\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_Rotations\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_Rotations\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"Effect\"\tVARCHAR(30),\r\n\t\"Rotation\"\tVARCHAR(30),\r\n\t\"Sprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_Random\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_Random\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"Sprite\"\tVARCHAR(30),\r\n\t\"Weight\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_Frames\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_Frames\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_Combine\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_Combine\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Sprite\"\tVARCHAR(30),\r\n\t\"Tint\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_ByMaterialTypes\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_ByMaterialTypes\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"MaterialType\"\tVARCHAR(30),\r\n\t\"Sprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites_ByMaterials\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites_ByMaterials\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"Effect\"\tVARCHAR(30),\r\n\t\"MaterialID\"\tVARCHAR(30),\r\n\t\"Sprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Sprites\";\r\nCREATE TABLE IF NOT EXISTS \"Sprites\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Anim\"\tBOOLEAN,\r\n\t\"BaseSprite\"\tVARCHAR(30),\r\n\t\"HasRandom\"\tBOOLEAN,\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Rot90\"\tBOOLEAN,\r\n\t\"Tint\"\tVARCHAR(30),\r\n\t\"DefaultMaterial\"\tVARCHAR,\r\n\t\"HasTransp\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Spells\";\r\nCREATE TABLE IF NOT EXISTS \"Spells\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"EffectRequirements\"\tVARCHAR(50),\r\n\t\"Effects\"\tVARCHAR(50),\r\n\t\"Radius\"\tVARCHAR(30),\r\n\t\"SkillID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Skills\";\r\nCREATE TABLE IF NOT EXISTS \"Skills\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"RequiredToolItemID\"\tVARCHAR(30),\r\n\t\"SkillGroup\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"SkillGroups\";\r\nCREATE TABLE IF NOT EXISTS \"SkillGroups\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Color\"\tVARCHAR(30),\r\n\t\"Position\"\tDOUBLE,\r\n\t\"SkillID\"\tVARCHAR(50),\r\n\t\"Text\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Seasons\";\r\nCREATE TABLE IF NOT EXISTS \"Seasons\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"NextSeason\"\tVARCHAR(30),\r\n\t\"NumDays\"\tDOUBLE,\r\n\t\"SunRiseFirst\"\tVARCHAR(30),\r\n\t\"SunsetFirst\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"RandomMetals\";\r\nCREATE TABLE IF NOT EXISTS \"RandomMetals\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Copper\"\tINTEGER,\r\n\t\"Tin\"\tINTEGER,\r\n\t\"Malachite\"\tINTEGER,\r\n\t\"Iron\"\tINTEGER,\r\n\t\"Lead\"\tINTEGER,\r\n\t\"Silver\"\tINTEGER,\r\n\t\"Gold\"\tINTEGER,\r\n\t\"Platinum\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Quality\";\r\nCREATE TABLE IF NOT EXISTS \"Quality\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Rank\"\tINTEGER,\r\n\t\"Modifier\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Plants_States\";\r\nCREATE TABLE IF NOT EXISTS \"Plants_States\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Fell\"\tBOOLEAN,\r\n\t\"GrowTime\"\tDOUBLE,\r\n\t\"GrowTimeDeviation\"\tDOUBLE,\r\n\t\"Harvest\"\tBOOLEAN,\r\n\t\"ID2\"\tVARCHAR(30),\r\n\t\"Layout\"\tVARCHAR(30),\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"HasAlpha\"\tBOOLEAN,\r\n\t\"LightIntensity\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Plants_OnHarvest_HarvestedItem\";\r\nCREATE TABLE IF NOT EXISTS \"Plants_OnHarvest_HarvestedItem\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Chance\"\tDOUBLE,\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"MaterialID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Plants_OnHarvest\";\r\nCREATE TABLE IF NOT EXISTS \"Plants_OnHarvest\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Action\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Plants_OnFell\";\r\nCREATE TABLE IF NOT EXISTS \"Plants_OnFell\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"MaterialID\"\tVARCHAR(30),\r\n\t\"Random\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Plants\";\r\nCREATE TABLE IF NOT EXISTS \"Plants\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"AllowInWild\"\tBOOLEAN,\r\n\t\"FruitItemID\"\tVARCHAR(30),\r\n\t\"GrowsIn\"\tVARCHAR(30),\r\n\t\"GrowsInSeason\"\tVARCHAR(50),\r\n\t\"IsKilledInSeason\"\tVARCHAR(30),\r\n\t\"IsLarge\"\tBOOLEAN,\r\n\t\"LosesFruitInSeason\"\tVARCHAR(30),\r\n\t\"Material\"\tVARCHAR(30),\r\n\t\"NumFruitsPerSeason\"\tDOUBLE,\r\n\t\"SeedItemID\"\tVARCHAR(30),\r\n\t\"ToolButtonSprite\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Needs_States_Modifiers\";\r\nCREATE TABLE IF NOT EXISTS \"Needs_States_Modifiers\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Attribute\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"Value_\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Needs_States\";\r\nCREATE TABLE IF NOT EXISTS \"Needs_States\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Action\"\tVARCHAR(30),\r\n\t\"ID2\"\tVARCHAR(30),\r\n\t\"Priority\"\tDOUBLE,\r\n\t\"ThoughtBubble\"\tVARCHAR(30),\r\n\t\"Threshold\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Needs\";\r\nCREATE TABLE IF NOT EXISTS \"Needs\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BarColor\"\tVARCHAR(30),\r\n\t\"DecayPerMinute\"\tDOUBLE,\r\n\t\"GainFromSleep\"\tDOUBLE,\r\n\t\"Max_\"\tDOUBLE,\r\n\t\"Creature\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Names\";\r\nCREATE TABLE IF NOT EXISTS \"Names\" (\r\n\t\"ID\"\tTEXT,\r\n\t\"Gender\"\tSTRING(1) DEFAULT M\r\n);\r\nDROP TABLE IF EXISTS \"Namerules_Rule\";\r\nCREATE TABLE IF NOT EXISTS \"Namerules_Rule\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Part\"\tVARCHAR(50)\r\n);\r\nDROP TABLE IF EXISTS \"Namerules\";\r\nCREATE TABLE IF NOT EXISTS \"Namerules\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"MoveSpeed\";\r\nCREATE TABLE IF NOT EXISTS \"MoveSpeed\" (\r\n\t\"Creature\"\tSTRING,\r\n\t\"Skill\"\tINTEGER,\r\n\t\"Speed\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Monsters_Levels\";\r\nCREATE TABLE IF NOT EXISTS \"Monsters_Levels\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Level\"\tDOUBLE,\r\n\t\"Sprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Monsters\";\r\nCREATE TABLE IF NOT EXISTS \"Monsters\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BehaviorTree\"\tVARCHAR(30),\r\n\t\"Food\"\tVARCHAR(50)\r\n);\r\nDROP TABLE IF EXISTS \"Missions\";\r\nCREATE TABLE IF NOT EXISTS \"Missions\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"TypeInt\"\tINTEGER,\r\n\t\"MinGnomes\"\tINTEGER,\r\n\t\"MaxGnomes\"\tINTEGER,\r\n\t\"Target\"\tSTRING,\r\n\t\"Actions\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Mechanism\";\r\nCREATE TABLE IF NOT EXISTS \"Mechanism\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"GUI\"\tSTRING,\r\n\t\"Buildable\"\tBOOLEAN,\r\n\t\"Item\"\tSTRING,\r\n\t\"Sprite\"\tSTRING,\r\n\t\"MaxFuel\"\tINTEGER,\r\n\t\"ProducePower\"\tINTEGER,\r\n\t\"ConsumePower\"\tINTEGER,\r\n\t\"Anim\"\tBOOLEAN,\r\n\t\"WallSpriteOn\"\tSTRING,\r\n\t\"WallSpriteOff\"\tSTRING,\r\n\t\"FloorSpriteOn\"\tSTRING,\r\n\t\"FloorSpriteOff\"\tSTRING,\r\n\t\"EffectOn\"\tSTRING,\r\n\t\"EffectOff\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"MaterialToToolLevel\";\r\nCREATE TABLE IF NOT EXISTS \"MaterialToToolLevel\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"RequiredToolLevel\"\tDOUBLE,\r\n\t\"ToolLevel\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Materials\";\r\nCREATE TABLE IF NOT EXISTS \"Materials\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Color\"\tVARCHAR(30),\r\n\t\"Strength\"\tDOUBLE(30),\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"Value\"\tDOUBLE(30)\r\n);\r\nDROP TABLE IF EXISTS \"Magic\";\r\nCREATE TABLE IF NOT EXISTS \"Magic\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Color\"\tVARCHAR(30),\r\n\t\"Spells\"\tVARCHAR(50)\r\n);\r\nDROP TABLE IF EXISTS \"Lairs_Tiles\";\r\nCREATE TABLE IF NOT EXISTS \"Lairs_Tiles\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Offset\"\tSTRING,\r\n\t\"Type\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Lairs_Spawns\";\r\nCREATE TABLE IF NOT EXISTS \"Lairs_Spawns\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Type\"\tSTRING,\r\n\t\"Offset\"\tSTRING,\r\n\t\"Level\"\tINTEGER,\r\n\t\"Rotation\"\tINTEGER,\r\n\t\"Gender\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Lairs\";\r\nCREATE TABLE IF NOT EXISTS \"Lairs\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Type\"\tSTRING,\r\n\t\"Size\"\tSTRING,\r\n\t\"Layout\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Jobs_Tasks\";\r\nCREATE TABLE IF NOT EXISTS \"Jobs_Tasks\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ConstructionID\"\tVARCHAR(30),\r\n\t\"Duration\"\tSTRING,\r\n\t\"Material\"\tVARCHAR(30),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Task\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Jobs_SpriteID\";\r\nCREATE TABLE IF NOT EXISTS \"Jobs_SpriteID\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Rotate\"\tBOOLEAN,\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Jobs\";\r\nCREATE TABLE IF NOT EXISTS \"Jobs\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ConstructionType\"\tVARCHAR(30),\r\n\t\"MayTrapGnome\"\tBOOLEAN,\r\n\t\"RequiredToolItemID\"\tVARCHAR(30),\r\n\t\"RequiredToolLevel\"\tVARCHAR(30),\r\n\t\"SkillGain\"\tVARCHAR(30),\r\n\t\"SkillID\"\tVARCHAR(30),\r\n\t\"TechGain\"\tVARCHAR(30),\r\n\t\"WorkPosition\"\tVARCHAR(50)\r\n);\r\nDROP TABLE IF EXISTS \"Items_Tiles\";\r\nCREATE TABLE IF NOT EXISTS \"Items_Tiles\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Forbidden\"\tVARCHAR(50),\r\n\t\"Required\"\tVARCHAR(50),\r\n\t\"Location\"\tSTRING,\r\n\t\"Offset\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Items_Components\";\r\nCREATE TABLE IF NOT EXISTS \"Items_Components\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"NoMaterial\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Items\";\r\nCREATE TABLE IF NOT EXISTS \"Items\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"SpriteID\"\tSTRING,\r\n\t\"Category\"\tSTRING,\r\n\t\"ItemGroup\"\tSTRING,\r\n\t\"StackSize\"\tINTEGER,\r\n\t\"HasQuality\"\tBOOLEAN,\r\n\t\"Value\"\tINTEGER,\r\n\t\"EatValue\"\tINTEGER,\r\n\t\"DrinkValue\"\tINTEGER,\r\n\t\"IsContainer\"\tBOOLEAN,\r\n\t\"IsTool\"\tBOOLEAN,\r\n\t\"LightIntensity\"\tINTEGER,\r\n\t\"HasComponents\"\tBOOLEAN,\r\n\t\"AllowedMaterialTypes\"\tSTRING,\r\n\t\"AllowedMaterials\"\tSTRING,\r\n\t\"AllowedContainers\"\tSTRING,\r\n\t\"CarryContainer\"\tSTRING,\r\n\t\"AttackValue\"\tINT,\r\n\t\"BurnValue\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"ItemGrouping_Groups\";\r\nCREATE TABLE IF NOT EXISTS \"ItemGrouping_Groups\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"GroupID\"\tVARCHAR(30),\r\n\t\"SpriteID\"\tVARCHAR\r\n);\r\nDROP TABLE IF EXISTS \"ItemGrouping\";\r\nCREATE TABLE IF NOT EXISTS \"ItemGrouping\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Color\"\tSTRING,\r\n\t\"SpriteID\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Hydraulics\";\r\nCREATE TABLE IF NOT EXISTS \"Hydraulics\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Buildable\"\tBOOLEAN,\r\n\t\"Item\"\tSTRING,\r\n\t\"Sprite\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"HairColors\";\r\nCREATE TABLE IF NOT EXISTS \"HairColors\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Color\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"FormationPerks\";\r\nCREATE TABLE IF NOT EXISTS \"FormationPerks\" (\r\n\t\"ID\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Food_Values\";\r\nCREATE TABLE IF NOT EXISTS \"Food_Values\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"MaterialID\"\tSTRING,\r\n\t\"Fruit\"\tDECIMAL,\r\n\t\"Vegetable\"\tDECIMAL,\r\n\t\"Meat\"\tDECIMAL,\r\n\t\"Dairy\"\tDECIMAL,\r\n\t\"Grain\"\tDECIMAL\r\n);\r\nDROP TABLE IF EXISTS \"FarmUtils\";\r\nCREATE TABLE IF NOT EXISTS \"FarmUtils\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Buildable\"\tBOOLEAN,\r\n\t\"Item\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Events_OnSuccess\";\r\nCREATE TABLE IF NOT EXISTS \"Events_OnSuccess\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Action\"\tVARCHAR(30),\r\n\t\"CenterCamera\"\tBOOLEAN,\r\n\t\"Count\"\tVARCHAR(30),\r\n\t\"Message\"\tVARCHAR(300),\r\n\t\"Pause\"\tBOOLEAN,\r\n\t\"Title\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Events_OnFailure\";\r\nCREATE TABLE IF NOT EXISTS \"Events_OnFailure\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Message\"\tVARCHAR(300),\r\n\t\"Title\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Events_Init\";\r\nCREATE TABLE IF NOT EXISTS \"Events_Init\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Title\"\tSTRING,\r\n\t\"Message\"\tSTRING,\r\n\t\"Min\"\tDOUBLE,\r\n\t\"Max\"\tDOUBLE,\r\n\t\"Pause\"\tBOOLEAN,\r\n\t\"Require\"\tSTRING,\r\n\t\"Location\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Events_Expires\";\r\nCREATE TABLE IF NOT EXISTS \"Events_Expires\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"After\"\tDOUBLE,\r\n\t\"Unit\"\tVARCHAR(30),\r\n\t\"Title\"\tVARCHAR(30),\r\n\t\"Message\"\tVARCHAR(300)\r\n);\r\nDROP TABLE IF EXISTS \"Events\";\r\nCREATE TABLE IF NOT EXISTS \"Events\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Trigger_\"\tVARCHAR(30),\r\n\t\"TriggerCount\"\tDOUBLE,\r\n\t\"TriggerUnit\"\tVARCHAR(30),\r\n\t\"NotBeforeDay\"\tINTEGER,\r\n\t\"NotInPeaceful\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"EmbeddedMaterials\";\r\nCREATE TABLE IF NOT EXISTS \"EmbeddedMaterials\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Highest\"\tDOUBLE,\r\n\t\"Lowest\"\tDOUBLE,\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"WallSprite\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Creature_Parts\";\r\nCREATE TABLE IF NOT EXISTS \"Creature_Parts\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Part\"\tSTRING,\r\n\t\"BaseSprite\"\tSTRING,\r\n\t\"Order\"\tINTEGER,\r\n\t\"Tint\"\tSTRING,\r\n\t\"Conceales\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Creature_Layouts\";\r\nCREATE TABLE IF NOT EXISTS \"Creature_Layouts\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Offset\"\tSTRING,\r\n\t\"Sprite\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Crafts_TechGain\";\r\nCREATE TABLE IF NOT EXISTS \"Crafts_TechGain\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"TechID\"\tVARCHAR(30),\r\n\t\"Value\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Crafts_SkillGain\";\r\nCREATE TABLE IF NOT EXISTS \"Crafts_SkillGain\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Value\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Crafts_Prereqs\";\r\nCREATE TABLE IF NOT EXISTS \"Crafts_Prereqs\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Category\"\tVARCHAR(30),\r\n\t\"TechGroup\"\tVARCHAR(30),\r\n\t\"Value\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Crafts_Components\";\r\nCREATE TABLE IF NOT EXISTS \"Crafts_Components\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"AllowedMaterial\"\tVARCHAR(30),\r\n\t\"AllowedMaterialType\"\tVARCHAR(50),\r\n\t\"Amount\"\tINTEGER,\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"RequireSame\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Crafts\";\r\nCREATE TABLE IF NOT EXISTS \"Crafts\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Amount\"\tINTEGER,\r\n\t\"ConversionMaterial\"\tVARCHAR(30),\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"ProductionTime\"\tDOUBLE,\r\n\t\"ResultMaterial\"\tVARCHAR(50),\r\n\t\"ResultMaterialTypes\"\tVARCHAR(50),\r\n\t\"SkillID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Containers_Tiles\";\r\nCREATE TABLE IF NOT EXISTS \"Containers_Tiles\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Construction\"\tBOOLEAN,\r\n\t\"Job\"\tBOOLEAN,\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"Stockpile\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Containers_Components\";\r\nCREATE TABLE IF NOT EXISTS \"Containers_Components\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ItemID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Containers\";\r\nCREATE TABLE IF NOT EXISTS \"Containers\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Buildable\"\tBOOLEAN,\r\n\t\"Capacity\"\tINTEGER,\r\n\t\"RequireSame\"\tBOOLEAN,\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"Item\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"ConstructionTypes\";\r\nCREATE TABLE IF NOT EXISTS \"ConstructionTypes\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Constructions_Sprites\";\r\nCREATE TABLE IF NOT EXISTS \"Constructions_Sprites\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"SpriteIDOverride\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Constructions_IntermediateSprites\";\r\nCREATE TABLE IF NOT EXISTS \"Constructions_IntermediateSprites\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"Percent\"\tDOUBLE,\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Constructions_Components\";\r\nCREATE TABLE IF NOT EXISTS \"Constructions_Components\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Amount\"\tINTEGER,\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"MaterialTypes\"\tVARCHAR(50),\r\n\t\"Materials\"\tVARCHAR(50)\r\n);\r\nDROP TABLE IF EXISTS \"Constructions\";\r\nCREATE TABLE IF NOT EXISTS \"Constructions\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"NoConstruction\"\tBOOLEAN,\r\n\t\"Rotation\"\tBOOLEAN,\r\n\t\"Type\"\tVARCHAR(30),\r\n\t\"Category\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"BaseSprites\";\r\nCREATE TABLE IF NOT EXISTS \"BaseSprites\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"SourceRectangle\"\tVARCHAR(30),\r\n\t\"Tilesheet\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"BaseItems\";\r\nCREATE TABLE IF NOT EXISTS \"BaseItems\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Automaton_Cores_Skills\";\r\nCREATE TABLE IF NOT EXISTS \"Automaton_Cores_Skills\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"SkillID\"\tSTRING,\r\n\t\"SkillValue\"\tINTEGER\r\n);\r\nDROP TABLE IF EXISTS \"Automaton_Cores\";\r\nCREATE TABLE IF NOT EXISTS \"Automaton_Cores\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"BehaviorTree\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Attributes\";\r\nCREATE TABLE IF NOT EXISTS \"Attributes\" (\r\n\t\"ID\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Animals_States_Behavior\";\r\nCREATE TABLE IF NOT EXISTS \"Animals_States_Behavior\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ID2\"\tVARCHAR(30),\r\n\t\"RequiredGender\"\tVARCHAR(30),\r\n\t\"Amount\"\tDOUBLE,\r\n\t\"CreatureID\"\tVARCHAR(30),\r\n\t\"DaysBetween\"\tDOUBLE,\r\n\t\"EatTime\"\tDOUBLE,\r\n\t\"EggID\"\tVARCHAR(30),\r\n\t\"FoodValue\"\tDOUBLE,\r\n\t\"HungerPerTick\"\tDOUBLE,\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"Speed\"\tDOUBLE\r\n);\r\nDROP TABLE IF EXISTS \"Animals_States\";\r\nCREATE TABLE IF NOT EXISTS \"Animals_States\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"ID2\"\tVARCHAR(30),\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"DaysToNextState\"\tDOUBLE,\r\n\t\"Immobile\"\tBOOLEAN,\r\n\t\"BehaviorTree\"\tSTRING,\r\n\t\"IsAggro\"\tBOOLEAN,\r\n\t\"Attack\"\tINTEGER,\r\n\t\"Damage\"\tINTEGER,\r\n\t\"Anatomy\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"Animals_OnButcher\";\r\nCREATE TABLE IF NOT EXISTS \"Animals_OnButcher\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Amount\"\tDOUBLE,\r\n\t\"ItemID\"\tVARCHAR(30),\r\n\t\"Type\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Animals\";\r\nCREATE TABLE IF NOT EXISTS \"Animals\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"AllowInWild\"\tBOOLEAN,\r\n\t\"Aquatic\"\tBOOLEAN,\r\n\t\"BehaviorTree\"\tVARCHAR(30),\r\n\t\"Biome\"\tVARCHAR(30),\r\n\t\"Embark\"\tBOOLEAN,\r\n\t\"Food\"\tVARCHAR(50),\r\n\t\"GestationDays\"\tDOUBLE,\r\n\t\"Pasture\"\tBOOLEAN,\r\n\t\"PastureSize\"\tDOUBLE,\r\n\t\"Prey\"\tVARCHAR(50),\r\n\t\"IsMulti\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Anatomy_Parts\";\r\nCREATE TABLE IF NOT EXISTS \"Anatomy_Parts\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"ID2\"\tSTRING,\r\n\t\"Parent\"\tSTRING,\r\n\t\"IsInside\"\tBOOLEAN,\r\n\t\"Height\"\tSTRING,\r\n\t\"Side\"\tSTRING,\r\n\t\"Facing\"\tSTRING,\r\n\t\"HP\"\tINTEGER,\r\n\t\"IsVital\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Anatomy\";\r\nCREATE TABLE IF NOT EXISTS \"Anatomy\" (\r\n\t\"ID\"\tSTRING,\r\n\t\"Blood\"\tINTEGER,\r\n\t\"Root\"\tSTRING,\r\n\t\"LayerOrder\"\tSTRING\r\n);\r\nDROP TABLE IF EXISTS \"AI\";\r\nCREATE TABLE IF NOT EXISTS \"AI\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"BehaviorTree\"\tVARCHAR(30)\r\n);\r\nDROP TABLE IF EXISTS \"Actions_Tiles\";\r\nCREATE TABLE IF NOT EXISTS \"Actions_Tiles\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Offset\"\tVARCHAR(11),\r\n\t\"SpriteID\"\tVARCHAR(30),\r\n\t\"IsFloor\"\tBOOLEAN,\r\n\t\"Required\"\tVARCHAR(50),\r\n\t\"Forbidden\"\tVARCHAR(50)\r\n);\r\nDROP TABLE IF EXISTS \"Actions\";\r\nCREATE TABLE IF NOT EXISTS \"Actions\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Job\"\tVARCHAR(30),\r\n\t\"ConstructionType\"\tVARCHAR(30),\r\n\t\"ConstructionSelect\"\tBOOLEAN,\r\n\t\"IsFloor\"\tBOOLEAN,\r\n\t\"Multi\"\tBOOLEAN,\r\n\t\"MultiZ\"\tBOOLEAN,\r\n\t\"Rotate\"\tBOOLEAN\r\n);\r\nDROP TABLE IF EXISTS \"Sounds\";\r\nCREATE TABLE IF NOT EXISTS \"Sounds\" (\r\n\t\"ID\"\tVARCHAR(30),\r\n\t\"Material\"\tVARCHAR(30),\r\n\t\"SoundFile\"\tVARCHAR(30)\r\n);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Crude',1.0,'RawWood',NULL,'1 0 0',NULL,NULL,'RawWood',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Crude',1.0,'RawStone',NULL,'0 0 0',NULL,NULL,'GiantStoneBlock',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Crude',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Crude',0.0,NULL,NULL,'1 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Crude',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Crude',0.0,NULL,NULL,'0 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',1.0,'Workbench',NULL,'-1 0 0',NULL,NULL,'Workbench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',1.0,'Chisel',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',0.0,NULL,'1|2','1 0 0',NULL,NULL,'WorkshopTable_AxeBench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',0.0,NULL,'1','1 -1 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',0.0,NULL,'1','1 1 0',NULL,NULL,'CratePlank',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Carpenter',0.0,NULL,'1','-1 1 0',NULL,NULL,'SawHorse',NULL,NULL,'FR',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',1.0,'Workbench',NULL,'-1 0 0',NULL,NULL,'Workbench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',1.0,'Sawblade',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',0.0,NULL,'1|2','1 0 0',NULL,NULL,'SawTableLeft_SawTableBlade',NULL,NULL,'BR',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',0.0,NULL,'1','1 -1 0',NULL,NULL,'SawTableRight',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',0.0,NULL,'1','1 1 0',NULL,NULL,'CrateLog',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Sawmill',0.0,NULL,'1','-1 1 0',NULL,NULL,'SawHorse',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',1.0,'Workbench',NULL,'-1 0 0',NULL,NULL,'Workbench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',1.0,'Chisel',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',0.0,NULL,'2','1 0 0',NULL,NULL,'GiantStoneBlock',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',0.0,NULL,'2','1 -1 0',NULL,NULL,'RawStone',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecutter',0.0,NULL,NULL,'-1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',1.0,'Workbench',NULL,'-1 0 0',NULL,NULL,'Workbench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',1.0,'Chisel',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',0.0,NULL,'1','1 0 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',0.0,NULL,'1','1 -1 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',0.0,NULL,'2','1 1 0',NULL,NULL,'StoneBlockPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonemason',0.0,NULL,'1','-1 1 0',NULL,NULL,'SawHorse',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',1.0,'Table',NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',1.0,'Knife',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',0.0,NULL,'1','1 1 0',NULL,NULL,'WorkshopTable_Meat',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',0.0,NULL,'1','1 0 0',NULL,NULL,'WorkshopTable_KitchenTableTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',0.0,NULL,'1','1 -1 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',0.0,NULL,NULL,'-1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kitchen',0.0,NULL,NULL,'-1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',1.0,'Table',NULL,'1 1 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',2.0,'Barrel',NULL,'-1 0 0',NULL,NULL,'Keg',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,'1','-1 -1 0',NULL,NULL,'Keg',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,'1','-1 1 0',NULL,NULL,'Keg',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,'1','0 1 0',NULL,NULL,'WorkshopWaterTub',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,NULL,'0 -1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,'1','1 -1 0',NULL,NULL,'Distill',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Distillery',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',1.0,'Table',NULL,'1 0 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,NULL,'-1 1 0',NULL,NULL,'DyedCloth',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,'0','-1 -1 0',NULL,NULL,'WoodTub',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,NULL,'-1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Dyer',0.0,NULL,NULL,'1 1 0',NULL,NULL,'Pigment',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',1.0,'Hearth',NULL,'-1 0 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',1.0,'Mold',NULL,'0 0 0',NULL,NULL,'MoldWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',1.0,'Bellows',NULL,'1 -1 0',NULL,NULL,'Bellows',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',0.0,NULL,NULL,'-1 1 0',NULL,NULL,'CoalPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,'OrePile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Forge',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',1.0,'Furnace',NULL,'-1 0 0',NULL,NULL,'FurnaceWithFlame',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',1.0,'Bellows',NULL,'0 0 0',NULL,NULL,'Bellows',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,'1','-1 -1 0',NULL,NULL,'CrateLog',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,NULL,'-1 1 0',NULL,NULL,'CoalPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Furnace',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',1.0,'Furnace',NULL,'-1 0 0',NULL,NULL,'KilnWithFlame',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',1.0,'Bellows',NULL,'0 0 0',NULL,NULL,'Bellows',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,'1','-1 -1 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,'0','-1 1 0',NULL,NULL,'StoneBlockPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,NULL,'1 0 0',NULL,NULL,'CoalPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Kiln',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',1.0,'Bellows',NULL,'-1 0 0',NULL,NULL,'CoalPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',1.0,'Hearth',NULL,'-1 1 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',1.0,'Anvil',NULL,'0 0 0',NULL,NULL,'Anvil',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',0.0,NULL,'2','-1 -1 0',NULL,NULL,'MetalBarPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',0.0,NULL,NULL,'1 -1 0',NULL,NULL,'WaterTrough',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',0.0,NULL,'0','1 0 0',NULL,NULL,'WorkshopTable_Hammer',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Blacksmith',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',1.0,'Anvil',NULL,'-1 0 0',NULL,NULL,'Anvil',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',1.0,'Bellows',NULL,'-1 1 0',NULL,NULL,'Bellows',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',1.0,'Hearth',NULL,'1 0 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',0.0,NULL,'1|0','1 -1 0',NULL,NULL,'WorkshopTable_Statuette',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Metalworker',0.0,NULL,NULL,'1 1 0',NULL,NULL,'WaterTrough',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',1.0,'Workbench',NULL,'-1 -1 0',NULL,NULL,'WorkshopTable_RawGem',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',1.0,'CuttingWheel',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',0.0,NULL,'0|2','-1 0 0',NULL,NULL,'SawTable_TableSaw',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',0.0,NULL,'0','-1 1 0',NULL,NULL,'WorkshopTable',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Gemcutter',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',1.0,'Loom',NULL,'-1 0 0',NULL,NULL,'Loom',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,'1','-1 -1 0',NULL,NULL,'WorkshopTable_Cloth',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,NULL,'-1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,NULL,'1 -1 0',NULL,NULL,'ClothRollTableTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Loom',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',1.0,'Workbench',NULL,'-1 0 0',NULL,NULL,'Workbench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',1.0,'Chisel',NULL,'-1 -1 0',NULL,NULL,'StoneBlockPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',0.0,NULL,'0','-1 1 0',NULL,NULL,'CarpenterStandWithTools',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Stonecarver',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',1.0,'Workbench',NULL,'-1 0 0',NULL,NULL,'Workbench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',1.0,'Chisel',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',0.0,NULL,'0','-1 -1 0',NULL,NULL,'CratePlank',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',0.0,NULL,'0','-1 1 0',NULL,NULL,'CarpenterStandWithTools',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Woodcarver',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',1.0,'Workbench',NULL,'-1 -1 0',NULL,NULL,'WorkshopTable_Gem',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',1.0,'File',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,'0','-1 0 0',NULL,NULL,'WorkshopTable_Vise',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,'0','-1 1 0',NULL,NULL,'WorkshopTable_JewelryPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Jeweler',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',1.0,'Table',NULL,'-1 -1 0',NULL,NULL,'WorkshopTable_ClothRollTableTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',1.0,'Needle',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',0.0,NULL,'0','-1 0 0',NULL,NULL,'WorkshopTable_ShearsTableTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',0.0,NULL,'0','-1 1 0',NULL,NULL,'WorkshopTable_String',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Tailor',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',1.0,'Table',NULL,'-1 -1 0',NULL,NULL,'WorkshopTable_Skull',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',1.0,'Knife',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',0.0,NULL,'0','-1 0 0',NULL,NULL,'WorkshopTable_ChiselTableTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',0.0,NULL,'0','-1 1 0',NULL,NULL,'WorkshopTable_BoneNeedle',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',0.0,NULL,'0','1 -1 0',NULL,NULL,'CarpenterStandWithTools',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Bonecarver',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',1.0,'Table',NULL,'-1 -1 0',NULL,NULL,'WorkshopTable','BigBlood1',NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',1.0,'Knife',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',0.0,NULL,'0|2','-1 0 0',NULL,NULL,'WorkshopTable_ButcherTableTop','ButcherTableTop',NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',0.0,NULL,'0','-1 1 0',NULL,NULL,'WorkshopTable_Meat',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',0.0,NULL,NULL,'1 0 0',NULL,NULL,'MeatStack',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Butcher',0.0,NULL,NULL,'1 1 0',NULL,NULL,'SausageStack',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',3.0,'Table',NULL,'0 -1 0',NULL,NULL,'MarketStallWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,'0','0 0 0',NULL,NULL,'MarketStallWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,'0','0 1 0',NULL,NULL,'MarketStallWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',1.0,'Chair',NULL,'-1 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,NULL,'1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MarketStall',0.0,NULL,'0','-1 1 0',NULL,NULL,'Crate',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',1.0,'Table',NULL,'-1 -1 0',NULL,NULL,'WorkshopTable_ProspectorSliver',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',1.0,'Chisel',NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',0.0,NULL,'0','-1 0 0',NULL,NULL,'WorkshopTable_ChiselTableTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',0.0,NULL,'0','-1 1 0',NULL,NULL,'WorkshopTable_ProspectorOre',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',0.0,NULL,NULL,'1 -1 0',NULL,NULL,'WaterTrough',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Prospector',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',1.0,'Plank',NULL,'0 -1 0','RampTop',NULL,'ScaffoldFloor',NULL,'Floor',NULL,1);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',1.0,'Plank',NULL,'-1 -1 0','RampTop',NULL,'ScaffoldFloor',NULL,'Floor',NULL,1);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',4.0,'Plank',NULL,'1 -1 0','RampTop',NULL,'ScaffoldFloor',NULL,'Floor',NULL,1);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,'0','1 0 0',NULL,NULL,'FishingRodRack',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,NULL,'-1 0 0',NULL,NULL,'FishingFishRack',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,NULL,'-1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,'1','1 1 0',NULL,NULL,'FishingVat',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,NULL,'0 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',1.0,'Table',NULL,'1 -1 0',NULL,NULL,'WorkshopTable','RawHide',NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',0.0,NULL,'0|2','1 0 0',NULL,NULL,'WorkshopTable_AxeBench',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',0.0,NULL,NULL,'-1 1 0',NULL,NULL,'TanningRack',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',1.0,'Chair',NULL,'0 0 0',NULL,NULL,'Chair',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',1.0,'Knife',NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,'TanningRack',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',0.0,NULL,NULL,'-1 0 0',NULL,NULL,'TanningRack',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Leatherworker',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',1.0,'Bellows',NULL,'-1 1 0',NULL,NULL,'Bellows',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',1.0,'Hearth',NULL,'1 1 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',1.0,'Anvil',NULL,'1 0 0',NULL,NULL,'Anvil',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',0.0,NULL,NULL,'1 -1 0',NULL,NULL,'WaterTrough',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',0.0,NULL,NULL,'-1 0 0',NULL,NULL,'UprightWeaponStand',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Weaponsmith',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',1.0,'Bellows',NULL,'1 -1 0',NULL,NULL,'Bellows',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',1.0,'Hearth',NULL,'-1 1 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',1.0,'Anvil',NULL,'-1 0 0',NULL,NULL,'Anvil',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',0.0,NULL,NULL,'1 0 0',NULL,NULL,'WaterTrough',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',0.0,NULL,'1','1 1 0',NULL,NULL,'Statue',NULL,NULL,'BL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Armorer',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-2 -2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-1 -2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'0 -2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'1 -2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'2 -2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-2 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',3.0,'TrainingDummy',NULL,'-1 -1 0',NULL,NULL,'TrainingDummy',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,'0','1 -1 0',NULL,NULL,'TrainingDummy',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'2 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-2 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'2 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-2 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,'0','0 1 0',NULL,NULL,'TrainingDummy',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'2 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-2 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'-1 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'0 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'1 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MeleeTraining',0.0,NULL,NULL,'2 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,'0','0 -1 -1','Ramp','Wall','Scaffold',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,'0','1 -1 -1','Ramp','Wall','Scaffold',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Fishery',0.0,NULL,'0','-1 -1 -1','Ramp','Wall','Scaffold',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',1.0,'Chair','','0 0 0','','','Chair','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',1.0,'Workbench','','-1 0 0','','','Workbench','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',1.0,'Wrench','','0 -1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',0.0,'','','0 1 0','','','WorkshopInputIndicator','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',0.0,'','1|2','1 0 0','','','WorkshopTable_Wrench','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',0.0,'','1','1 -1 0','','','WorkshopTable_Blueprint','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',0.0,'','1|2','1 1 0','','','WorkshopTable_Wheel','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',0.0,'','','-1 -1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Engineer',0.0,'',NULL,'-1 1 0','','',NULL,'','',NULL,'');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',1.0,'Chair','','0 0 0','','','Chair','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',1.0,'Workbench','','-1 0 0','','','Workbench','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',1.0,'CuttingWheel','','0 -1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',0.0,'','','0 1 0','','','WorkshopInputIndicator','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',0.0,'','1|2','1 0 0','','','SawTable_TableSaw','','',NULL,'');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',0.0,'','1','1 -1 0','','','WorkshopTable_Blueprint','','',NULL,'');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',0.0,'','1|2','1 1 0','','','WorkshopTable_Bar','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',0.0,'','','-1 -1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('MachineShop',0.0,'',NULL,'-1 1 0','','',NULL,'','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',1.0,'Chair','','0 0 0','','','Chair','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',1.0,'Workbench','','-1 0 0','','',NULL,'','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',1.0,'Wrench','','0 -1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',0.0,'','','0 1 0','','','WorkshopInputIndicator','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',0.0,'','1|2','1 0 0','','','WorkshopTable_Wrench','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',0.0,'','1','1 -1 0','','','WorkshopTable_Blueprint','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',0.0,'','1|2','1 1 0','','','WorkshopTable_Wheel','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',0.0,'','2','-1 -1 0','','','Automaton','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Automaton',0.0,'','2','-1 1 0','','','AutomatonTorso','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',4.0,'WindmillBlade',NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'0 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'0 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'0 3 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',4.0,'Plank',NULL,'1 1 0',NULL,NULL,'WindmillBase',NULL,NULL,'BR',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,'','4','1 2 0',NULL,NULL,'WindmillBase',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'1 3 0',NULL,NULL,'FlourSack',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'2 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'2 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'2 2 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'2 3 0',NULL,NULL,'FlourSackPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'3 0 0',NULL,NULL,'FlourSackPile',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'3 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,NULL,'3 2 0',NULL,NULL,'Donkey',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'4','3 3 0',NULL,NULL,'Trough',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',4.0,'Plank',NULL,'1 1 1',NULL,NULL,'WindmillBase2',NULL,NULL,'BR',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'8','1 2 1',NULL,NULL,'WindmillBase2',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',4.0,'Plank',NULL,'1 1 2',NULL,NULL,'WindmillRoof',NULL,NULL,'BR',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'12','1 2 2',NULL,NULL,'WindmillRoof',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'0','2 2 2',NULL,NULL,'WindmillSail1',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'0','2 1 2',NULL,NULL,'WindmillSail2',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'0','2 2 1',NULL,NULL,'WindmillSail3',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('Windmill',0.0,NULL,'0','2 1 1',NULL,NULL,'WindmillSail4',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',1.0,'Barrel',NULL,'-1 -1 0',NULL,NULL,'Barrel',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',1.0,'Crate',NULL,'-1 0 0',NULL,NULL,'Crate',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',1.0,'Hearth',NULL,'-1 1 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',1.0,'Furnace',NULL,'0 -1 0',NULL,NULL,'FurnaceWithFlame',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',0.0,'',NULL,'0 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',1.0,'Furnace',NULL,'1 -1 0',NULL,NULL,'FurnaceWithFlame',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('WasteDisposal',0.0,NULL,'2','1 1 0',NULL,NULL,'ForgeWithTop',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',1.0,'Furnace',NULL,'-1 0 0',NULL,NULL,'GlassFurnace',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',1.0,'Crate',NULL,'1 -1 0',NULL,NULL,'Crate',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',0.0,NULL,NULL,'0 1 0',NULL,NULL,'WorkshopInputIndicator',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',0.0,NULL,NULL,'-1 -1 0',NULL,NULL,'SandContainer',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',0.0,NULL,NULL,'0 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',0.0,NULL,NULL,'-1 1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',0.0,NULL,NULL,'0 -1 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',0.0,NULL,NULL,'1 0 0',NULL,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassFurnace',1.0,'Hearth',NULL,'1 1 0',NULL,NULL,'WaterTrough',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',1.0,'Furnace','','-1 -1 0','','','GlassFurnace','','','FL','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',1.0,'Table','','1 -1 0','','','WorkshopTable_GlassIngot','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',0.0,'','','0 1 0','','','WorkshopInputIndicator','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',0.0,'','','-1 0 0','','',NULL,'','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',1.0,'Chair','','0 0 0','','','Chair','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',0.0,'','','-1 1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',0.0,'','','0 -1 0','','','','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',0.0,'','1','1 0 0','','','WorkshopTable','','','','');\r\nINSERT INTO \"Workshops_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialItem\",\"Offset\",\"Required\",\"Forbidden\",\"SpriteID\",\"SpriteID2\",\"Type\",\"WallRotation\",\"IsFloor\") VALUES ('GlassMaker',0.0,'','1','1 1 0','','','WorkshopTable_Mosaic','','','','');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Crude','Plank|Stick|WoodChair|Workbench|Chisel',NULL,'1 1 0','1 -1 0','2 3',NULL,NULL,'Wood');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Carpenter','WoodChair|Workbench|Crate|Barrel|Chest|WoodTable|Stick|Haft|Hilt|Knife|PickaxeBaseWood|PickaxeHeadWood|Pickaxe|BedFrame|FancyBedFrame|Bed|FancyBed|WoodDoor|Dresser|Cabinet|Torch|Loom|Bellows|TrainingDummy|Wheelbarrow|Bucket|FishingRod|Shed|AlarmBellBase|BeeHive|Bookshelf',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Wood');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Sawmill','Plank',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Wood');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Stonecutter','Block',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Stone');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Stonemason','StoneChair|StoneTable|StoneSawblade|KnifeBlade|PickaxeHeadStone|Chisel',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Stone');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Kitchen','FlourKitchen|Bread|Sausage|Sandwich|Cheese|CheeseOmelette|SausageOmelette|MushroomOmelette|Vinegar|Sugar|DropCandy|ShepherdsPie|Biscuit|PickledFruit|PickledEgg|PickledVegetable|SmokedMeat|SmokedSausage|SmokedBird|SmokedFish|FreshCheese|HardCheese|FruitBread|FruitPie|VeggiePie|MeatPie|FineMeatPie',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Food');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Distillery','Beer|Wine|FruitWine|HoneyWine|Cider',NULL,'0 -1 0','1 0 0','3 3',NULL,NULL,'Food');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Dyer','RedDye|GreenDye|BlueDye|PurpleDye|YellowDye|CyanDye|DyedTable|DyedPlank|DyedBolt',NULL,'0 1 0','0 -1 0','3 3','true',NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Forge','Bar|BronzeBar|SteelBar|RoseGoldBar|Anvil|SliverBar',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Metal');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Furnace','RawCoal',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Wood');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Kiln','Brick|ClayStatuette',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Stone');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Blacksmith','PickaxeHeadMetal|FellingAxeHead|FellingAxe|CuttingWheel|File|BallPeenHammer|MetalNeedle|AlarmBell|AlarmBellBell|BigTorch|Brazier',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Metal');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Metalworker','MetalStatue|MetalStatuette|Coin',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Metal');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Gemcutter','Gem|PickaxeHeadFlintStone',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Loom','Bolt',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Stonecarver','StoneDoor|Hearth|Mold|Furnace|Trough|StoneStatue|StonePillar|StoneStatuette|PetRock',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Stone');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Woodcarver','WoodStatue|WoodStatuette|PuzzleBox',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Wood');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Jeweler','Ring|GemmedRing|Necklace|GemmedNecklace',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Tailor','Bag|Sack|Bandage|String|Padding|Mattress|AmmoPouch',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Bonecarver','Needle|BoneStatuette|SkullHelmet|BoneShirt|BoneTable|BoneChair|BoneBedFrame|BoneBed',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Butcher',NULL,'Butcher','0 1 0','0 -1 0','3 3',NULL,NULL,'Food');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('MarketStall',NULL,'Trader','-1 0 0','1 0 0','3 3',NULL,NULL,'Misc');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Prospector','SliverFromStone|SliverFromDirt',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Stone');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Fishery',NULL,'Fishery','0 -1 0','0 0 0','3 3',NULL,NULL,'Food');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Leatherworker','LeatherStrap|LeatherArmorPanel|LeatherHelm|LeatherCuirass|LeatherBracer|LeatherPants|LeatherGlove|LeatherBoot|Backpack',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Weaponsmith','SwordBlade|Sword|HandAxeHead|HandAxe|HammerHead|Hammer|ClaymoreBlade|Claymore|BattleAxeHead|BattleAxe|WarhammerHead|Warhammer',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Metal');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Armorer','ArmorPlate|ChainGloves|ChainBracers|ChainBoots|ChainPants|ChainHelm|ChainShirt|PlateGloves|PlatePauldrons|PlateBoots|PlateGreaves|PlateHelm|PlateChest|HeavyPlateGloves|HeavyPlatePauldrons|HeavyPlateBoots|HeavyPlateGreaves|HeavyPlateHelm|HeavyPlateChest',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Metal');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('MeleeTraining',NULL,'Training','-2 -2 0','0 0 0','5 5',NULL,NULL,'Misc');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Engineer','Axle|MechanismBase|Gearbox|Handcrank|TrapBase|SpikeTrap|Lever|MechanicalWall|WindmillBlade|PressurePlate|Hatch|SteamEngine',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Mechanics');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('MachineShop','Wrench|Rod|Gear|Spring|Spike|Screw|Cylinder',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Mechanics');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Automaton','Automaton|AutomatonHead|AutomatonTorso|AutomatonArm|AutomatonLeg|AutomatonCoreMark1|AutomatonCoreMark2','','0 1 0','0 -1 0','3 3',NULL,NULL,'Mechanics');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('Windmill','Flour',NULL,'1 0 0','1 3 0','4 4',NULL,'windmill.png','Food');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('WasteDisposal','BurnBone|BurnFishBone|BurnStraw|BurnSeeds',NULL,'0 1 0','0 -1 0','3 3','true',NULL,'Misc');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('GlassFurnace','GlassIngot|RoughGlassGem',NULL,'0 1 0','0 -1 0','3 3',NULL,NULL,'Craft');\r\nINSERT INTO \"Workshops\" (\"ID\",\"Crafts\",\"GUI\",\"InputTile\",\"OutputTile\",\"Size\",\"NoAutoGenerate\",\"Icon\",\"Tab\") VALUES ('GlassMaker','MosaicTile|GlassBottle|GlassJar','','0 1 0','0 -1 0','3 3','','','Craft');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('aced','acing','aced','aces','ace');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('acted','acting','acted','acts','act');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('adventured','adventuring','adventured','adventures','adventure');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('aged','aging','aged','ages','age');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('angered','angering','angered','angers','anger');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('armed','arming','armed','arms','arm');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('armored','armoring','armored','armors','armor');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('axed','axing','axed','axes','axe');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('babied','babying','babied','babies','baby');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('backed','backing','backed','backs','back');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('baked','baking','baked','bakes','bake');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('balded','balding','balded','balds','bald');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bared','baring','bared','bares','bare');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bastardized','bastardizing','bastardized','bastardizes','bastardize');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bathed','bathing','bathed','bathes','bathe');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('battled','battling','battled','battles','battle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('born','bearing','bore','bears','bear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('beguiled','beguiling','beguiled','beguils','beguil');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('beheaded','beheading','beheaded','beheads','behead');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('belched','belching','belched','belches','belch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bewitched','bewitching','bewitched','bewitches','bewitch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bitched','bitching','bitched','bitches','bitch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('blackened','blackening','blackened','blackens','blacken');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('blazed','blazing','blazed','blazes','blaze');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('blinded','blinding','blinded','blinds','blind');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('blistered','blistering','blistered','blisters','blister');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bloated','bloating','bloated','bloats','bloat');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bled','bleeding','bled','bleeds','bleed');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('blossomed','blossoming','blossomed','blossoms','blossom');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('boiled','boiling','boiled','boils','boil');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bolted','bolting','bolted','bolts','bolt');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('booted','booting','booted','boot','boot');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bothered','bothering','bothered','bothers','bother');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bowed','bowing','bowed','bows','bow');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('brained','braining','brained','brains','brain');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('breached','breaching','breached','breaches','breach');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('broken','breaking','broke','breaks','break');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('breathed','breathing','breathed','breathes','breathe');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bred','breeding','bred','breeds','breed');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('brewed','brewing','brewed','brews','brew');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bridled','bridling','bridled','bridles','bridle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('brightened','brightening','brighten','brightens','brighten');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bristled','bristling','bristled','bristles','bristle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('brimmed','brimming','brimmed','brims','brim');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('brought','bringing','brought','brings','bring');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('broiled','broiling','broiled','broils','broil');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bucked','bucking','bucked','bucks','buck');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('buckled','buckling','buckled','buckles','buckle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bunched','bunching','bunched','bunches','bunch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('burdened','burdening','burdened','burdens','burden');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('burned','burning','burned','burns','burn');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('buried','burying','buried','buries','bury');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('busheled','busheling','busheled','bushels','bushel');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('busted','busting','busted','busts','bust');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('busied','busying','busied','busies','busy');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('bustled','bustling','bustled','bustles','bustle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('butchered','butchering','butchered','butchers','butcher');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('buttered','buttering','buttered','butters','butter');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('buttoned','buttoning','buttoned','buttons','button');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cackled','cackling','cackled','cackles','cackle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('caged','caging','caged','cages','cage');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('called','calling','called','calls','call');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('camped','camping','camped','camps','camp');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('candied','candying','candied','candies','candy');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('castle','castling','castled','castles','castle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('caved','caving','caved','caves','cave');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cavorted','cavorting','cavorted','cavorts','cavort');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chained','chaining','chained','chains','chain');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chanted','chanting','chanted','chants','chant');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('charred','charring','charred','chars','char');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('charmed','charming','charmed','charms','charm');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chewed','chewing','chewed','chews','chew');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chilled','chilling','chilled','chills','chill');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chipped','chipping','chipped','chips','chip');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('choked','choking','choked','chokes','choke');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chopped','chopping','chopped','chops','chop');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('chucked','chucking','chucked','chucks','chuck');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cindered','cindering','cindered','cinder','cinder');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('clapped','clapping','clapped','claps','clap');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('clasped','clasping','clasped','clasps','clasp');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('clawed','clawing','clawed','claws','claw');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cleared','clearing','cleared','clears','clear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cleaved','cleaving','cleaved','cleaves','cleave');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('clinged','cleaving','clinged','clings','cling');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cloistered','cloistering','cloistered','cloisters','cloister');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('clubbed','clubbing','clubbed','clubs','club');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('clustered','clustering','clustered','clusters','cluster');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cluttered','cluttering','cluttered','clutters','clutter');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('coiled','coiling','coiled','coils','coil');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('colored','coloring','colored','colors','color');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cometed','cometing','cometed','comets','comet');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('conquered','conquering','conquered','conquers','conquer');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cooked','cooking','cooked','cooks','cook');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('covered','covering','covered','covers','cover');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('coupled','coupling','coupled','couples','couple');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crawled','crawling','crawled','crawls','crawl');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('creamed','creaming','creamed','creams','cream');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('creeked','creeking','creeked','creeks','creek');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('creet','creeping','crept','creeps','creep');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crossed','crossing','crossed','crosses','cross');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crowned','crowning','crowned','crowns','crown');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crucified','crucifying','crucified','crucifies','crucify');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crumbled','crumbling','crumbled','crumbles','crumble');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crunched','crunching','crunched','crunches','crunch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('crushed','crushing','crushed','crushes','crush');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cried','crying','cried','cries','cry');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cuddled','cuddling','cuddled','cuddles','cuddle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cursed','cursing','cursed','curses','curse');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('cut','cutting','cut','cuts','cut');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('danced','dancing','danced','dances','dance');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dangled','dangling','dangled','dangle','dangle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dated','dating','dated','dates','date');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('damaged','damaging','damaged','damages','damage');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('damned','damning','damned','damns','damn');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dawned','dawning','dawned','dawns','dawn');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('died','dying','died','dies','die');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('decapitated','decapitating','decapitated','decapitates','decapitate');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('decayed','decaying','decayed','decays','decay');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('deceived','deceiving','deceived','deceives','deceive');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('desecrated','desecrating','desecrated','desecrates','desecrate');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('deserted','deserting','deserted','deserts','desert');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('despaired','despairing','despaired','despairing','despair');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('destroyed','destroying','destroyed','destroys','destroy');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('devilled','devilling','devilled','bedevils','devil');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('devoured','devouring','devoured','devours','devour');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dined','dining','dined','dines','dine');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dirtied','dirtying','dirtied','dirty','dirty');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('disguised','disguising','disguised','disguises','disguise');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ditched','ditching','ditched','ditches','ditch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('doomed','dooming','doomed','dooms','doom');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('drained','draining','drained','drains','drain');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dreamed','dreaming','dreamed','dream','dream');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dressed','dressing','dressed','dresses','dress');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('drunk','drinking','drank','drinks','drink');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dripped','dripping','dripped','drips','drip');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('drooled','drooling','drooled','drools','drool');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('drowned','drowning','drowned','drowns','drown');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dried','drying','dried','dries','dry');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dumped','dumping','dumped','dump','dump');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('dyed','dying','dyed','dyes','dye');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('eaten','eating','ate','eats','eat');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('engraved','engraving','engraved','engraves','engrave');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('entranced','entrancing','entranced','entrances','entrance');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('entrenched','entrenching','entrenched','entrenches','entrench');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('entwined','entwining','entwined','entwines','entwine');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('executed','executing','executed','executes','execute');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('faced','facing','faced','faces','face');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fallen','falling','fell','falls','fall');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fattened','fattening','fattened','fattens','fatten');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fathered','fathering','fathered','fathers','father');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('feared','fearing','feared','fears','fear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('feasted','feasting','feasted','feasts','feast');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('found','finding','found','finds','find');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fired','firing','fired','fire','fire');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fished','fishing','fished','fishes','fish');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('flamed','flaming','flamed','flames','flame');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('flanked','flanking','flanked','flanks','flank');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fled','fleeing','fled','flees','flee');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('flung','flinging','flung','flings','fling');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('flooded','flooding','flooded','floods','flood');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('flowered','flowering','flowered','flowers','flower');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fluted','fluting','fluted','flutes','flute');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('flew','flying','flew','flies','fly');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('focused','focusing','focused','focuses','focus');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fogged','fogging','fogged','fogs','fog');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fooled','fooling','fooled','fools','fool');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('forked','forking','forked','forks','fork');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fortified','fortifying','fortified','fortifies','fortify');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('founded','founding','founded','founds','found');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('fragmented','fragmenting','fragmented','fragments','fragment');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('framed','framing','framed','frames','frame');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('frayed','fraying','frayed','frays','fray');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('freed','freeing','freed','frees','free');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('frenzied','frenzying','frenzied','frenzies','frenzy');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('frozen','freezing','froze','freezes','freeze');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gamed','gaming','gamed','games','game');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('garnished','garnishing','garnished','garnishes','garnish');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gazed','gazing','gazed','gazes','gaze');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('geared','gearing','geared','gears','gear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gifted','gifting','gifted','gifts','gift');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('glazed','glazing','glazed','glazes','glaze');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('glided','gliding','glided','glides','glide');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('glimmered','glimmering','glimmered','glimmers','glimmer');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('glistened','glistening','glistened','glistens','glisten');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('glossed','glossing','glossed','glosses','gloss');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gored','goring','gored','gores','gore');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gorged','gorging','gorged','gorges','gorge');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('greased','greasing','greased','greases','grease');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('greeded','greeding','greeded','greeds','greed');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('grilled','grilling','grilled','grills','grill');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ground','grinding','ground','grinds','grind');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gripped','gripping','gripped','grips','grip');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gripped','gripping','gripped','grips','grip');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('grizzled','grizzling','grizzled','grizzles','grizzle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('grown','growing','grew','grows','grow');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('growled','growling','growled','growls','growl');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('grubbed','grubbing','grubbed','grubs','grub');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('guarded','guarding','guarded','grguardsubs','guard');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('gutted','gutting','gutted','guts','gut');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('haggled','haggling','haggled','haggles','haggle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hammered','hammering','hammered','hammers','hammer');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('handed','handing','handed','hands','hand');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('harvested','harvesting','harvested','harvests','harvest');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hatcheted','hatcheting','hatcheted','hatchets','hatchet');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hated','hating','hated','hates','hate');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('haunted','haunting','haunted','haunts','haunt');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hawked','hawking','hawked','hawks','hawk');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('headed','heading','headed','heads','head');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hexed','hexing','hexed','hexes','hex');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hidden','hiding','hid','hides','hide');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hobbled','hobbling','hobbled','hobbles','hobble');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hogged','hoggin','hogged','hogs','hog');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hoisted','hoisting','hoisted','hoists','hoist');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('holed','holing','holed','holes','hole');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('homed','homing','homed','homes','home');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('honeyed','honeying','honeyed','honeys','honey');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hopped','hopping','hopped','hops','hop');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hounded','hounding','hounded','hounds','hound');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('howled','howling','howled','howls','howl');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hugged','huggin','hugged','hugs','hug');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hummed','humming','hummed','hums','hum');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hungered','hungering','hungered','hungers','hunger');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('hustled','hustleing','hustled','hustles','hustle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('iced','icing','iced','ices','ice');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('idled','idling','idled','idles','idle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('idoled','idoling','idoled','idols','idol');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('idolized','idolizing','idolized','idolizes','idolize');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('imprisoned','imprisoning','imprisoned','imprisons','imprison');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('impured','impuring','impured','impures','impure');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('incensed','incensing','incensed','incenses','incense');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('incested','incesting','incested','incests','incest');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('inched','inching','inched','inches','inch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('inked','inking','inked','inks','ink');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ironed','ironing','ironed','irons','iron');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('itched','itching','itched','itches','itch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('jested','jesting','jested','jests','jest');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('joked','joking','joked','jokes','joke');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('judged','judging','judged','judges','judge');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('juggled','juggling','juggled','juggles','juggle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('juiced','juicing','juiced','juices','juice');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('jumped','jumping','jumped','jumps','jump');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('justified','justifying','justified','justifies','justify');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('kept','keeping','kept','keeps','keep');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('kicked','kicking','kicked','kicks','kick');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('killed','killing','killed','kills','kill');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('kissed','kissing','kissed','kisses','kiss');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('knead','kneading','kneaded','kneads','knead');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('knifed','knifing','knifed','knifes','knife');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('knighted','knighting','knighted','knights','knight');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('knitted','knitting','knit','knits','knit');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('knotted','knotting','knotted','knots','knot');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('laced','lacing','laced','laces','lace');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lasted','lasting','lasted','lasts','last');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('led','leading','led','leads','lead');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('leaked','leaking','leaked','leaks','leak');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('leeched','leeching','leeched','leeches','leech');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lied','lieing','lied','lies','lie');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lit','lighting','lit','lights','light');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lived','living','lived','lives','live');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('listened','listening','listened','listens','listen');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('loaned','loaning','loaned','loans','loan');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('locked','locking','locked','locks','lock');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('looted','looting','looted','loots','loot');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lost','losing','lost','loses','lose');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('loved','loving','loved','loves','love');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lowered','lowering','lowered','lowers','lower');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lurched','lurching','lurched','lurches','lurch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('lurked','lurking','lurked','lurks','lurk');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('mangled','mangling','mangled','mangles','mangle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('martyred','martyring','martyred','martyrs','martyr');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('mastered','mastering','mastered','masters','master');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('meditated','meditating','meditated','meditates','meditate');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('menaced','menacing','menaced','menaces','menace');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('messed','messing','messed','messes','mess');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('minced','mincing','minced','minces','mince');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('minded','minding','minded','minds','mind');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('mined','mining','mined','mines','mine');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('mirrored','mirroring','mirrored','mirrors','mirror');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('misted','misting','misted','mists','mist');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('molded','molding','molded','molds','mold');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('murdered','murdering','murdered','murders','murder');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('mushed','mushing','mushed','mushes','mush');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('negated','negating','negated','negates','negate');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('nested','nesting','nested','nests','nest');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('nestled','nestling','nestled','nestles','nestle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('netted','netting','netted','nets','net');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('nibbled','nibbling','nibbled','nibbles','nibble');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('nurtured','nurturing','nurtured','nurtures','nurture');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('opened','opening','opened','opens','open');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('packed','packing','packed','packs','pack');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('padded','pading','padded','pads','pad');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('painted','painting','painted','paints','paint');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('pandered','pandering','pandered','panders','pander');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('panted','panting','panted','pant','pant');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('planted','planting','planted','plants','plant');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('plotted','plotting','plotted','plots','plot');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('pocketed','pocketing','pocketed','pockets','pocket');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('poisoned','poisoning','poisoned','poisons','poison');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('powered','powering','powered','powers','power');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('pranked','pranking','pranked','pranks','prank');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('primed','priming','primed','primes','prime');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('profited','profiting','profited','profits','profit');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('prowled','prowling','prowled','prowls','prowl');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('puked','puking','puked','pukes','puke');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('pulled','pulling','pulled','pulls','pull');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('punched','punching','punched','punches','punch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('pushed','pushing','pushed','pushes','push');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('quacked','quacking','quacked','quacks','quack');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('quaked','quaking','quaked','quakes','quake');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('quickened','quickening','quickened','quickens','quick');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('raced','racing','raced','races','race');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('rained','raining','rained','rains','rain');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('raked','raking','raked','rakes','rake');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('rammed','ramming','rammed','rams','ram');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('rampaged','rampaging','rampaged','rampages','rampage');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ransacked','ransacking','ransacked','ransacks','ransack');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ravaged','ravaging','ravaged','ravages','ravage');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('reigned','reigning','reigned','reigns','reign');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('reined','reining','reined','reins','rein');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('rung','ringing','rang','rings','ring');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ripped','ripping','ripped','rips','rip');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('risen','rising','rose','rises','rise');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('romanced','romancing','romanced','romances','romance');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ruined','ruining','ruined','ruins','ruin');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ruled','ruling','ruled','rules','rule');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sawn','sawing','sawed','saws','saw');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('scalded','scalding','scalded','scalds','scald');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('scarred','scarring','scarred','scars','scar');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('scolded','scolding','scolded','scolds','scold');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('screamed','screaming','screamed','screams','scream');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('seduced','seducing','seduced','seduces','seduce');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('seen','seeing','saw','sees','see');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('seized','seizing','seized','seizes','seize');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('served','serving','served','serves','serve');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('severed','severing','severed','severs','sever');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sheared','shearing','sheared','shears','shear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sheltered','sheltering','sheltered','shelters','shelter');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shielded','shielding','shielded','shields','shield');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shimmered','shimmering','shimmered','shimmers','shimmer');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shot','shooting','shot','shoots','shoot');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shown','showing','showed','shows','show');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('showered','showering','showered','showers','shower');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shredded','shredding','shredded','shreds','shred');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shrieked','shrieking','shrieked','shrieks','shriek');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('shut','shutting','shut','shuts','shut');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sickened','sickening','sickened','sickens','sicken');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sieged','sieging','sieged','sieges','siege');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('silenced','silencing','silenced','silences','silence');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sung','singing','sang','sings','sing');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('skirted','skirting','skirted','skirts','skirt');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('skulked','skulking','skulked','skulks','skulk');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('slaughtered','slaughtering','slaughtered','slaughters','slaughter');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('enslaved','enslaving','enslaved','enslaves','enslave');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('slain','slaying','slew','slays','slay');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('slimmed','slimming','slimmed','slims','slim');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('slunk','slinking','slunk','slinks','slink');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('slit','sliting','slit','slits','slit');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('slithered','slithering','slithered','slithers','slither');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('smashed','smashing','smashed','smashes','smash');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('smiled','smiling','smiled','smiles','smile');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('smoked','smoking','smoked','smokes','smoke');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('smoothed','smoothing','smoothed','smooths','smooth');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('smouldered','smouldering','smouldered','smoulders','smoulder');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('snacked','snacking','snacked','snacks','snack');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('snickered','snickering','snickered','snickers','snicker');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('snuggled','snuggling','snuggled','snuggles','snuggle');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('soothed','soothing','soothed','soothes','soothe');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sounded','sounding','sounded','sounds','sound');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('spewed','spewing','spewed','spews','spew');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('spun','spinning','spun','spins','spin');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('spoiled','spoiling','spoiled','spoils','spoil');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('spooned','spooning','spooned','spoons','spoon');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sprung','springing','sprang','springs','spring');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('spied','spying','spied','spies','spy');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('squirmed','squirming','squirmed','squirms','squirm');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stabbed','stabbing','stabbed','stabs','stab');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stalked','stalking','stalked','stalks','stalk');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stood','standing','stood','stands','stand');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('starved','starving','starved','starves','starve');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stolen','stealing','stole','steals','steal');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stuck','sticking','stuck','sticks','stick');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stoned','stoning','stoned','stones','stone');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stormed','storming','stormed','storms','storm');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('strapped','strapping','strapped','straps','strap');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('strayed','straying','strayed','strays','stray');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('strengthened','strengthening','strengthened','strengthens','strengthen');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stretched','stretching','stretched','stretches','stretch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stricken','striking','struck','strikes','strike');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stroked','stroking','stroked','strokes','stroke');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('stuttered','stuttering','stuttered','stutters','stutter');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('styled','styling','styled','styles','style');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sucked','sucking','sucked','sucks','suck');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('suffered','suffering','suffered','suffers','suffer');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sundered','sundering','sundered','sunders','sunder');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('surprised','surprising','surprised','surprises','surprise');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('swamped','swamping','swamped','swamps','swamp');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('sweat','sweating','sweat','sweats','sweat');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('swam','swimming','swam','swims','swim');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('taken','taking','took','takes','take');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tarnished','tarnishing','tarnished','tarnishes','tarnish');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('told','telling','told','tells','tell');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('torn','tearing','torn','tears','tear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('terrified','terrifying','terrified','terrifies','terrify');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('terrorized','terrorizing','terrorized','terrorizes','terrorize');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('thrown','throwing','threw','throws','throw');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('thundered','thundering','thundered','thunders','thunder');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('ticked','ticking','ticked','ticks','tick');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tightened','tightenening','tightened','tightens','tighten');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('timed','timing','timed','times','time');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tormented','tormenting','tormented','torments','torment');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('touched','touching','touched','touches','touch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('towered','towering','towered','towers','tower');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('trailed','trailing','trailed','trails','trail');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('trapped','trapping','trapped','traps','trap');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('treasured','treasuring','treasured','treasures','treasure');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('treated','treating','treated','treats','treat');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tricked','tricking','tricked','tricks','trick');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('trimmed','trimming','trimmed','trims','trim');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('troubled','troubling','troubled','troubles','trouble');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tugged','tugging','tugged','tugs','tug');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tumbled','tumbling','tumbled','tumbles','tumble');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('tweeted','tweeting','tweeted','tweets','tweet');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('twisted','twisting','twisted','twists','twist');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('vandalized','vandalizing','vandalized','vandalizes','vandalize');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('violated','violating','violated','violates','violate');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('voiced','voicing','voiced','voices','voice');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('voided','voiding','voided','voids','void');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('wailed','wailing','wailed','wails','wail');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('wandered','wandering','wandered','wanders','wander');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('wasted','wasting','wasted','wastes','waste');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('watched','watching','watched','watches','watch');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('waved','waving','waved','waves','wave');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('worn','wearing','wore','wears','wear');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('weaved','weaving','weaved','weaves','weave');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('weeded','weeding','weeded','weeds','weed');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('weighed','weighing','weighed','weighs','weigh');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('wheeled','wheeling','wheeled','wheels','wheel');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('whipped','whipping','whipped','whips','whip');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('whisked','whisking','whisked','whisks','whisk');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('whispered','whispering','whispered','whispers','whisper');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('willed','willing','willed','wills','will');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('wondered','wondering','wondered','wonders','wonder');\r\nINSERT INTO \"Words_Verb\" (\"PastParticiple\",\"PresentParticiple\",\"SimplePast\",\"SimplePresent\",\"Word\") VALUES ('worked','working','worked','works','work');\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('zero',0);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('one',1);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('two',2);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('three',3);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('four',4);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('five',5);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('six',6);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('seven',7);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('eight',8);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('nine',9);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('ten',10);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('eleven',11);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('dwelve',12);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('thirteen',13);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('fourteen',14);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('fifteen',15);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('sixteen',16);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('seventeen',17);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('eighteen',18);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('nineteen',19);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('twenty',20);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('thirty',30);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('fourty',40);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('fifty',50);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('sixty',60);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('seventy',70);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('eighty',80);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('ninety',90);\r\nINSERT INTO \"Words_Numbers\" (\"Word\",\"Number\") VALUES ('one hundred',100);\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('aces','ace');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('acts','act');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('adventures','adventure');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ages','age');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ales','ale');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('apples','apple');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ancients','ancient');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('angels','angel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('angers','anger');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('animals','animal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('arms','arm');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('armors','armor');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('arrows','arrow');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('artifacts','artifact');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ashes','ash');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('auras','aura');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('axes','axe');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('babies','baby');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('backs','back');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bakers','baker');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('baldnesses','baldness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('balls','ball');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('banes','bane');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bars','bar');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('barbs','barb');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bastards','bastard');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('baths','bath');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('battles','battle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beaks','beak');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beasts','beast');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bears','bear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beds','bed');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bee','bee');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beers','beer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beetles','beetle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beguilers','beguiler');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('beheadings','beheading');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('belches','belch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('berries','berry');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('biles','bile');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bins','bin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('birds','bird');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bitches','bitch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blacknessess','blackness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blades','blade');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blazes','blaze');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blindnesses','blindness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blisters','blister');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bloats','bloat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blood','blood');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bloodinesses','bloodiness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('blossoms','blossom');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('boars','boar');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('boats','boat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bodices','bodice');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bogs','bog');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('boils','boil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('boldnesses','boldness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bolts','bolt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bones','bone');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('books','book');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('boots','boot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bows','bow');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brains','brain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breaches','breach');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breeches','breeches');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breads','bread');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breaks','break');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breakfasts','breakfast');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breaths','breath');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('breeds','breed');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brews','brew');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brides','bride');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bridles','bridle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brightnesses','brightness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bristles','bristle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brilliances','brilliance');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brims','brim');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brothers','brother');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('brunches','brunch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bucks','buck');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('buckles','buckle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('buds','bud');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bunches','bunch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('burdens','burden');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('burns','burn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('burials','burial');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bushes','bush');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('bushels','bushel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('busts','bust');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('businesses','business');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('busynesses','busyness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('butters','butter');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('butterflies','butterfly');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('buttons','button');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('buzzards','buzzard');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cackles','cackle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cages','cage');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cakes','cake');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('calls','call');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('camps','camp');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cancers','cancer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('candles','candle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('candies','candy');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('canyons','canyon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('carnages','carnage');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('caskets','casket');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('castles','castle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cats','cat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('caves','cave');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cells','cell');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cellars','cellar');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chains','chain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chants','chant');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chaoses','chaos');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chambers','chamber');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('children','child');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chills','chill');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chips','chip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('chokers','choker');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cinders','cinder');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clams','clam');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clasps','clasp');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('claws','claw');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clears','clear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clearings','clearing');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clefts','cleft');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cloaks','cloak');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clods','clod');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cloisters','cloister');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('closets','closet');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clubs','club');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clusters','cluster');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('clutter','clutter');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cobras','cobra');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('coils','coil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('coldnesses','coldness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('colors','color');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('comets','comet');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cooks','cook');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('covers','cover');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cottons','cotton');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('couples','couple');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crabs','crab');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('jumps','jump');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crazes','craze');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crazinesses','craziness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('creams','cream');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('creeks','creek');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('creeps','creep');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('creepinesses','creepiness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crescents','crescent');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crosses','cross');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crows','crow');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crowns','crown');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crotches','crotch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crucifixions','crucifixion');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crypts','crypt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('crystals','crystal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cudgels','cudgel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cups','cup');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('curses','curse');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cuts','cut');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('cysts','cyst');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dances','dance');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('danknesses','dankness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('daggers','dagger');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('darknesses','darkness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dates','date');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('damages','damage');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dawns','dawn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('days','day');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dead','dead');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('deaths','death');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('decays','decay');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('depths','deep');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('deer','deer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('demons','demon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('desecration','desecration');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('deserts','desert');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('desertednesses','desertedness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('desserts','dessert');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('despairs','despair');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('destructions','destruction');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('devils','devil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('diamonds','diamond');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dinners','dinner');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dirts','dirt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('disguises','disguise');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ditches','ditch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dogs','dog');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('domains','domain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('domesciles','domescile');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('donkeys','donkey');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dooms','doom');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('doors','door');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dragons','dragon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('drains','drain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dreams','dream');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dresses','dress');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('drinks','drink');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('drips','drip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('drools','drool');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dumps','dump');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dumplings','dumpling');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dungs','dung');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dungeons','dungeon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dusks','dusk');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dusts','dust');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('duties','duty');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('dyes','dye');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('eagles','eagle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ears','ear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('earths','earth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('eels','eel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('eerienesses','eerieness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('eggs','egg');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('elders','elder');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('entrances','entrance');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('entrails','entrails');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('entwinements','entwinement');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('evils','evil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('executions','execution');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('eyes','eye');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('faces','face');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('falls','fall');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('falsehoods','falsehood');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('famines','famine');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fangs','fang');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fats','fat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fatalities','fatality');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fathers','father');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fear','fear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('feasts','feast');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fiends','fiend');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fiercenesses','fierceness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('filths','filth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fins','fin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fingers','finger');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fires','fire');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fish','fish');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fists','fist');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('flames','flame');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('flanks','flank');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fleas','flea');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fleshes','flesh');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('floods','flood');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('flowers','flower');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('flutes','flute');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('flies','fly');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('focuses','focus');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fogs','fog');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fools','fool');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('feet','foot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('forests','forest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fork','fork');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fortifications','fortification');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fortresses','fortress');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('foundations','foundation');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fragments','fragment');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('frames','frame');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('freedoms','freedom');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('frenzies','frenzy');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('frills','frill');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('frogs','frog');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fruits','fruit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('fungi','fungus');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('furs','fur');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('games','game');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('garlics','garlic');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('garnishes','garnish');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gazes','gaze');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gears','gear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gerbils','gerbil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ghosts','ghost');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ghouls','ghoul');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gifts','gift');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gills','gill');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('glands','gland');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('glazes','glaze');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('glimmers','glimmer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('glosses','gloss');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gloves','glove');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gluttons','glutton');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('goats','goat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gods','god');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gold','gold');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('geese','goose');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gore','gore');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gorges','gorge');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grains','grain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grandeurs','grandeur');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grapes','grape');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grasses','grass');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('graves','grave');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('greases','grease');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('greatnesses','greatness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('greed','greed');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('griffons','griffon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grips','grip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('gristles','gristle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grizzles','grizzle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('groves','grove');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('growths','growth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('growls','growl');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('grubs','grub');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('guards','guard');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('guiles','guile');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('guises','guise');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('guts','gut');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hags','hag');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hairs','hair');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hammers','hammer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hands','hand');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hares','hare');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('harvests','harvest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hatchets','hatchet');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hates','hate');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('haunts','haunt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hawks','hawk');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hays','hay');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('heads','head');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hearts','heart');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('heartlessnesses','heartlessness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('heartfulnesses','heartfulness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hearths','hearth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hedges','hedge');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hells','hell');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('helms','helm');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('heroes','hero');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hexes','hex');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hides','hide');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hideousnesses','hideousness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('highnesses','highness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hills','hill');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hips','hip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hogs','hog');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('holes','hole');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('holinesses','holiness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('homes','home');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('honeys','honey');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hoods','hood');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hooves','hoof');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hops','hop');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('horns','horn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('horses','horse');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hounds','hound');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('howls','howl');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hugs','hug');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hungers','hunger');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('hungrinesses','hungriness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ices','ice');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('idlenessess','idleness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('idols','idol');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('idoltries','idoltry');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('illnesses','illness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('impurities','impurity');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('incenses','incense');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('incests','incest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('inches','inch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('inks','ink');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('inklings','inkling');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('inns','inn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('insanities','insanity');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('invisibilities','invisibility');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('irons','iron');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ironies','irony');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('itches','itch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ivory','ivory');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ivy','ivy');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('jackals','jackal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('jaws','jaw');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('jests','jest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('jokes','joke');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('judges','judge');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('juices','juice');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('jungles','jungle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('justices','justice');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('keeps','keep');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kegs','keg');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('keys','key');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kicks','kick');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kills','kill');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kindnesses','kindness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kisses','kiss');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kings','king');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('kingdoms','kingdom');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('knives','knife');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('knights','knight');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('knots','knot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('laces','lace');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lakes','lake');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lards','lard');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('larvae','larva');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('laws','law');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lazinesses','laziness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lead','lead');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('leaves','leaf');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('leak','leak');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('leeches','leech');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('legends','legend');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lenses','lens');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('leopards','leopard');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('leper','leper');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('leprosies','leprosy');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('letters','letter');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lies','lie');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lights','light');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lightnings','lightning');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lives','life');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('limbs','limb');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lips','lip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('livers','liver');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lizards','lizard');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('loans','loan');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lobsters','lobster');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('locks','lock');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lengths','length');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('loots','loot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lords','lord');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lice','louse');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('loves','love');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lownesses','lowness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lunches','lunch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lungs','lung');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lushnesses','lushness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lusts','lust');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lutes','lute');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('lyrics','lyric');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('maggots','maggot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('magics','magic');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('men','man');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('marshes','marsh');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('martyrs','martyr');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('masters','master');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('meads','mead');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('meadows','meadow');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('meals','meal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('meats','meat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('meditations','meditation');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('menaces','menace');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('messes','mess');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('metals','metal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('midnights','midnight');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mights','might');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('miles','mile');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('minds','mind');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mine','mine');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('minions','minion');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mirror','mirror');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('miseries','misery');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mists','mist');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('molds','mold');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('moles','mole');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('monkeys','monkey');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('moons','moon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('moths','moth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mothers','mother');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mice','mouse');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mouths','mouth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('muds','mud');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('muffins','muffin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mules','mule');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('murders','murder');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mushes','mush');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mushrooms','mushroom');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('musics','music');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('mysteries','mystery');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('myths','myth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nails','nail');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('natures','nature');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nests','nest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nets','net');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('newts','newt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nights','night');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nightmares','nightmare');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nobles','noble');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('noses','nose');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('numbers','number');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('nuts','nut');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oaks','oak');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oars','oar');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oats','oat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oblivions','oblivion');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oceans','ocean');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('omens','omen');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ones','one');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('onions','onion');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oozes','ooze');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('orbs','orb');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('owls','owl');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('oxen','ox');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('packs','pack');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pads','pad');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pages','page');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pains','pain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('paints','paint');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('palenesses','paleness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('palms','palm');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('panthers','panther');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pants','pants');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('papers','paper');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('peaces','peace');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('peaches','peach');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('peppers','pepper');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pigs','pig');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pisses','piss');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pits','pit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pitches','pitch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('plagues','plague');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('plants','plant');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('plots','plot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pockets','pocket');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('poisons','poison');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('portals','portal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('powers','power');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pranks','prank');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('prides','pride');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('priests','priest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('prime','prime');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('prisons','prison');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('profanities','profanity');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('profits','profit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('prophecies','prophecy');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pukes','puke');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pulls','pull');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pulleys','pulley');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pulps','pulp');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pusses','pus');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('pushes','push');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('putrescences','putrescence');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('quacks','quack');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('quakes','quake');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('quarks','quark');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('queens','queen');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('quicknesses','quickness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('quills','quill');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rabbits','rabbit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rabbles','rabble');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('races','race');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('racks','rack');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rags','rag');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rages','rage');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rains','rain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rakes','rake');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rams','ram');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rampages','rampage');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rats','rat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('raven','raven');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rawnesses','rawness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('razors','razor');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rednesses','redness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('reigns','reign');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('reins','rein');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('riders','rider');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rims','rim');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rings','ring');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rips','rip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ripenesses','ripeness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rites','rite');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rivers','river');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rocks','rock');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rogues','rogue');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('romances','romance');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rooms','room');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('roots','root');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('roses','rose');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rots','rot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('roughnesses','roughness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('royalties','royalty');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ruins','ruin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rumors','rumor');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('rusts','rust');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sabres','sabre');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sacks','sack');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('saints','saint');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('salts','salt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('salves','salve');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('saps','sap');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('satins','satin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('savages','savage');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('savageries','savagery');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('saviors','savior');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('saws','saw');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('scabs','scab');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('scalds','scald');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('scars','scar');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('scorpions','scorpion');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('scourges','scourge');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('screams','scream');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('scums','scum');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seas','sea');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seals','seal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seams','seam');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seasons','season');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('secrets','secret');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seductions','seduction');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seeds','seed');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('seizures','seizure');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('serpents','serpent');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('servants','servant');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sewers','sewer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shadows','shadow');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shafts','shaft');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shanks','shank');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sharks','shark');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sheens','sheen');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shells','shell');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shelters','shelter');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shields','shield');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shimmers','shimmer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ships','ship');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shows','show');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('showers','shower');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shreds','shred');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('shrieks','shriek');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sick','sick');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sicknessess','sickness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sieges','siege');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('silences','silence');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('silks','silk');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('silkinesses','silkiness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('silt','silt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('silvers','silver');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sins','sin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sinews','sinew');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('songs','song');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sisters','sister');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('skirts','skirt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('skulls','skull');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('skulks','skulk');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('skunks','skunk');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('skies','sky');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slaughters','slaughter');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slaves','slave');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slain','slain');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slimes','slime');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slits','slit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slivers','sliver');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sloths','sloth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('slugs','slug');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('smashes','smash');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('smiles','smile');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('smiths','smith');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('smokes','smoke');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('smoothnesses','smoothness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('snacks','snack');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('snakes','snake');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sneers','sneer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('snots','snot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('soils','soil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('soldiers','soldier');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('soots','soot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sorrow','sorrow');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('souls','soul');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sound','sound');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spasms','spasm');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spawns','spawn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spears','spear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spells','spell');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spews','spew');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spices','spice');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spiders','spider');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spikes','spike');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spines','spine');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spirits','spirit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spits','spit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spoils','spoil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spoons','spoon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('springs','spring');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('spies','spy');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('squids','squid');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('staves','staff');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stands','stand');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stars','star');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('steeds','steed');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('starvations','starvation');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('steels','steel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stenches','stench');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sticks','stick');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stone','stone');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('storms','storm');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('strangenesses','strangeness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('strangers','stranger');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('straps','strap');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('straws','straw');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('strays','stray');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('strengths','strength');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stretches','stretch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('strikes','strike');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('strokes','stroke');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stunts','stunt');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('stupidities','stupidity');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('styles','style');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('subordinate','subordinate');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sufferings','suffering');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('summers','summer');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('suppers','supper');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('surprises','surprise');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('swamps','swamp');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sweats','sweat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sweets','sweet');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('sweetnesses','sweetness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('swiftnesses','swiftness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('swines','swine');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('swords','sword');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('syrups','syrup');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tails','tail');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('talons','talon');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tars','tar');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tarnish','tarnish');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tempests','tempest');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tears','tear');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('terrors','terror');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('thieves','thief');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('thirsts','thirst');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('thorns','thorn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('thralls','thrall');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('throats','throat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('thrones','throne');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('thunders','thunder');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('ticks','tick');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tightnesses','tightness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('time','time');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('toads','toad');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('toes','toe');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tombs','tomb');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tomes','tome');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tongues','tongue');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('teeth','tooth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('torments','torment');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('touches','touch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tours','tour');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('towers','tower');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('trails','trail');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('trances','trance');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('traps','trap');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('trashes','trash');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('treasures','treasure');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('treats','treat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('treaties','treaty');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('trenches','trench');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tribes','tribe');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tricks','trick');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('trickeries','trickery');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('trims','trim');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('troubles','trouble');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tulips','tulip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tumors','tumor');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('turmoils','turmoil');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('tusks','tusk');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('twilights','twilight');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('twines','twine');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('twists','twist');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('uglinesses','ugliness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('uncles','uncle');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('urns','urn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vandal','vandal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vegetables','vegetable');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vegetations','vegetation');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('velvets','velvet');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('venoms','venom');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vermins','vermin');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vilenesses','vileness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('violences','violence');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vipers','viper');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('voices','voice');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('voids','void');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('volcanoes','volcano');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vomits','vomit');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('vultures','vulture');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wails','wail');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wars','war');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('warriors','warrior');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wasps','wasp');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wastes','waste');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('watches','watch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('watchfulnesses','watchfulness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('waves','wave');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('weasels','weasel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('weaves','weave');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('weeds','weed');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('weights','weight');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wheats','wheat');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wheels','wheel');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('whips','whip');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('whiskers','whisker');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('whiskies','whisky');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('whispers','whisper');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wickednesses','wickedness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wildnesses','wildness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wildernesses','wilderness');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wills','will');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wings','wing');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('winters','winter');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wisps','wisp');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('witches','witch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wonders','wonder');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('woods','wood');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('works','work');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('worms','worm');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wraiths','wraith');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wraths','wrath');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('wretches','wretch');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('yarns','yarn');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('years','year');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('youths','youth');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('zeals','zeal');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('zealots','zealot');\r\nINSERT INTO \"Words_Noun\" (\"Plural\",\"Word\") VALUES ('zephyrs','zephyr');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ace');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('aging');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ageless');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('alive');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ancient');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('angelic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('angery');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('animalistic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('armored');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('artificial');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ashen');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bad');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bald');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('barbed');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('beastly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('beguiling');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('big');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bitchy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('black');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('blazing');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('blind');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('blistering');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bloated');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bleeding');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bloody');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('blossoming');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('blue');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('boiling');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bold');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bolted');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('boned');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bothering');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('broken');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bridled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bright');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bristled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('brilliant');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('broiled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('buckled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('bunched');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('burdened');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('burned');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('buried');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('busheled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('busted');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('busy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('butchered');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('buttered');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('buttoned');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('caged');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('caked');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cancerous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('candlelit');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('candied');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('celled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('chained');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('chaotic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('chambered');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('charred');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('charmed');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('childlike');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('chilled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('chipped');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cinderous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('clammy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('clasped');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('clawlike');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cleared');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('clingy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cloaked');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cluttered');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cobralike');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('coiled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cold');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('common');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('conquered');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cooked');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('covered');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('coupled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('crazed');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('crazy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('creamy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('creepy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('crescent-shaped');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('cross');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('crotchety');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('crystalline');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dank');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dark');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dead');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dear');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('deep');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('demonic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('desert');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('diamond');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dirty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('domestic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('doomed');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dreamy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dusty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dutifull');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('dyed');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('earthen');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('east');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('eerie');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('elder');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('eternal');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('everlasting');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('evil');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('false');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fat');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fatal');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fetid');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fiendish');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fierce');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('filthy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('finned');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fiery');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('first');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fishy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('flaming');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fleshy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('flowery');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('foggy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('foolish');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fragile');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('free');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('frilly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('froggy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('fruity');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('furry');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gaunt');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ghostly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ghoulish');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gifted');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gilled');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gloved');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gluttonous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('godly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('god-forsaken');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gold');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gory');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('grand');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('grave');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('greasy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('great');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('greedy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('green');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('grim');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('gristly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('grizzly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('grubby');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('guileful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hairy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('handy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hateful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('headless');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hearty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('heartless');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('heartful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hellish');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('helmed');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('heroic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hideous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('high');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hilly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hip');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hobbly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hoggy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('holey');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('holy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('homey');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hooded');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hooved');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hoppy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('horned');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('horny');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('hungry');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('icy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('idle');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ill');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('impure');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('inky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('insane');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('invisible');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('irony');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ivory');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('jumpy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('just');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('kicking');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('kind');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('kingly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('knit');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lacy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('larval');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('last');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lazy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('leafy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('leaky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lean');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('legendary');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('leperous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('light');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lone');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('long');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lordly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lovely');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('low');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lush');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lustful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('lyrical');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('magical');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('manly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mangy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mellow');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mighty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('miserable');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('misty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('moldy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('molten');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mousy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('muddy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mushy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('musical');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mysterious');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('mythical');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('nasty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('natural');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('negative');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('new');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('noble');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('north');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('null');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('oaken');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('oceanic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('old');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('painful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('pale');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('peaceful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('poisonous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('prime');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('primitive');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('profane');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('pulpy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('purple');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('putrid');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('quick');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('quirky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('rainy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('random');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('raw');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('red');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('regal');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ripper');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ripe');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('romantic');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('roomy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('rosy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('rough');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('royal');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('rumored');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('rusty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('salty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('savage');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('scalding');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('scummy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('secretive');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('shimmery');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('silent');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('silken');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('silky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('silty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('silvery');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sinful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('slitted');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('smashing');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('smiley');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('smooth');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sooty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('soulful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('south');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('spicy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('spidery');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('spiky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('spirited');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('starry');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('stern');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sticky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('stormy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('strange');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('strapping');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('strong');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('stretchy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('stunted');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('stupid');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('stylish');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('subordinate');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sucky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('insufferable');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sullen');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('swampy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sweaty');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('sweet');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('swift');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('syrupy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('terrible');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('thunderous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('tight');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('timey');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('toady');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('touchy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('trashy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('tricky');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('trim');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ugly');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('ultimate');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('unholy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('unkempt');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('unseen');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('useless');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('velvety');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('venomous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('vile');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('violence');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('violet');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('watchful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wavy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('weird');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('west');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('white');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wicked');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wild');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('willful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wispy');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wonderous');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wooden');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wormlike');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wrathful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('wretched');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('yellow');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('young');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('youthful');\r\nINSERT INTO \"Words_Adjective\" (\"Word\") VALUES ('zealous');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('acers','acer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('actors','actor');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('adventurers','adventurer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('armorers','armorer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('axers','axer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('backers','backer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('barbers','barber');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bathers','bather');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('battlers','battler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bearers','bearer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('beheaders','beheader');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('belchers','belcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bewitchers','bewitcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bitchers','bitcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('blackeners','blackener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('blazers','blazer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('blinders','blinder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('blisterers','blisterer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bloaters','bloater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bleeders','bleeder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('blossomers','blossomer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('boilers','boiler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('emboldeners','emboldener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bolteners','boltener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('booters','booter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('botherers','botherer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bowers','bower');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('breachers','breacher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('breakers','breaker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('breathers','breather');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('breeders','breeder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('brewer','brew');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bridlers','bridler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('brighteners','brightener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bristlers','bristler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bringers','bringer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('broilers','broiler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('buckers','bucker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bucklers','buckler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('burdeners','burdener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('burners','burner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('buriers','burier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bushelers','busheler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('busters','buster');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('bustlers','bustler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('butchers','butcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('butterers','butterer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('buttoners','buttoner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cacklers','cackler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('callers','caller');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('campers','camper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('candiers','candier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cavers','caver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cavorter','cavorter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chanters','chanter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('charrers','charrer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('charmers','charmer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chewers','chewer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chillers','chiller');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chippers','chipper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chokers','choker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('choppers','chopper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chuckers','chucker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('clappers','clapper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('claspers','clasper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('clawers','clawer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('clearers','clearer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cleavers','cleaver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('clingers','clinger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('clubbers','clubber');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('clutterers','clutterer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('coilers','coiler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('colorers','colorer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('conquerors','conqueror');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('chefs','chef');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('coverers','coverer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('couplers','coupler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('crawlers','crawler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('creepers','creeper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('crossers','crosser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('crowners','crowner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('crucifiers','crucifier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('crunchers','cruncher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('crushers','crusher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('criers','crier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cuddlers','cuddler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cursers','curser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('cutters','cutter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('dancers','dancer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('danglers','dangler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('damagers','damager');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('decapitaters','decapitater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('deceivers','deceiver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('desecraters','desecrater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('deserters','deserter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('despairers','despairer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('destroyers','destroyer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('devourers','devourer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('diners','diner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('dirtiers','dirtier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('ditchers','ditcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('drainers','drainer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('dreamers','dreamer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('dressers','dresser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('drinkers','drinker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('drippers','dripper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('droolers','drooler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('drowners','drowner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('drier','drier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('dumpers','dumper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('dyers','dyer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('eaters','eater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('engravers','engraver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('entrancers','entrancer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('entrenchers','entrencher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('evildoers','evildoer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('executioners','executioner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('faces','face');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('feasters','feaster');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('finders','finder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('fishers','fisher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('flamers','flamer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('flankers','flanker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('flingers','flinger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('flooders','flooder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('flutists','flutist');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('fliers','flier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('focusers','focuser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('foggers','fogger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('foolers','fooler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('forkers','forker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('fortifiers','fortifier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('founders','founder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('framer','framer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('freers','freer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('freezers','freezer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('gamers','gamer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('garnishers','garnisher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('gazers','gazer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('glazers','glazer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('gliders','glider');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('gorgers','gorger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('greasers','greaser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('grillers','griller');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('grinders','grinder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('grippers','gripper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('growers','grower');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('grubbers','grubber');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('guarders','guarder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('gutters','gutter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hagglers','haggler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hammerers','hammerer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('handers','hander');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('harvesters','harvester');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hatcheters','hatcheter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('haters','hater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('haunters','haunter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hawker','hawker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hexers','hexer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hiders','hider');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hobblers','hobbler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hoggers','hogger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hoisters','hoister');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('holers','holer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('honeyers','honeyer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hoppers','hopper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hounders','hounder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('howlers','howler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hugger','hugger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hummers','hummer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hungerers','hungerer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('hustlers','hustler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('icers','icer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('idlers','idler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('idolizers','idolizer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('imprisoners','imprisoner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('inkers','inker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('innkeepers','innkeeper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('ironers','ironer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('itchers','itcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('jesters','jester');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('jokers','joker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('jugglers','juggler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('juicers','juicer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('jumpers','jumper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('keepers','keeper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('kickers','kicker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('killers','killer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('kissers','kisser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('kneaders','kneader');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('knifer','knifer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('knitters','knitter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('lawyers','lawyer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('leaders','leader');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('leechers','leecher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('liars','liar');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('lighters','lighter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('listeners','listener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('loaners','loaner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('loners','loner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('looters','looter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('losers','loser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('lovers','lover');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('lurkers','lurker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('lyricists','lyricist');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('manglers','mangler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('meditaters','meditater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('mincers','mincer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('miners','miner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('murderers','murderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('musher','musher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('negators','negator');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('openers','opener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('packers','packer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('panderers','panderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('planters','planter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('plotter','plotter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('poisoners','poisoner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('prankers','pranker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('prisoners','prisoner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('profiters','profiter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('prophets','prophet');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('prowlers','prowler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('pukers','puker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('pullers','puller');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('punchers','puncher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('pushers','pusher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('quackers','quacker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('racers','racer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('rammers','rammer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('rampagers','rampager');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('ravagers','ravager');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('ringers','ringer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('romancers','romancer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('ruiners','ruiner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('ruler','ruler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('sawers','sawer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('screamers','screamer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('seducers','seducer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('seers','seer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('server','server');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('severers','severer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shankers','shanker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shearers','shearer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shelterers','shelterer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shielders','shielder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shooters','shooter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('showers','shower');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('showerers','showerer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shredder','shredder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shrieker','shrieker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('shutter','shutter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('sickeners','sickener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('siegers','sieger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('silencers','silencer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('singers','singer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('skulkers','skulker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('slaughterers','slaughterer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('slavers','slaver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('slayers','slayer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('slimmers','slimmer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('slitters','slitter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('smashers','smasher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('smilers','smiler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('smokers','smoker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('smoothers','smoother');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('smoulderers','smoulderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('snackers','snacker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('snickerers','snickerer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('snugglers','snuggler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('soothers','soother');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('spewers','spewer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('spoilers','spoiler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('spooners','spooner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('springers','springer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('spiers','spier');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('squirmers','squirmer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stabbers','stabber');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stalkers','stalker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('starvers','starver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stealers','stealer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stoners','stoner');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stormers','stormer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('strengtheners','strengthener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stretchers','stretcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('strikers','striker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stroker','stroker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stutterers','stutterer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('stylers','styler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('suckers','sucker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('sufferers','sufferer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('sunderers','sunderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('surprisers','surpriser');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('swampers','swamper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('sweater','sweater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('swimmers','swimmer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('takers','taker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tarnishers','tarnisher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tellers','teller');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('terrorizers','terrorizer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('throwers','thrower');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('thunderers','thunderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tickers','ticker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tighteners','tightener');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('timers','timer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tormenters','tormenter');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('touchers','toucher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('trappers','trapper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('treasurers','treasurer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('treaters','treater');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tricksters','trickster');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('trimmers','trimmer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('troublemakers','troublemaker');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tugger','tugger');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('tumblers','tumbler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('vandalizers','vandalizer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('violators','violator');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('voiders','voider');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('wailers','wailer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('wanderers','wanderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('wasters','waster');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('watchers','watcher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('wearers','wearer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('weavers','weaver');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('weeders','weeder');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('weighers','weigher');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('wheelers','wheeler');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('whippers','whipper');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('whisperers','whisperer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('wonderers','wonderer');\r\nINSERT INTO \"Words_ActionNoun\" (\"Plural\",\"Word\") VALUES ('workers','worker');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ace');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('act');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('adventure');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('age');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ageless');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ale');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('alive');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('apple');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ancient');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('angel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('anger');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('animal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('arm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('armor');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('arrow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('artifact');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('artificial');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ash');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('aura');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('axe');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('baby');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('back');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bad');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bake');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bald');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ball');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bane');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bar');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bare');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('barb');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bastard');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bath');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('battle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('beak');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('beast');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bear_animal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bed');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bee');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('beer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('beetle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('beguil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('behead');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('belch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('berry');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bewitch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('big');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bile');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bird');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bitch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('black');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blade');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blaze');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blind');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blister');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bloat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blood');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bloody');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blossom');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('blue');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('boar');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('boat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bodice');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bog');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('boil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bold');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bolt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bone');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('book');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('boot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bother');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('brain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('breach');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('breeches');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bread');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('break');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('breakfast');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('breath');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('breed');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('brew');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bride');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bridle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bright');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bristle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('brilliant');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('brim');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bring');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('broil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('brother');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('brunch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('buck');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('buckle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bud');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bunch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('burden');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('burn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bury');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bush');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bushel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bust');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('business');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('busy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('bustle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('butcher');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('butter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('butterfly');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('button');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('buzzard');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cackle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cake');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('call');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('camp');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cancer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('candle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('candy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('canyon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('carnage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('casket');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('castle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cavort');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cell');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cellar');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chant');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chaos');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chamber');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('char');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('charm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chew');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('child');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('choke');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('choker');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chop');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('chuck');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cinder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clam');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clap');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clasp');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('claw');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clearing');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cleave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cling');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cloak');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clod');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cloister');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('closet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('club');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cluster');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('clutter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cobra');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('coil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cold');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('color');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('comet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('common');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('conquer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cook');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cover');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cotton');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('couple');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crab');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crawl');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('craze');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crazy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cream');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('creek');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('creep');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('creepy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crescent');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cross');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crown');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crotch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crucify');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crumble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crunch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crush');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cry');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crypt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('crystal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cuddle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cudgel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cup');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('curse');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cut');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('cyst');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dance');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dangle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dank');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dagger');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dark');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('date');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('damage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('damn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dawn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('day');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dead');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('death');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('decapitate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('decay');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('deceive');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('deep');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('deer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('demon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('desecrate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('desert');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('desert_verb');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dessert');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('despair');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('destroy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('destruction');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('devil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('devour');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('diamond');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dinner');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dirt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('disguise');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ditch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dog');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('domain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('domestic');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('donkey');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('doom');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('door');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dragon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('drain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dream');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dress');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('drink');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('drip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('drool');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('drown');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dry');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dump');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dumpling');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dung');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dungeon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dusk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dust');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('duty');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('dye');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('eagle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('earth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('east');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('eat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('eel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('eerie');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('egg');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('elder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('engrave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('eternal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('entrance');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('entrails');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('entrench');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('entwine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('everlasting');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('evil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('execute');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('eye');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('face');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fall');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('false');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('famine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fang');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fatal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('father');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('feast');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fetid');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fiend');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fierce');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('filth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('find');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('finger');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fire');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('first');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fish');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fist');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flame');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flank');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flea');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flee');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flesh');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fling');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flood');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flower');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('flute');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fly');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('focus');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fog');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fool');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('foot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('forest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fork');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fortify');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fortress');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('found');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fragile');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fragment');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('frame');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fray');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('free');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('frenzy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('freeze');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('frill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('frog');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fruit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fungus');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('fur');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('game');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('garlic');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('garnish');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gaunt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gaze');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gerbil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ghost');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ghoul');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gift');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gland');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('glaze');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('glide');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('glimmer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('glisten');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gloss');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('glove');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('glutton');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('goat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('god');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('god-forsaken');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gold');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('goose');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gore');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gorge');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grand');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grape');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grass');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grease');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('great');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('greed');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('green');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('griffon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grim');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grind');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gristle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grizzle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grove');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('growl');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('grub');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('guard');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('guile');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('guise');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('gut');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hag');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('haggle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hair');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hammer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hand');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hare');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('harvest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hatchet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('haunt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hawk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hay');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('head');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('heart');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('heartless');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('heartful');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hearth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hedge');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hell');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('helm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hero');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hex');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hide');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hideous');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('high');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hobble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hog');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hoist');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hole');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('holy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('home');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('honey');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hood');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hoof');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hop');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('horn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('horny');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('horse');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hound');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('howl');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hug');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hum');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hunger');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hungry');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('hustle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ice');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('idle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('idol');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('idolize');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('imprison');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('impure');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('incense');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('incest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('inch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ink');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('inkling');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('inn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('insane');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('invisible');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('iron');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('irony');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('itch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ivory');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ivy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('jackal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('jaw');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('jest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('joke');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('judge');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('juggle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('juice');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('jump');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('jungle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('just');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('justify');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('keep');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('keg');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('key');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('kick');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('kill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('kind');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('kiss');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('king');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('kingdom');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('knead');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('knife');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('knight');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('knit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('knot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lace');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lake');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lard');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('larva');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('last');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('law');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lazy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lead');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lead_metal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('leaf');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('leak');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lean');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('leech');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('legend');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lens');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('leopard');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('leper');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('leprosy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('letter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lie');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('light');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lightning');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('life');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('limb');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('listen');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('liver');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lizard');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('loan');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lobster');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lock');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lone');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('long');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('loot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lord');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lose');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('louse');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('love');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('low');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lunch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lung');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lurch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lurk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lush');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lust');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lute');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('lyric');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('maggot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('magic');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('man');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mangle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mangy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('marsh');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('martyr');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('master');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mead');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('meadow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('meal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('meat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('meditation');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mellow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('menace');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mess');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('metal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('midnight');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('might');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mile');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mince');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mind');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('minion');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mirror');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('misery');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mist');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mold');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mole');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('molten');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('monkey');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('moon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('moth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mother');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mouse');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mouth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mud');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('muffin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mule');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('murder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mush');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mushroom');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('music');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('mystery');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('myth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nail');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nasty');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nature');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('negate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nestle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('net');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('new');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('newt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nibble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('night');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nightmare');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('noble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('north');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nose');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('null');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('number');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nurture');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('nut');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('oak');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('oar');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('oat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('oblivion');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ocean');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('old');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('omen');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('one');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('onion');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ooze');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('open');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('orb');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('owl');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ox');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pack');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pad');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('page');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('paint');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pale');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('palm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pander');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pant');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('panther');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pants');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('paper');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('peace');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('peach');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pepper');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pig');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('piss');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pitch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('plague');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('plant');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('plot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pocket');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('poison');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('portal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('power');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('prank');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pride');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('priest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('prime');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('prison');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('primitive');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('profane');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('profit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('prophecy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('prowl');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('puke');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pull');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pulley');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pulp');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('punch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('purple');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('pus');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('push');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('putrid');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('quack');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('quake');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('quark');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('queen');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('quick');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('quill');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('quirk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rabbit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rabble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('race');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rack');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rag');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rain');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rake');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ram');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rampage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('random');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ransack');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ravage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('raven');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('raw');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('razor');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('red');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('regal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('reign');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rein');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rider');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rim');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ring');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ripe');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rise');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rite');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('river');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rock');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rogue');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('romance');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('room');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('root');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rose');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rough');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('royal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ruin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rule');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rumor');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('rust');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sabre');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sack');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('saint');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('salt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('salve');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sap');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('satin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('savage');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('savagery');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('savior');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('saw');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scab');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scald');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scar');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scold');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scorpion');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scourge');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scream');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('scum');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sea');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('seal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('seam');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('season');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('secret');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('seduce');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('seed');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('see');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('seize');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('serpent');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('servant');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('serve');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sever');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sewer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shadow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shaft');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shank');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shark');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sheen');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shell');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shelter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shield');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shimmer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ship');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shoot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('show');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shower');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shred');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shriek');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('shut');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sick');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sickness');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('siege');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('silence');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('silk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('silky');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('silt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('silver');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sinew');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sing');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sister');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('skirt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('skull');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('skulk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('skunk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sky');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slaughter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slay');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slim');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slime');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slink');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slither');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sliver');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sloth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('slug');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('smash');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('smile');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('smith');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('smoke');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('smooth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('smoulder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('snack');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('snake');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sneer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('snicker');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('snot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('snuggle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('soil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('soldier');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('soot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('soothe');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sorrow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('soul');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sound');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('south');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spasm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spawn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spell');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spew');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spice');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spider');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spike');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spirit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spoil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spoon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spring');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('spy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('squid');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('squirm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stab');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('staff');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stalk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stand');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('star');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('steed');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('starve');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('steal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('steel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stench');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stern');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stick');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sticky');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stone');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('storm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('strange');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stranger');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('strap');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('straw');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stray');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('strength');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stretch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('strike');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stroke');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stunt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stupid');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('stutter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('style');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('subordinate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('suck');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('suffer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sullen');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('summer');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sunder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('supper');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('surprise');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('swamp');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sweat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sweet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sweetness');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('swift');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('swim');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('swine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('sword');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('syrup');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('take');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tail');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('talon');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tar');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tarnish');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tell');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tempest');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('terrible');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('terror');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('terrorize');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('thief');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('thirst');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('thorn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('thrall');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('throat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('throne');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('throw');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('thunder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tick');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tight');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('time');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('toad');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('toe');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tomb');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tome');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tongue');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tooth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('torment');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('touch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tour');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tower');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trail');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trance');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trap');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trash');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('treasure');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('treat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('treaty');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trench');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tribe');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trick');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trickery');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trim');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('trouble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tug');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tulip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tumble');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tumor');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('turmoil');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tusk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('tweet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('twilight');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('twine');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('twist');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ugly');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('ultimate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('uncle');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('unholy');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('unkempt');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('unseen');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('urn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('useless');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vandal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vegetable');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vegetation');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('velvet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('venom');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vermin');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vile');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('violate');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('violence');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('violet');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('viper');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('voice');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('void');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('volcano');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vomit');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('vulture');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wail');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wander');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('war');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('warrior');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wasp');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('waste');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('watch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('watchful');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wear');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('weasel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('weave');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('weed');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('weigh');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('weird');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('west');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wheat');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wheel');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('whip');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('whisk');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('whisker');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('whisky');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('whisper');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('white');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wicked');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wild');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wilderness');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('will');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wing');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('winter');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wisp');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('witch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wonder');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wood');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('work');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('worm');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wraith');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wrath');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('wretch');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('yarn');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('year');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('yellow');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('young');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('youth');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('zeal');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('zealot');\r\nINSERT INTO \"Words\" (\"Word\") VALUES ('zephyr');\r\nINSERT INTO \"Utility\" (\"ID\",\"Buildable\",\"Item\") VALUES ('Door',1,NULL);\r\nINSERT INTO \"Utility\" (\"ID\",\"Buildable\",\"Item\") VALUES ('Torch',1,NULL);\r\nINSERT INTO \"Utility\" (\"ID\",\"Buildable\",\"Item\") VALUES ('WallTorch',1,'Torch');\r\nINSERT INTO \"Utility\" (\"ID\",\"Buildable\",\"Item\") VALUES ('BigTorch',1,NULL);\r\nINSERT INTO \"Utility\" (\"ID\",\"Buildable\",\"Item\") VALUES ('Brazier',1,NULL);\r\nINSERT INTO \"Utility\" (\"ID\",\"Buildable\",\"Item\") VALUES ('AlarmBell',1,NULL);\r\nINSERT INTO \"Uniforms\" (\"ID\",\"Name\",\"UserDefined\") VALUES (1,'Leather',0);\r\nINSERT INTO \"Uniforms\" (\"ID\",\"Name\",\"UserDefined\") VALUES (2,'Chain',0);\r\nINSERT INTO \"Uniforms\" (\"ID\",\"Name\",\"UserDefined\") VALUES (3,'Plate',0);\r\nINSERT INTO \"Uniforms\" (\"ID\",\"Name\",\"UserDefined\") VALUES (4,'Heavy Plate',0);\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HeadArmor','Leather','LeatherHelm','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HeadArmor','Bone','SkullHelmet','Bone');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HeadArmor','Chainmail','ChainHelm','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HeadArmor','Plate','PlateHelm','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HeadArmor','HeavyPlate','HeavyPlateHelm','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ChestArmor','Leather','LeatherCuirass','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ChestArmor','Bone','BoneShirt','Bone');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ChestArmor','Chainmail','ChainShirt','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ChestArmor','Plate','PlateChest','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ChestArmor','HeavyPlate','HeavyPlateChest','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ArmArmor','Leather','LeatherBracer','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ArmArmor','Chainmail','ChainBracer','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ArmArmor','Plate','PlatePauldron','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('ArmArmor','HeavyPlate','HeavyPlatePauldron','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HandArmor','Leather','LeatherGlove','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HandArmor','Chainmail','ChainGlove','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HandArmor','Plate','PlateGlove','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('HandArmor','HeavyPlate','HeavyPlateGlove','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('LegArmor','Leather','LeatherPants','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('LegArmor','Chainmail','ChainPants','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('LegArmor','Plate','PlateGreaves','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('LegArmor','HeavyPlate','HeavyPlateGreaves','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('FootArmor','Leather','LeatherBoot','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('FootArmor','Chainmail','ChainBoot','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('FootArmor','Plate','PlateBoot','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('FootArmor','HeavyPlate','HeavyPlateBoot','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('LeftHandHeld','Torch','Torch','Wood');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('RightHandHeld','Sword','Sword','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('RightHandHeld','Pickaxe','Pickaxe','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('RightHandHeld','FellingAxe','FellingAxe','Metal');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('Back','Backpack','Backpack','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('Back','Quiver','Quiver','Leather');\r\nINSERT INTO \"Uniform_Slots\" (\"ID\",\"Type\",\"ItemID\",\"MaterialType\") VALUES ('Back','AmmoPouch','AmmoPouch','Leather');\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('HeadArmor',1);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('ChestArmor',1);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('ArmArmor',2);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('HandArmor',2);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('LegArmor',1);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('FootArmor',2);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('LeftHandHeld',1);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('RightHandHeld',1);\r\nINSERT INTO \"Uniform\" (\"ID\",\"Sides\") VALUES ('Back',1);\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 0 0',NULL,'PineTrunk1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 0 1',NULL,'PineTrunk2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'1 0 1','FR','PineTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 1 1','FL','PineTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'-1 0 1','BL','PineTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 -1 1','BR','PineTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 0 2',NULL,'PineTrunk2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'1 0 2','FR','PineTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 1 2','FL','PineTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'-1 0 2','BL','PineTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 -1 2','BR','PineTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 0 3',NULL,'PineTrunk2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'1 0 3','FR','PineTree3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 1 3','FL','PineTree3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'-1 0 3','BL','PineTree3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 -1 3','BR','PineTree3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('PineTree',0,'0 0 4',NULL,'PineTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'0 0 0',NULL,'AppleTreeTrunkBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'0 0 1',NULL,'AppleTreeTrunkMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'1 0 1','FR','AppleTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'0 1 1','FL','AppleTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'-1 0 1','BL','AppleTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'0 -1 1','BR','AppleTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'1 1 1','FR','AppleTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'-1 1 1','FL','AppleTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'-1 -1 1','BL','AppleTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'1 -1 1','BR','AppleTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'-1 -1 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'-1 0 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'-1 1 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'0 -1 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'0 0 2',NULL,'AppleTreeTrunkMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'0 1 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'1 -1 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'1 0 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'1 1 2',NULL,'AppleTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'1 0 3','FR','AppleTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'0 1 3','FL','AppleTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'-1 0 3','BL','AppleTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'0 -1 3','BR','AppleTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',0,'0 0 3',NULL,'AppleTreeMiddleTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'-1 1 3','FL','AppleTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'1 1 3','FR','AppleTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'-1 -1 3','BL','AppleTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('AppleTree',1,'1 -1 3','BR','AppleTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'0 0 0',NULL,'OrangeTreeTrunkBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'0 0 1',NULL,'OrangeTreeTrunkMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'1 0 1','FR','OrangeTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'0 1 1','FL','OrangeTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'-1 0 1','BL','OrangeTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'0 -1 1','BR','OrangeTreeBottom');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'1 1 1','FR','OrangeTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'-1 1 1','FL','OrangeTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'-1 -1 1','BL','OrangeTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'1 -1 1','BR','OrangeTreeBottomCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'-1 -1 2','BL','OrangeTreeMiddleCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'-1 0 2',NULL,'OrangeTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'-1 1 2','FL','OrangeTreeMiddleCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'0 -1 2',NULL,'OrangeTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'0 0 2',NULL,'OrangeTreeTrunkMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'0 1 2',NULL,'OrangeTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'1 -1 2','BR','OrangeTreeMiddleCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'1 0 2',NULL,'OrangeTreeMiddle');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'1 1 2','FR','OrangeTreeMiddleCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'1 0 3','FR','OrangeTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'0 1 3','FL','OrangeTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'-1 0 3','BL','OrangeTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'0 -1 3','BR','OrangeTreeTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',0,'0 0 3',NULL,'OrangeTreeMiddleTop');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'-1 1 3','FL','OrangeTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'1 1 3','FR','OrangeTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'-1 -1 3','BL','OrangeTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OrangeTree',1,'1 -1 3','BR','OrangeTreeTopCorner');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 0 0',NULL,'OakTree21');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 0 1',NULL,'OakTree22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 1 1',NULL,'OakTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 1 1',NULL,'OakTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 1 1',NULL,'OakTree3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 0 1',NULL,'OakTree4');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 -1 1',NULL,'OakTree5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 -1 1',NULL,'OakTree6_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 0 1',NULL,'OakTree6_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 -1 1',NULL,'OakTree6_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 0 2',NULL,'OakTree22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 1 2',NULL,'OakTree7');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 1 2',NULL,'OakTree8');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 1 2',NULL,'OakTree9');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 0 2',NULL,'OakTree10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 -1 2',NULL,'OakTree11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 -1 2',NULL,'OakTree12_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 0 2',NULL,'OakTree12_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 -1 2',NULL,'OakTree12_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 1 3',NULL,'OakTree23');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 1 3',NULL,'OakTree24');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 1 3',NULL,'OakTree25');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 0 3',NULL,'OakTree26');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'1 -1 3',NULL,'OakTree27');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 0 3',NULL,'OakTree28');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 0 3',NULL,'OakTree29');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'0 -1 3',NULL,'OakTree210');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('OakTree',0,'-1 -1 3',NULL,'OakTree211');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 0 0',NULL,'WillowTree21');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 0 1',NULL,'WillowTree22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 1 1',NULL,'WillowTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 1 1',NULL,'WillowTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 1 1',NULL,'WillowTree3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 0 1',NULL,'WillowTree4');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 -1 1',NULL,'WillowTree5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 -1 1',NULL,'WillowTree6_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 0 1',NULL,'WillowTree6_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 -1 1',NULL,'WillowTree6_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 0 2',NULL,'WillowTree22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 1 2',NULL,'WillowTree7');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 1 2',NULL,'WillowTree8');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 1 2',NULL,'WillowTree9');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 0 2',NULL,'WillowTree10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 -1 2',NULL,'WillowTree11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 -1 2',NULL,'WillowTree12_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 0 2',NULL,'WillowTree12_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 -1 2',NULL,'WillowTree12_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 1 3',NULL,'WillowTree23');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 1 3',NULL,'WillowTree24');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 1 3',NULL,'WillowTree25');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 0 3',NULL,'WillowTree26');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'1 -1 3',NULL,'WillowTree27');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 0 3',NULL,'WillowTree28');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 0 3',NULL,'WillowTree29');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'0 -1 3',NULL,'WillowTree210');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('WillowTree',0,'-1 -1 3',NULL,'WillowTree211');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom1',0,'0 0 0',NULL,'Mushroom1_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom1',0,'0 0 1',NULL,'Mushroom1_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom1',0,'0 0 2',NULL,'Mushroom1_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom1',0,'0 0 3',NULL,'Mushroom1_4');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 0 0',NULL,'Mushroom2_14');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 0 1',NULL,'Mushroom2_22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 0 2',NULL,'Mushroom2_28');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 0 3',NULL,'Mushroom2_16');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 1 3','FL','Mushroom2_3_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 1 3',NULL,'Mushroom2_16');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 1 3',NULL,'Mushroom2_3_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 0 3',NULL,'Mushroom2_16');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 -1 3','BR','Mushroom2_3_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 -1 3',NULL,'Mushroom2_16');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 -1 3','BL','Mushroom2_3_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 0 3',NULL,'Mushroom2_16');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 2 3','FL','Mushroom2_3_21');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 2 3',NULL,'Mushroom2_3_02');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 2 3',NULL,'Mushroom2_3_12');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'2 2 3',NULL,'Mushroom2_3_22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'2 1 3',NULL,'Mushroom2_3_21');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'2 0 3','BR','Mushroom2_3_02');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'2 -1 3','BR','Mushroom2_3_12');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 0 4',NULL,'Mushroom2_19');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 0 4','BL','Mushroom2_4_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 -1 4','BR','Mushroom2_4_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 -1 4','BR','Mushroom2_4_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 0 4',NULL,'Mushroom2_4_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 1 4',NULL,'Mushroom2_4_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 1 4','FL','Mushroom2_4_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 1 4','FL','Mushroom2_4_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 0 0',NULL,'Mushroom2_14');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 0 1',NULL,'Mushroom2_22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 0 2',NULL,'Mushroom2_16');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'1 0 2',NULL,'Mushroom3_2_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 1 2','FL','Mushroom3_2_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'-1 0 2','BL','Mushroom3_2_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 -1 2','BR','Mushroom3_2_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'1 1 2',NULL,'Mushroom3_2_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'-1 1 2','FL','Mushroom3_2_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'-1 -1 2','BL','Mushroom3_2_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'1 -1 2','BR','Mushroom3_2_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 0 3',NULL,'Mushroom2_6_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'1 0 3',NULL,'Mushroom3_3_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 1 3','FL','Mushroom3_3_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 0',NULL,'BirchTree1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 1',NULL,'BirchTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 0 1',NULL,'BirchTree9');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 1 1',NULL,'BirchTree6');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 0 1',NULL,'BirchTree7');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 -1 1',NULL,'BirchTree8');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 2 2',NULL,'BirchTree5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'2 0 2',NULL,'BirchTree10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 2',NULL,'BirchTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 0 3',NULL,'BirchTree9');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 1 3',NULL,'BirchTree6');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 0 3',NULL,'BirchTree7');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 -1 3',NULL,'BirchTree8');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 2 4',NULL,'BirchTree5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'2 0 4',NULL,'BirchTree11_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 3',NULL,'BirchTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 4',NULL,'BirchTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 1 3',NULL,'BirchTree11_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 0 5',NULL,'BirchTree20_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 -1 5',NULL,'BirchTree11_5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 -1 5',NULL,'BirchTree20_4');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 1 5',NULL,'BirchTree11_5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 1 5',NULL,'BirchTree20_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 0 5',NULL,'BirchTree20_1');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 5',NULL,'BirchTree2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 0 6',NULL,'BirchTree15');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 -2 2',NULL,'BirchTree5_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-2 0 2',NULL,'BirchTree10_5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'0 -2 4',NULL,'BirchTree5_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-2 0 4',NULL,'BirchTree10_5');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 -1 3',NULL,'BirchTree11_2');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 -1 3',NULL,'BirchTree11_3');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 1 3',NULL,'BirchTree11_4');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'1 -1 5',NULL,'BirchTree11_6');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('BirchTree',0,'-1 1 5',NULL,'BirchTree11_6');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-2 -2 3','BL','Mushroom2_3_22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-2 -1 3','BL','Mushroom2_3_21');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-2 1 3','FL','Mushroom2_3_12');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-2 2 3','FL','Mushroom2_3_22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 -2 3','BL','Mushroom2_3_12');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'0 -2 3','BL','Mushroom2_3_02');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'1 -2 3','BR','Mushroom2_3_21');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'2 -2 3','BR','Mushroom2_3_22');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-2 0 3','FL','Mushroom2_3_02');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom2',0,'-1 -1 4','BL','Mushroom2_4_11');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'-1 0 3','BL','Mushroom3_3_10');\r\nINSERT INTO \"TreeLayouts_Layout\" (\"ID\",\"FruitPos\",\"Offset\",\"Rotation\",\"SpriteID\") VALUES ('Mushroom3',0,'0 -1 3','BR','Mushroom3_3_10');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('PineTree');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('AppleTree');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('OrangeTree');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('OakTree');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('WillowTree');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('Mushroom1');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('Mushroom2');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('Mushroom3');\r\nINSERT INTO \"TreeLayouts\" (\"ID\") VALUES ('BirchTree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Floor','floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Wall','wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$PileOf','Pile of');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Stockpile','Stockpile');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Stockpiles','Stockpiles');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Grove','Grove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Farm','Farm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Pasture','Pasture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Room','Room');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Door','Door');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Population','Population');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Kingdom','Kingdom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GnomeList','Gnome List');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Professions','Professions');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Skills','Skills');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Inventory','Inventory');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Build','Build');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Gnome','Gnome');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Workshop','Workshop');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Debug','Debug');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Overview','Overview');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$LastActions','Last Actions');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$PlantTree','Plant Tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$BuildStorage','Build Storage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$BuildFurniture','Build Furniture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$BuildDoor','Build Door');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$BuildUtility','Build Utility');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$BuildItem','Build Item');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Utility','Utility');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemHistory','Item History');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ButtonBack','Back');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechWood','wood tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechStone','stone tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechMetal','metal tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechEngineer','engineering tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechCloth','cloth tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechFood','food tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechMilitary','military tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechMagic','magic tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$TechName_TechLeather','leather tech');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SeasonName_Spring','Spring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SeasonName_Summer','Summer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SeasonName_Autumn','Autumn');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SeasonName_Winter','Winter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Crude','crude workbench');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Carpenter','carpenter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Sawmill','sawmill');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Kitchen','kitchen');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Stonecutter','stonecutter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Stonemason','stonemason');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Distillery','distillery');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Forge','forge');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Furnace','furnace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Kiln','kiln');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Blacksmith','blacksmith');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Metalworker','metal worker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Gemcutter','gem cutter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Loom','loom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Stonecarver','stone carver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Woodcarver','wood carver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Jeweler','jeweler');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Tailor','tailor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Bonecarver','bone carver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Butcher','butcher');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_MarketStall','market stall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Prospector','prospector');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Dyer','dyer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Fishery','fishery');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_HauleItem','Haule item');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_HauleMultipleItems','Haule multiple items');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Fish','Fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Mine','Mine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_DigHole','Dig hole');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_ExplorativeMine','Explorative mine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_RemoveRamp','Remove ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_RemoveFloor','Remove floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Deconstruct','Deconstruct');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_RemovePlant','Remove plant');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_MineStairsUp','Mine stairs up');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_DigStairsDown','Dig stairs down');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_DigRampDown','Dig ramp down');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildWall','Build wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildFence','Build fence');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildFloor','Build floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildWallFloor','Build wall with floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildStairs','Build stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildScaffold','Build scaffolding');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildRamp','Build ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildRampCorner','Build ramp corner');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildWorkshop','Build workshop');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildStorage','Build storage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildFurniture','build furniture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildItem','Build item');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildDoor','Build door');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_BuildTorch','Build torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Harvest','Harvest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_HarvestTree','harvest tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_PlantTree','Plant tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_PlantTreeGrove','Plant tree in grove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Till','Till');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Plant','Plant');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_PlantFarm','Plant farm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_FellTree','Fell tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_CraftAtWorkshop','Craft at workshop');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_ManMarketStall','Man market stall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_ButcherFish','Butcher fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_LeadAnimalToPasture','Lead animal to pasture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_HarvestAnimal','Harvest animal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_ButcherAnimal','Butcher animal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Magic_Nature_SpeedGrowth','Cast nature spell,speed up growth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_Magic_Geomancy_RevealOre','Cast geomancy spell,reveal ore');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AlarmBell','alarm bell');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AlarmBellBase','alarm bell base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AlarmBellBell','alarm bell bell');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AmmoPouch','ammo pouch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Anvil','anvil');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AppleTree','apple tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bag','bag');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BallPeenHammer','ballpeen hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bandage','bandage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bar','bar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Barrel','barrel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Beans','beans');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bed','bed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WoodBedFrame','wood bed frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Beer','beer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bellows','bellows');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Berries','berries');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Block','block');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Brick','brick');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bolt','bolt of cloth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bone','bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BoneShirt','bone shirt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bread','bread');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bucket','bucket');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Cabinet','cabinet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Chair','chair');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Cheese','cheese');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_CheeseOmelette','cheese omelette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Chisel','chisel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Clipping','clipping');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Coin','coin');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Crate','crate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_CuttingWheel','cutting wheel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Door','door');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Dresser','dresser');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Dye','dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Egg','egg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FancyBed','four poster bed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FancyBedFrame','four poster bed frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FellingAxeBase','felling axe base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FellingAxeHead','felling axe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FellingAxe','felling axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_File','file');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FishBone','fish bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Fruit','fruit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Furnace','furnace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Gem','gem');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GemmedRing','gemmed ring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GemmedNecklace','gemmed necklace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Grain','grain');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Haft','haft');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Hearth','hearth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Hide','hide');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Hilt','hilt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Knife','knife');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_KnifeBlade','knife blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_KnifeHilt','knife hilt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherStrap','leather strap');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Leaves','leaves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LogFloor','log floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LogWall','log wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Loom','loom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Mattress','mattress');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Meat','meat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Milk','milk');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Mold','mold');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Mushroom','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_MushroomOmelette','mushroom omelette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Necklace','necklace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Needle','needle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_OrangeTree','orange tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Padding','padding');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PetRock','pet rock');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Pickaxe','pickaxe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PickaxeBase','pickaxe base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PickaxeHead','pickaxe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Pillar','pillar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_OakTree','oak tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WillowTree','willow tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PineTree','pine tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Plank','plank');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlankStairs','plank stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BlockStairs','block stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PuzzleBox','puzzle box');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Radish','fruit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawCloth','raw cloth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawCoal','raw coal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawGem','raw gem');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawOre','raw ore');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawSoil','raw soil');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawStone','raw stone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawWood','raw wood');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Ring','ring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sandwich','sandwich');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sack','sack');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sawblade','sawblade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Seed','seed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Skull','skull');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SkullHelmet','skull helmet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SoilFloor','soil floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SoilStairs','soil stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SoilWall','soil wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Statue','statue');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Statuette','statuette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Stick','stick');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_StoneFloor','stone floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_StoneStairs','stone stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_StoneWall','stone wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Straw','straw');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_String','string');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sausage','sausage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SausageOmelette','sausage omelette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Table','table');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Torch','torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_TrainingDummy','training dummy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Trough','trough');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Vegetable','vegetable');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Wheelbarrow','wheelbarrow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Wheat','wheat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Wine','wine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WoodBed','bed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WoodBedSheets','bed sheets');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Workbench','workbench');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FishingRod','fishing rod');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Fish','fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AnimalCorpse','corpse');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GoblinCorpse','corpse');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Painting','painting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BeeHive','bee hive');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Shed','shed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Cone','cone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Oak','acorn');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WillowSeed','willow seed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AlarmBell','alarm bell');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AmmoPouch','ammo pouch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Anvil','anvil');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ArmorPlate','armor plate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ArtificialArm','artificial arm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ArtificialFoot','artificial foot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ArtificialHand','artificial hand');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ArtificialLeg','artificial leg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Axle','axle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bag','bag');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BallPeenHammer','ball peen hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bandage','bandage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bar','bar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Barrel','barrel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BattleAxe','battle axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BattleAxeHead','battle axe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bed','bed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BedFrame','bed frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Beer','beer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bellows','bellows');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BladeTrap','blade trap');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Block','block');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Blunderbuss','blunderbuss');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BlunderbussBarrel','blunderbuss barrel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BlunderbussStock','blunderbuss stock');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bolt','bolt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BoneChair','bone chair');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BoneShirt','bone shirt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BoneStatuette','bone statuette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BoneTable','bone table');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Boot','boot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bread','bread');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Breastplate','breastplate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Brick','brick block');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BronzeBar','bronze bar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bucket','bucket');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Cabinet','cabinet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Cheese','cheese');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_CheeseOmelette','cheese omelette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Chisel','chisel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ClayStatuette','clay statuette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Claymore','claymore');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ClaymoreBlade','claymore blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Coin','coin');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Crate','crate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Crossbow','crossbow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_CrossbowBow','crossbow bow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_CrossbowStock','crossbow stock');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_CuttingWheel','cutting wheel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Cylinder','cylinder');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Dresser','dresser');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FancyBed','fancy bed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FancyBedFrame','fancy bed frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FellingAxe','felling axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FellingAxeHead','felling axe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_File','file');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Furnace','furnace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FruitWine','fruit wine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HoneyWine','honey wine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Gauntlet','gauntlet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Gear','gear');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Gearbox','gearbox');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Gem','gem');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_GemmedNecklace','gemmed necklace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_GemmedRing','gemmed ring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Greave','greave');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Haft','haft');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Hammer','hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HammerHead','hammer head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HandAxe','hand axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HandAxeHead','hand axe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Handcrank','handcrank');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Hatch','hatch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Hearth','hearth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Helmet','helmet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Hilt','hilt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Knife','knife');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_KnifeBlade','knife blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherArmorPanel','leather armor panel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherBoot','leather boot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherBracer','leather bracer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherCuirass','leather cuirass');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherGlove','leather glove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherGreave','leather greave');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherHelm','leather helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherStrap','leather strap');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Lever','lever');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Loom','loom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Mattress','mattress');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MechanicalWall','mechanical wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MechanismBase','mechanism base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MetalCrossbowBolt','crossbow bolt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MetalMusketRound','musket round');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MetalStatue','statue');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MetalStatuette','statuette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Mold','mold');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MushroomOmelette','mushroom omelette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Necklace','necklace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Needle','needle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MetalNeedle','needle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Padding','padding');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Pauldron','pauldron');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PetRock','pet rock');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Pickaxe','pickaxe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickaxeBaseWood','pickaxe base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickaxeHeadFlintStone','pickaxe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickaxeHeadStone','pickaxe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickaxeHeadWood','pickaxe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Pistol','pistol');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PistolBarrel','pistol barral');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PistolStock','pistol stock');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Plank','plank');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PressurePlate','pressure plate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PuzzleBox','puzzle box');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Quiver','quiver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_RawCoal','coal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Ring','ring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Rod','rod');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_RoseGoldBar','rosegold bar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Sack','sack');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Sandwich','sandwich');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Sausage','sausage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SausageOmelette','sausage omelette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Screw','screw');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Shield','shield');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ShieldBacking','shield backing');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ShieldBoss','shield boss');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SkullHelmet','skull helmet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SliverBar','bar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Spike','spike');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SpikeTrap','spike trap');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Spring','spring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SteelBar','steel bar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Stick','stick');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneChair','chair');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneCrossbowBolt','crossbow bolt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneDoor','door');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneHammer','hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneHandAxe','hand axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneMusketRound','musket round');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StonePillar','pillar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneSawblade','saw blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneStatue','statue');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneStatuette','statuette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneSword','sword');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_StoneTable','table');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_String','string');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Sword','sword');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SwordBlade','sword blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Tea','tea');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Tile','tile');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Torch','torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_TowerShield','tower shield');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_TowerShieldBacking','tower shield backing');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_TrainingDummy','training dummy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_TrapBase','trap base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Trough','trough');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Warhammer','warhammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WarhammerHead','warhammer head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Wheelbarrow','wheelbarrow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WindmillBlade','windmill blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Wine','wine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WoodChair','chair');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WoodDoor','door');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WoodStatue','statue');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WoodStatuette','statuette');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WoodTable','table');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_WoodenShield','shield');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Workbench','workbench');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Wrench','wrench');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FishingRod','fishing rod');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_DyedTable','dye table');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_DyedPlank','dye plank');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_RedDye','red dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_GreenDye','green dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_YellowDye','yellow dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BlueDye','blue dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PurpleDye','purple dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_CyanDye','cyan dye');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_DyeHair','dye hair');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AlarmBellBase','alarm bell base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AlarmBellBell','alarm bell bell');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Materials','Materials');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Grown','Grown');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Workshop','Workshop');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Food','Food');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Containers','Containers');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Furniture','Furniture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Cloth','Cloth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Butchery','Butchery');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Drinks','Drinks');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Gem','gem');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Coal','coal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Soil','soil');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Metal','metal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Stone','stone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Wood','wood');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Tree','tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Plant','plant');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Tools','tools');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Workplaces','workplaces');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Raw','raw');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Pastry','pastry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Drinks','drinks');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Immovable','immovable');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Movable','movable');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Living','living');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Unprocessed','unprocessed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Bones','bones');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Meats','meats');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Hides','hides');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Fruit','fruits');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Vegetable','vegetables');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Alcoholic','alcoholics');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Chairs','chairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Tables','tables');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Beds','beds');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Doors','doors');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Cabinets','cabinets');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_ClothProducts','products');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_LeatherProducts','products');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_JewelryProducts','products');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Misc','misc');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_MiscMaterials','misc materials');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Corpses','corpses');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_None','none');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_any','any');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Grass','grass');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Dirt','dirt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Sand','sand');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Clay','clay');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Granite','granite');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Basalt','basalt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Marble','marble');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Sandstone','sandstone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Bauxite','bauxite');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Serpentine','serpentine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_LapisLazuli','lapislazuli');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Obsidian','obsidian');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_ClayBrick','clay brick');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_SandBrick','sand brick');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Water','water');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Lava','lava');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Pine','pine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Oak','oak');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Willow','willow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_AppleWood','applewood');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Birch','birch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Coal','coal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Copper','copper');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Malachite','malachite');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Tin','tin');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Bronze','bronze');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Iron','iron');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Steel','steel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Lead','lead');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Silver','silver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Gold','gold');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_RoseGold','rosegold');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Platinum','platinum');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Emerald','emerald');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Sapphire','sapphire');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Amethyst','amethyst');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Diamond','diamond');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Ruby','ruby');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_FlintStone','flintstone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Amber','amber');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Beryll','beryll');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Topaz','topaz');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Wool','wool');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Chicken','chicken');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Yak','yak');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Emu','emu');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Sheep','sheep');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Pig','pig');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cow','cow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Rabbit','rabbit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Llama','llama');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Duck','duck');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Goose','goose');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Dog','dog');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cat','cat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Porcupine','porcupine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Fox','fox');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Wolf','wolf');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Deer','deer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Badger','badger');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_BlackBear','black bear');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Goat','goat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Squirrel','squirrel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GreenFish','green');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GreyFish','grey');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Panda','panda');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Spider','spider');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Woodlouse','woodlouse');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_ChickenBone','chicken bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_YakBone','yak bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_EmuBone','emu bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_SheepBone','sheep bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_PigBone','pig bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_CowBone','cow bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_RabbitBone','rabbit bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_LlamaBone','llama bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_DuckBone','duck bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GooseBone','goose bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_DogBone','dog bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_CatBone','cat bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_PorcupineBone','porcupine bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_FoxBone','fox bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_WolfBone','wolf bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_DeerBone','deer bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GoatBone','goat bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_BadgerBone','badger bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_BlackBearBone','black bear bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_SquirrelBone','squirrel bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GreenFishBone','green bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GreyFishBone','grey bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_PandaBone','panda bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_SpiderBone','spider bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_WoodlouseBone','woodlouse bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_OrangeWood','orangewood');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Mushroom','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Silica','silica');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Ceramic','ceramic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Glass','glass');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Strawberry','strawberry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Apple','apple');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Wheat','wheat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cotton','cotton');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Orange','orange');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Carrot','carrot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Onion','onion');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Potato','potato');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cabbage','cabbage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Asparagus','asparagus');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Broccoli','broccoli');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cauliflower','cauliflower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cucumber','cucumber');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Garlic','garlic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Parsnip','parsnip');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Radish','radish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Turnip','turnip');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Lettuce','lettuce');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Melon','melon');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Sugarbeet','sugar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Pumpkin','pumpkin');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Peas','pea');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Tea','tea');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Tobacco','tobacco');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Pineapple','pineapple');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Corn','corn');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Leek','leek');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Beans','beans');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Blackberry','blackberry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Artichoke','artichoke');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Bottlegourd','bottle gourd');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Tomato','tomato');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Capsicum','capsicum');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Grape','grape');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_BeetRoot','beet root');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Woad','woad');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_DyersWeed','dyers weed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Barley','barley');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Oat','oat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Millet','millet');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Red','red');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Green','green');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Blue','blue');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Purple','purple');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Yellow','yellow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Cyan','cyan');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_WoolBag','wool');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_CottonBag','cotton');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Goblin','goblin');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Mushroom1','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Mushroom2','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Mushroom3','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_StrawMushroom','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_WoodMushroom','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_FibreMushroom','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GrainMushroom','mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ERROR_TranslationKeyUnknown','***ERROR*** unknown string');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Tree','tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Plant','plant');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$AttributeName_Str','Strength');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$AttributeName_Dex','Dexterity');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$AttributeName_Con','Constitution');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$AttributeName_Int','Intelligence');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$AttributeName_Wis','Wisdom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$AttributeName_Cha','Charisma');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$NeedName_Hunger','Hunger');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$NeedName_Thirst','Thirst');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$NeedName_Sleep','Sleep');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$NeedName_Happiness','Happiness');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Panda','Panda');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Rabbit','Rabbit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Chicken','Chicken');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Pig','Pig');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_PigPink','Pig');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_PigYellow','Pig');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Sheep','Sheep');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Woodlouse','Woodlouse');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Dragon','Dragon');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Badger','Badger');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Lizzard','Lizzard');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_BlackBear','Black Bear');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Llama','Llama');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Yak','Yak');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Cow','Cow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Emu','Emu');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Spider','Spider');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Beetle','Beetle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_BeetleEgg','Beetle egg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Duck','Duck');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Goose','Goose');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Shepherd','Shepherd Dog');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_CatTabby','Tabby Cat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_CatBlack','Black Cat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Porcupine','Porcupine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Fox','Fox');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Wolf','Wolf');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Stag','Stag');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Roe','Roe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Goat','Goat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Snake','Snake');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Squirrel','Squirrel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_GreyFish','Grey Fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_GreenFish','Green Fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_CrystalSnake','Crystal Snake');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_ZygYoung','Young Zyg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_ZygYouth','Zyg Youth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_ZygAdult','Adult Zyg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_ZygSenior','Senior Zyg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Mining','Mining');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Mining','Miner');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Masonry','Masonry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Masonry','Mason');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Stonecarving','Stonecarving');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Stonecarving','Stonecarver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Woodcutting','Woodcutting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Woodcutting','Woodcutter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Carpentry','Carpentry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Carpentry','Carpenter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Woodcarving','Woodcarving');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Woodcarving','Woodcarver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Smelting','Smelting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Smelting','Smelter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Blacksmithing','Blacksmithing');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Blacksmithing','Blacksmith');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Metalworking','Metalworking');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Metalworking','Metalworker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_WeaponCrafting','Weapon Crafting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_WeaponCrafting','Weaponsmith');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_ArmorCrafting','Armor Crafting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_ArmorCrafting','Armorer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Gemcutting','Gemcutting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Gemcutting','Gemcutter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_JewelryMaking','Jewelry Making');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_JewelryMaking','Jeweler');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Weaving','Weaving');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Weaving','Weaver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Tailoring','Tailoring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Tailoring','Tailor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Dyeing','Dyeing');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Dyeing','Dyer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Pottery','Pottery');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Pottery','Potter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Leatherworking','Leatherworking');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Leatherworking','Leatherworker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Tinkering','Tinkering');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Tinkering','Tinkerer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Machining','Machining');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Machining','Machinist');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Engineering','Engineering');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Engineering','Engineer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Mechanic','Mechanic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Mechanic','Mechanic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_AnimalHusbandry','Animal Husbandry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_AnimalHusbandry','Rancher');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Butchery','Butchery');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Butchery','Butcher');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Horticulture','Horticulture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Horticulture','Gardener');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Farming','Farming');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Farming','Farmer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Cooking','Cooking');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Cooking','Chef');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Brewing','Brewing');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Brewing','Brewer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Construction','Construction');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Construction','Builder');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Hauling','Hauling');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Hauling','Hauler');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_NaturalAttack','Fighting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_NaturalAttack','Fighter');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Brawling','Brawling');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Brawling','Brawler');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Sword','Sword');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Sword','Swords');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Axe','Axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Axe','Axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Hammer','Hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Hammer','Hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Dodge','Dodge');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Dogde','Dodger');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Shield','Shield');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Shield','Shielder');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Armor','Armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Armor','Knight');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Discipline','Discipline');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Discipline','Discipline');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Crossbow','Crossbow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Crossbow','Crossbow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Gun','Gun');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Gun','Gun');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Medic','Medic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Medic','Medic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Caretaking','Caretaking');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Caretaking','Caretaker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Bonecarving','Bonecarving');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Bonecarving','Bonecarver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Prospecting','Prospecting');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Prospecting','Prospector');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Fishing','Fishing');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_Fishing','Fisher');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_MagicNature','Nature');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_MagicNature','Nature mage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_MagicGeomancy','Geomancy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillTitle_MagicGeomancy','Geomancer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_Hungry','hungry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_VeryHungry','very hungry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_Starving','starving');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_StarvedToDeath','dead');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_Thirsty','thirsty');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_VeryThirsty','very thirsty');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_Dehydrated','dehydrated');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_DiedFromThirst','dead');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_Sleepy','sleepy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_VerySleepy','very sleepy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StateName_DeadTired','dead tired');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Bad','bad');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Acceptable','acceptable');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Average','average');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Good','good');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Excellent','excellent');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Outstanding','outstanding');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$QualityName_Legendary','legendary');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SliverFromStone','metal sliver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sliver','metal sliver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SliverFromDirt','metal sliver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Military','Military');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryPositionPerk_Highlander','Highlander');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryPositionPerk_Frenzy','Frenzy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryPositionPerk_WayOfGnome','Way of the gnome');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryPositionPerk_Marksman','Marksgnome');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryPositionPerk_Scout','Scout');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryPositionPerk_Guard','Guard');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryFormationPerk_EyesOpen','Keep your eyes open');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryFormationPerk_ShieldWall','Shieldwall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryFormationPerk_MeleeOffense','The best defense...');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MilitaryFormationPerk_FiringSquad','Firing squad');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Leatherworker','Leatherworker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Weaponsmith','Weaponsmith');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Armorer','Armorer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RawHide','raw hide');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherArmorPanel','leather panel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherHelm','leather helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherCuirass','leather cuirass');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherPants','leather pants');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherBoot','leather boot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherBracer','leather bracer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeatherGlove','leather glove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_EmuLeather','emu');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_CowLeather','cow');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_YakLeather','yak');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ChainBoots','chainmail boots');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ChainBracers','chainmail bracers');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ChainGloves','chainmail gloves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ChainHelm','chainmail helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ChainPants','chainmail pants');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ChainShirt','chainmail shirt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PlateBoots','plate boots');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PlateChest','plate chest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PlateGloves','plate gloves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PlateGreaves','plate greaves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PlateHelm','plate helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PlatePauldrons','plate pauldrons');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HeavyPlateBoots','heavy plate boots');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HeavyPlateChest','heavy plate chest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HeavyPlateGloves','heavy plate gloves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HeavyPlateGreaves','heavy plate greaves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HeavyPlateHelm','heavy plate helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HeavyPlatePauldrons','heavy plate pauldrons');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ArmorPlate','armor plate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ChainBoot','chainmail boot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ChainBracer','chainmail bracer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ChainGlove','chainmail glove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ChainHelm','chainmail helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ChainPants','chainmail pants');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ChainShirt','chainmail shirt');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Corpse','corpse');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_CrystalMushroom','crystal mushroom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FishMeat','fish meat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HeavyPlateBoot','heavy plate boot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HeavyPlateChest','heavy plate chest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HeavyPlateGlove','heavy plate glove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HeavyPlateGreaves','heavy plate greaves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HeavyPlateHelm','heavy plate helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HeavyPlatePauldron','heavy plate pauldron');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlateBoot','plate boot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlateChest','plate chest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlateGlove','plate glove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlateGreaves','plate greaves');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlateHelm','plate helm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PlatePauldron','plate pauldron');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Tea','tea');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WoodTub','wood tub');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Chainmail','chainmail');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Plate','plate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_HeavyPlate','heavy plate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sword','sword');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SwordBase','sword base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SwordBlade','sword blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Weapons','Weapons');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_WeaponsComponents','components');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_WeaponsMetal','metal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Unarmed','Unarmed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Melee','Melee');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Ranged','Ranged');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Thrown','Thrown');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_Block','Block');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_MeleeTraining','training ground');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Acorn','acorn');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Parts','parts');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Lights','lights');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_BoneArmor','bone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_NonAlcoholic','non alcoholic');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Cooked','cooked');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Meat','meat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Other','other');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Leather','leather');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Armor','Armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Jewelry','Jewelry');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Materials','materials');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickaxeHeadMetal','pickaxe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GearBox','gear box');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GearBoxBase','gear box  base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GearBoxFrame','gear box frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SteamEngine','steam engine');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Gear','gear');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Rod','rod');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Spring','spring');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Axle','axle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_VerticalAxle','vertical axle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Containers','containers');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Furniture','furniture');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Mechanism','mechanism');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$FarmUtils','farm utilities');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CategoryName_Utility','Utility');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Mechanism','mechanisms');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Cylinder','cylinder');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_DyedBolt','dye bolt of cloth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$Hydraulics','hydraulics');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Pipe','pipe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PipeCenter','pipe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PipeExit','pipe exit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Pump','pump');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Hydraulics','hydraulics');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Lever','lever');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeverBase','lever base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_LeverHandle','lever handle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Engineer','engineer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_MachineShop','machine shop');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Wrench','wrench');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Spike','spike');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Screw','screw');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_MechanismBase','mechanism base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Gearbox','gear box');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Handcrank','handcrank');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_TrapBase','trap base');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SpikeTrap','spike trap');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_MechanicalWall','mechanical wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WindmillBlade','windmill blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PressurePlate','pressure plate');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Hatch','hatch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Automaton','automaton');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Automaton','automaton maker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Automaton','automaton');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AutomatonHead','automaton head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AutomatonTorso','automaton torso');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AutomatonArm','automaton arm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AutomatonLeg','automaton leg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AutomatonCoreMark1','automaton core mark 1');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_AutomatonCoreMark2','automaton core mark 2');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Automaton','automaton');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AutomatonHead','automaton head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AutomatonTorso','automaton torso');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AutomatonLeg','automaton leg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AutomatonArm','automaton arm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AutomatonCoreMark1','automaton core mark 1');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_AutomatonCoreMark2','automaton core mark 2');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$NeedName_Fuel','Fuel');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_Windmill','windmill');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Flour','flour');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flour','flour');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FlourKitchen','flour');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BoneBedFrame','bone bed frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BoneBed','bone bed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BoneBedFrame','bone bed frame');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Continue','Continue');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_NewGame','New Game');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Resume','Resume');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Join','Join');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Mods','Mods');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Save','Save');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Load','Load');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Exit','Exit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_MainMenu','Main Menu');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Settings','Settings');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_SettingsVideo','Video');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_SettingsAudio','Audio');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_SettingsBindings','Key Bindings');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_SettingsGame','Game');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Random','Random');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_New','New');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Delete','Delete');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Back','Back');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_StartGame','Start Game');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_KingdomName','Kingdom Name');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Seed','Seed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Size','Size');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_zLevels','z-Levels');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Ground','Ground');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Flatness','Flatness');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Presets','Presets');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_AddItem','Add Item');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_AddAnimals','Add Animals');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Remove','Remove');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_FaunaFlora','Fauna Flora');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_TreeDensity','Tree Density');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_PlantDensity','Plant Density');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_WildAnimals','Wild Animals');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_MaxPerType','Max per type');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_StartingZone','Starting Zone');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_AllowedTrees','Allowed Trees');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_AllowedPlants','Allowed Wild Plants');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Enemies','Enemies');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_PeacefulMode','No enemies (peaceful mode)');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Gnomes','Gnomes');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_NewPreset','New Preset');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_SavePreset','Save Preset');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_DeletePreset','Delete Preset');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_AllowedAnimals','Allowed Animals');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Embark','Embark');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_World','World');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BirchTree','birch tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Kingdom','Kingdom');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Stocks','Stocks');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Population','Population');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Military','Military');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Events','Events');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Overview','Overview');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Technology','Technology');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_TechTree','Tech tree');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Skills','Skills');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Schedule','Schedule');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Name','Name');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Profession','Profession');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Schedule_none','none');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Schedule_eat','eat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Schedule_sleep','sleep');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Schedule_training','training');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Threats','Threats');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Squads','Squads');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Formations','Formations');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Positions','Positions');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Uniforms','Uniforms');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Perk','Perk');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Uniform','Uniform');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Leader','Leader');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_MaintainDistance','Maintain distance');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_RetreatBleeding','Retreat if bleeding');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_AvoidEnemies','Avoid enemies');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Formation','Formation');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_HeadArmor','head armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_ChestArmor','chest armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_ArmArmor','arm armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_HandArmor','hand armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_LegArmor','leg armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_FootArmor','foot armor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_LeftHandHeld','held in left hand');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$UniformSlot_RightHandHeld','held in right hand');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Neighbors','Neighbors');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Missions','Missions');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Action_Improve','Improve relationship');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Action_Insult','Insult');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Action_InviteTrader','Invite trader');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Action_InviteAmbassador','Invite ambassador (not implemented yet)');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GUI_Action_Select','Select Action');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_LeatherPants','leather pants');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Shed','shed');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$StockOverlay','Overlay');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SelectCategory','select category');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SelectGroup','select group');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SelectItem','select item');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SelectMaterial','select material');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_WasteDisposal','waste disposal');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BurnFishBone','burn fish bones');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BurnBone','burn bones');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BurnStraw','burn straw');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BurnSeeds','burn seeds');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Farm','farm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BladeTrap','blade trap');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Hay','hay');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower1','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower2','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower3','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower4','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower5','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower6','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower7','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Flower8','flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower1','orange flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower2','yellow flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower3','white flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower4','pink flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower5','red flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower6','purple flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower7','blue flower');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Flower8','yellow flower 2');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Honey','honey');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_Bee','bee');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HandAxeHead','hand axe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HandAxe','hand axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HammerHead','hammer head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Hammer','hammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ClaymoreBlade','claymore blade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Claymore','claymore');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BattleAxeHead','battle axe head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BattleAxe','battle axe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WarhammerHead','warhammer head');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Warhammer','warhammer');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_AlarmBell','alarm bells');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$JobName_SoundAlarm','sound the alarm');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BeeHive','bee hive');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_WallTorch','wall torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Chest','chest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Chest','chest');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Bookshelf','book shelf');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Bookshelf','book shelf');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_BigTorch','big torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Brazier','brazier');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_BigTorch','big torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Brazier','brazier');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Sabretooth','Sabretooth tiger');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Mammoth','Woolly Mammoth');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_BearLeather','bear');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Backpack','backpack');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Quiver','quiver');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Backpack','backpack');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_WolfLeather','wolf');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_StagLeather','stag');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_GlassMaker','glass maker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$WorkshopName_GlassFurnace','glass furnace');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$SkillName_GlassMaking','Glass Making');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GlassIngot','ingot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_GlassIngot','glass ingot');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_RoughGlassGem','rough gem');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_RoughGlassGem','rough glass gem');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_MosaicTile','mosaic tile');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MosaicTile','mosaic tile');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SoilStairs','soil stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_StoneStairs','stone stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SoilRamp','soil ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_StoneRamp','stone ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_Scaffold','scaffold');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_Palisade','palisade');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_StoneWall','stone wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SoilWallFloor','soil wall and floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_StoneWallFloor','stone wall and floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_PlankWallFloor','plank wall and floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BlockWall','block wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BrickWall','brick wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_PlankWall','plank wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_PlankFloor','plank floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SoilWall','soil wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_LogWall','log wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_ThatchWall','thatch wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_ThatchFloor','thatch floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_ThatchRamp','thatch ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_Roof','roof');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SoilCornerRamp','soil corner ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_StoneCornerRamp','stone corner ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_ThatchCornerRamp','thatch corner ramp');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BlockFloor','block floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_StoneFloor','stone floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BrickFloor','brick floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SoilFloor','soil floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_LogFloor','log floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyWall1','fancy wall 1');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyWall2','fancy wall 2');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyWall3','fancy wall 3');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyWall4','fancy wall 4');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyWall5','fancy wall 5');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyWall6','fancy wall 6');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyFloor1','fancy floor 1');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyFloor2','fancy floor 2');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyFloor3','fancy floor 3');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyFloor4','fancy floor 4');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyFloor5','fancy floor 5');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_FancyFloor6','fancy floor 6');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BlockFence','block fence');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_CobbleStoneFence','cobble stone fence');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_WoodFence','wood fence');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_VerticalAxle','vertical axle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_Pipe','pipe');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_PipeExit','pipe exit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BoneWall','bone wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_SkullWall','skull wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BoneFloor','bone floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_WallTorch','wall torch');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_PlankStairs','plank stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_BlockStairs','block stairs');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_MosaicWall','mosaic wall');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ConstructionName_MosaicFloor','mosaic floor');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Sand','soil');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$GroupName_Clay','soil');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_any (same)','any (same)');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_Goblin','Goblin');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_MantSoldier','Mant soldier');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_MantWorker','Mant worker');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CreatureName_MantQueen','Mant queen');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Cider','cider');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Vinegar','vinegar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Sugar','sugar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_DropCandy','drop candy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_ShepherdsPie','shepherds pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_Biscuit','biscuit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PickledFruit','pickled fruit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FruitPreserve','fruit preserve');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SmokedMeat','smoked meat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SmokedSausage','smoked sausage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FruitBread','fruit bread');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FreshCheese','fresh cheese');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_HardCheese','hard cheese');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_MeatPie','meat pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PickledVegetable','pickled vegetable');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_PickledEgg','pickled egg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_VegetablePreserve','vegetable preserve');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SmokedBird','smoked bird');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_SmokedFish','smoked fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FlatBread','flat bread');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FruitPie','fruit pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_VeggiePie','veggie pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_FineMeatPie','fine meat pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Cider','cider');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Vinegar','vinegar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Sugar','sugar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_DropCandy','drop candy');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_ShepherdsPie','shepherds pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_Biscuit','biscuit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickledFruit','pickled fruit');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FruitPreserve','fruit preserve');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SmokedMeat','smoked meat');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SmokedSausage','smoked sausage');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FruitBread','fruit bread');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FreshCheese','fresh cheese');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_HardCheese','hard cheese');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_MeatPie','meat pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickledVegetable','pickled vegetable');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_PickledEgg','pickled egg');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_VegetablePreserve','vegetable preserve');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SmokedBird','smoked bird');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_SmokedFish','smoked fish');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FlatBread','flat bread');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FruitPie','fruit pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_VeggiePie','veggie pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_FineMeatPie','fine meat pie');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GlassJar','jar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$ItemName_GlassBottle','bottle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_GlassJar','jar');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$CraftName_GlassBottle','bottle');\r\nINSERT INTO \"Translation\" (\"ID\",\"Text\") VALUES ('$MaterialName_GlowShroom','mushroom');\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('WoodTrader',NULL,'RawWood','Pine',100,0,NULL,10.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('WoodTrader',NULL,'RawWood','AppleWood',100,0,NULL,10.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('WoodTrader',NULL,'RawWood','OrangeWood',100,0,NULL,10.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('WoodTrader',NULL,'RawWood','Birch',100,0,NULL,10.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('OreTrader',NULL,'RawOre','Copper',50,0,NULL,60.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('OreTrader',NULL,'RawOre','Tin',59,0,NULL,60.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('OreTrader',NULL,'RawOre','Iron',20,0,NULL,100.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('OreTrader',NULL,'RawOre','Lead',20,0,NULL,150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('OreTrader',NULL,'RawOre','Silver',10,0,NULL,500.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('OreTrader',NULL,'RawOre','Gold',10,0,NULL,750.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Male','Cow',NULL,2,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Female','Cow',NULL,2,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Male','Yak',NULL,2,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Female','Yak',NULL,2,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Male','Chicken',NULL,5,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Female','Chicken',NULL,5,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Male','Rabbit',NULL,2,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('AnimalTrader','Female','Rabbit',NULL,2,0,'Animal',150.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Strawberry',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Carrot',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Onion',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Potato',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Cabbage',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Asparagus',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Broccoli',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Cauliflower',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Cucumber',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Garlic',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Parsnip',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Radish',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Turnip',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Lettuce',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Melon',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Sugarbeet',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Pumpkin',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Peas',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','BeetRoot',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Wheat',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Barley',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Oat',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Millet',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Cotton',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Tea',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Tobacco',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Pineapple',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Corn',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Leek',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Beans',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Blackberry',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Bottlegourd',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Artichoke',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Grape',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Tomato',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Capsicum',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','Woad',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('SeedTrader',NULL,'Seed','DyersWeed',50,0,NULL,20.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('WoodTrader',NULL,'RawWood','Oak',100,0,NULL,10.0);\r\nINSERT INTO \"Traders_Items\" (\"ID\",\"Gender\",\"Item\",\"Material\",\"Max_\",\"Min_\",\"Type\",\"Value_\") VALUES ('WoodTrader',NULL,'RawWood','Willow',100,0,NULL,10.0);\r\nINSERT INTO \"Traders\" (\"ID\") VALUES ('WoodTrader');\r\nINSERT INTO \"Traders\" (\"ID\") VALUES ('OreTrader');\r\nINSERT INTO \"Traders\" (\"ID\") VALUES ('AnimalTrader');\r\nINSERT INTO \"Traders\" (\"ID\") VALUES ('SeedTrader');\r\nINSERT INTO \"Time\" (\"ID\",\"Value_\") VALUES ('TicksPerMinute',10.0);\r\nINSERT INTO \"Time\" (\"ID\",\"Value_\") VALUES ('MinutesPerHour',60.0);\r\nINSERT INTO \"Time\" (\"ID\",\"Value_\") VALUES ('HoursPerDay',24.0);\r\nINSERT INTO \"Time\" (\"ID\",\"Value_\") VALUES ('MillisecondsSlow',25.0);\r\nINSERT INTO \"Time\" (\"ID\",\"Value_\") VALUES ('MillisecondsFast',5.0);\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Air','EmptyFloor',1000.0,0.0,'EmptyWall','Air','EmptyWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Dirt','RoughFloor',-1.0,-2.0,'RoughSoilWallShort','Soil','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Sand','RoughFloor',-3.0,-4.0,'RoughSoilWallShort','Soil','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Clay','RoughFloor',-5.0,-6.0,'RoughClayWallShort','Clay','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Sandstone','RoughFloor',-7.0,-14.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Marble','RoughFloor',-15.0,-26.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Bauxite','RoughFloor',-27.0,-42.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('LapisLazuli','RoughFloor',-43.0,-59.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Serpentine','RoughFloor',-60.0,-74.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Granite','RoughFloor',-75.0,-88.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"TerrainMaterials\" (\"ID\",\"FloorSprite\",\"Highest\",\"Lowest\",\"ShortWallSprite\",\"Type\",\"WallSprite\") VALUES ('Basalt','RoughFloor',-89.0,-1000.0,'RoughStoneWallShort','Stone','RoughWall');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechWood');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechStone');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechMetal');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechEngineer');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechCloth');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechLeather');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechFood');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechMilitary');\r\nINSERT INTO \"Tech\" (\"ID\") VALUES ('TechMagic');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSpring','GrassRamp_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSpring','GrassRamp_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSpring','GrassRamp_Spring_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSpring','GrassRamp_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSummer','GrassRamp_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSummer','GrassRamp_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSummer','GrassRamp_Summer_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampSummer','GrassRamp_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampAutumn','GrassRamp_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampAutumn','GrassRamp_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampAutumn','GrassRamp_Autumn_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampAutumn','GrassRamp_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampWinter','GrassRamp_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampWinter','GrassRamp_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampWinter','GrassRamp_Winter_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampWinter','GrassRamp_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSpring','GrassRampTop_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSpring','GrassRampTop_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSpring','GrassRampTop_Spring_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSpring','GrassRampTop_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSummer','GrassRampTop_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSummer','GrassRampTop_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSummer','GrassRampTop_Summer_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopSummer','GrassRampTop_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopAutumn','GrassRampTop_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopAutumn','GrassRampTop_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopAutumn','GrassRampTop_Autumn_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopAutumn','GrassRampTop_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopWinter','GrassRampTop_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopWinter','GrassRampTop_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopWinter','GrassRampTop_Winter_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassRampTopWinter','GrassRampTop_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSpring','GrassOuterCornerRamp_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSpring','GrassOuterCornerRamp_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSpring','EmptyWall','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSpring','GrassOuterCornerRamp_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSummer','GrassOuterCornerRamp_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSummer','GrassOuterCornerRamp_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSummer','EmptyWall','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampSummer','GrassOuterCornerRamp_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampAutumn','GrassOuterCornerRamp_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampAutumn','GrassOuterCornerRamp_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampAutumn','EmptyWall','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampAutumn','GrassOuterCornerRamp_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampWinter','GrassOuterCornerRamp_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampWinter','GrassOuterCornerRamp_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampWinter','EmptyWall','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassOuterCornerRampWinter','GrassOuterCornerRamp_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSpring','GrassCornerRamp_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSpring','GrassCornerRamp_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSpring','GrassCornerRamp_Spring_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSpring','GrassCornerRamp_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSummer','GrassCornerRamp_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSummer','GrassCornerRamp_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSummer','GrassCornerRamp_Summer_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampSummer','GrassCornerRamp_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampAutumn','GrassCornerRamp_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampAutumn','GrassCornerRamp_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampAutumn','GrassCornerRamp_Autumn_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampAutumn','GrassCornerRamp_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampWinter','GrassCornerRamp_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampWinter','GrassCornerRamp_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampWinter','GrassCornerRamp_Winter_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampWinter','GrassCornerRamp_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSpring','GrassCornerRampTop_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSpring','GrassCornerRampTop_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSpring','GrassCornerRampTop_Spring_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSpring','GrassCornerRampTop_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSummer','GrassCornerRampTop_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSummer','GrassCornerRampTop_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSummer','GrassCornerRampTop_Summer_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopSummer','GrassCornerRampTop_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopAutumn','GrassCornerRampTop_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopAutumn','GrassCornerRampTop_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopAutumn','GrassCornerRampTop_Autumn_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopAutumn','GrassCornerRampTop_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopWinter','GrassCornerRampTop_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopWinter','GrassCornerRampTop_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopWinter','GrassCornerRampTop_Winter_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassCornerRampTopWinter','GrassCornerRampTop_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSpring','GrassURamp_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSpring','GrassURamp_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSpring','GrassURamp_Spring_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSpring','GrassURamp_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSummer','GrassURamp_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSummer','GrassURamp_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSummer','GrassURamp_Summer_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampSummer','GrassURamp_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampAutumn','GrassURamp_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampAutumn','GrassURamp_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampAutumn','GrassURamp_Autumn_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampAutumn','GrassURamp_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampWinter','GrassURamp_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampWinter','GrassURamp_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampWinter','GrassURamp_Winter_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampWinter','GrassURamp_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSpring','GrassURampTop_Spring_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSpring','GrassURampTop_Spring_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSpring','GrassURampTop_Spring_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSpring','GrassURampTop_Spring_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSummer','GrassURampTop_Summer_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSummer','GrassURampTop_Summer_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSummer','GrassURampTop_Summer_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopSummer','GrassURampTop_Summer_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopAutumn','GrassURampTop_Autumn_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopAutumn','GrassURampTop_Autumn_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopAutumn','GrassURampTop_Autumn_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopAutumn','GrassURampTop_Autumn_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopWinter','GrassURampTop_Winter_FL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopWinter','GrassURampTop_Winter_FR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopWinter','GrassURampTop_Winter_BL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('GrassURampTopWinter','GrassURampTop_Winter_BR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSpring','SoilRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSpring','SoilRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSpring','SoilRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSpring','SoilRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSummer','SoilRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSummer','SoilRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSummer','SoilRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampSummer','SoilRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampAutumn','SoilRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampAutumn','SoilRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampAutumn','SoilRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampAutumn','SoilRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampWinter','SoilRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampWinter','SoilRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampWinter','SoilRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampWinter','SoilRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSpring','SoilRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSpring','SoilRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSpring','SoilRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSpring','SoilRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSummer','SoilRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSummer','SoilRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSummer','SoilRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopSummer','SoilRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopAutumn','SoilRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopAutumn','SoilRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopAutumn','SoilRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopAutumn','SoilRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopWinter','SoilRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopWinter','SoilRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopWinter','SoilRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilRampTopWinter','SoilRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSpring','SoilCornerRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSpring','SoilCornerRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSpring','SoilCornerRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSpring','SoilCornerRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSummer','SoilCornerRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSummer','SoilCornerRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSummer','SoilCornerRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampSummer','SoilCornerRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampAutumn','SoilCornerRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampAutumn','SoilCornerRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampAutumn','SoilCornerRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampAutumn','SoilCornerRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampWinter','SoilCornerRampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampWinter','SoilCornerRampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampWinter','SoilCornerRampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampWinter','SoilCornerRampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSpring','SoilCornerRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSpring','SoilCornerRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSpring','SoilCornerRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSpring','SoilCornerRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSummer','SoilCornerRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSummer','SoilCornerRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSummer','SoilCornerRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopSummer','SoilCornerRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopAutumn','SoilCornerRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopAutumn','SoilCornerRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopAutumn','SoilCornerRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopAutumn','SoilCornerRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopWinter','SoilCornerRampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopWinter','SoilCornerRampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopWinter','SoilCornerRampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilCornerRampTopWinter','SoilCornerRampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSpring','SoilURampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSpring','SoilURampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSpring','SoilURampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSpring','SoilURampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSummer','SoilURampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSummer','SoilURampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSummer','SoilURampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampSummer','SoilURampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampAutumn','SoilURampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampAutumn','SoilURampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampAutumn','SoilURampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampAutumn','SoilURampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampWinter','SoilURampFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampWinter','SoilURampFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampWinter','SoilURampBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampWinter','SoilURampBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSpring','SoilURampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSpring','SoilURampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSpring','SoilURampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSpring','SoilURampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSummer','SoilURampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSummer','SoilURampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSummer','SoilURampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopSummer','SoilURampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopAutumn','SoilURampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopAutumn','SoilURampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopAutumn','SoilURampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopAutumn','SoilURampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopWinter','SoilURampTopFL','FL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopWinter','SoilURampTopFR','FR');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopWinter','SoilURampTopBL','BL');\r\nINSERT INTO \"Sprites_Seasons_Rotations\" (\"ID\",\"BaseSprite\",\"Rotation\") VALUES ('SoilURampTopWinter','SoilURampTopBR','BR');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass1','Grass_1_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass1','Grass_1_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass1','Grass_1_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass1','Grass_1_10','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass2','Grass_2_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass2','Grass_2_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass2','Grass_2_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass2','Grass_2_10','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass3','Grass_3_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass3','Grass_3_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass3','Grass_3_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass3','Grass_3_10','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass4','Grass_4_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass4','Grass_4_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass4','Grass_4_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass4','Grass_4_10','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass5','Grass_5_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass5','Grass_5_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass5','Grass_5_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass5','Grass_5_10','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass6','Grass_6_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass6','Grass_6_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass6','Grass_6_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('Grass6','Grass_6_10','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower0','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower0','RedFlower_0','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower0','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower0','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower1','RedFlower_1','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower1','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower2','RedFlower_2','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower2','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower3','RedFlower_3','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower3','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower4','RedFlower_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower4','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower5','RedFlower_5','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower5','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower6','RedFlower_6','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower6','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower7','RedFlower_7','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower7','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower8','RedFlower_8','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower8','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RRedFlower8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower0','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower0','BlueFlower_0','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower0','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower0','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower1','BlueFlower_1','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower1','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower2','BlueFlower_2','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower2','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower3','BlueFlower_3','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower3','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower4','BlueFlower_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower4','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower5','BlueFlower_5','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower5','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower6','BlueFlower_6','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower6','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower7','BlueFlower_7','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower7','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower8','BlueFlower_8','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower8','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RBlueFlower8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower0','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower0','YellowFlower_0','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower0','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower0','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower1','YellowFlower_1','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower1','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower2','YellowFlower_2','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower2','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower3','YellowFlower_3','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower3','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower4','YellowFlower_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower4','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower5','YellowFlower_5','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower5','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower6','YellowFlower_6','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower6','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower7','YellowFlower_7','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower7','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower8','YellowFlower_8','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower8','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowFlower8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower0','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower0','PurpleFlower_0','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower0','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower0','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower1','PurpleFlower_1','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower1','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower2','PurpleFlower_2','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower2','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower3','PurpleFlower_3','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower3','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower4','PurpleFlower_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower4','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower5','PurpleFlower_5','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower5','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower6','PurpleFlower_6','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower6','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower7','PurpleFlower_7','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower7','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower8','PurpleFlower_8','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower8','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RPurpleFlower8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower0','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower0','OrangeFlower_0','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower0','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower0','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower1','OrangeFlower_1','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower1','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower2','OrangeFlower_2','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower2','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower3','OrangeFlower_3','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower3','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower4','OrangeFlower_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower4','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower5','OrangeFlower_5','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower5','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower6','OrangeFlower_6','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower6','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower7','OrangeFlower_7','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower7','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower8','OrangeFlower_8','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower8','empty','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeFlower8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom0','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom0','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom0','WhiteMushroom_0','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom0','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom1','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom1','WhiteMushroom_1','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom2','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom2','WhiteMushroom_2','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom3','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom3','WhiteMushroom_3','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom4','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom4','WhiteMushroom_4','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom5','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom5','WhiteMushroom_5','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom6','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom6','WhiteMushroom_6','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom7','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom7','WhiteMushroom_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom8','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom8','WhiteMushroom_8','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RWhiteMushroom8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom1','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom1','YellowMushroom_1','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom2','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom2','YellowMushroom_2','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom3','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom3','YellowMushroom_3','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom4','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom4','YellowMushroom_4','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom5','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom5','YellowMushroom_5','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom6','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom6','YellowMushroom_6','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom7','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom7','YellowMushroom_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom8','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom8','YellowMushroom_8','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RYellowMushroom8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom1','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom1','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom1','OrangeMushroom_1','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom1','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom2','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom2','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom2','OrangeMushroom_2','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom2','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom3','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom3','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom3','OrangeMushroom_3','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom3','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom4','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom4','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom4','OrangeMushroom_4','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom4','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom5','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom5','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom5','OrangeMushroom_5','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom5','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom6','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom6','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom6','OrangeMushroom_6','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom6','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom7','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom7','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom7','OrangeMushroom_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom7','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom8','empty','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom8','empty','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom8','OrangeMushroom_8','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('ROrangeMushroom8','empty','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone0','Stone_0','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone0','Stone_0','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone0','Stone_0','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone0','Stone_Snow_0','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone1','Stone_1','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone1','Stone_1','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone1','Stone_1','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone1','Stone_Snow_1','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone2','Stone_2','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone2','Stone_2','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone2','Stone_2','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone2','Stone_Snow_2','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone3','Stone_3','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone3','Stone_3','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone3','Stone_3','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone3','Stone_Snow_3','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone4','Stone_4','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone4','Stone_4','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone4','Stone_4','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone4','Stone_Snow_4','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone5','Stone_5','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone5','Stone_5','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone5','Stone_5','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone5','Stone_Snow_5','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone6','Stone_6','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone6','Stone_6','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone6','Stone_6','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone6','Stone_Snow_6','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone7','Stone_7','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone7','Stone_7','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone7','Stone_7','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone7','Stone_Snow_7','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone8','Stone_8','Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone8','Stone_8','Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone8','Stone_8','Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('RStone8','Stone_Snow_8','Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRampTop',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRampTop',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRampTop',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassRampTop',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassOuterCornerRamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassOuterCornerRamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassOuterCornerRamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassOuterCornerRamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRampTop',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRampTop',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRampTop',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassCornerRampTop',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURampTop',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURampTop',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURampTop',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('GrassURampTop',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRampTop',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRampTop',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRampTop',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilRampTop',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRampTop',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRampTop',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRampTop',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilCornerRampTop',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURamp',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURamp',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURamp',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURamp',NULL,'Winter');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURampTop',NULL,'Spring');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURampTop',NULL,'Summer');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURampTop',NULL,'Autumn');\r\nINSERT INTO \"Sprites_Seasons\" (\"ID\",\"BaseSprite\",\"Season\") VALUES ('SoilURampTop',NULL,'Winter');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedFrame','WoodBedFrameFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedFrame','WoodBedFrameFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedFrame','WoodBedFrameBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedFrame','WoodBedFrameBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedSheets','MattressFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedSheets','MattressFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedSheets','MattressBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodBedSheets','MattressBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedFrame','FancyWoodBedFrameFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedFrame','FancyWoodBedFrameFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedFrame','FancyWoodBedFrameBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedFrame','FancyWoodBedFrameBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedSheets','FancyWoodBedSheetsFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedSheets','FancyWoodBedSheetsFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedSheets','FancyWoodBedSheetsBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FancyWoodBedSheets','FancyWoodBedSheetsBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodChair','WoodChairFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodChair','WoodChairFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodChair','WoodChairBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodChair','WoodChairBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneChair','StoneChairFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneChair','StoneChairFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneChair','StoneChairBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneChair','StoneChairBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneChair','BoneChairFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneChair','BoneChairFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneChair','BoneChairBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneChair','BoneChairBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Statue','StoneStatueFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Statue','StoneStatueFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Statue','StoneStatueBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Statue','StoneStatueBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RawWood','RawWood',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RawWood','RawWood','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RawWood','RawWood',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RawWood','RawWood','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallBase','MarketStallBase',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallBase','MarketStallBase','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallBase','MarketStallBase',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallBase','MarketStallBase','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallTop','MarketStallTop',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallTop','MarketStallTop','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallTop','MarketStallTop',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MarketStallTop','MarketStallTop','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStandTools','CarpenterStandToolsFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStandTools','CarpenterStandToolsFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStandTools','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStandTools','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStand','CarpenterStandFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStand','CarpenterStandFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStand','CarpenterStandBR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CarpenterStand','CarpenterStandBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TableSaw','TableSaw',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TableSaw','TableSaw','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TableSaw','TableSaw',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TableSaw','TableSaw','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTable','SawTable',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTable','SawTable','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTable','SawTable',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTable','SawTable','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Workbench','WorkbenchFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Workbench','WorkbenchFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Workbench','WorkbenchBR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Workbench','WorkbenchBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AxeBench','AxeBenchFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AxeBench','AxeBenchFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AxeBench','AxeBenchBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AxeBench','AxeBenchBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Keg','KegFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Keg','KegFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Keg','KegBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Keg','KegBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TanningRack','TanningRackFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TanningRack','TanningRackFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TanningRack','TanningRackBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TanningRack','TanningRackBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodPile',NULL,NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodPile',NULL,'FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodPile',NULL,NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodPile',NULL,'FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneBlockPile','StoneBlockPileFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneBlockPile','StoneBlockPileFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneBlockPile','StoneBlockPileBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneBlockPile','StoneBlockPileBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableLeft','SawTableLeft',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableLeft','SawTableLeft','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableLeft','SawTableLeft2',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableLeft','SawTableLeft2','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableRight','SawTableRight',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableRight','SawTableRight','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableRight','SawTableRight2',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableRight','SawTableRight2','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableBlade','SawTableBladeFL',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableBlade','SawTableBladeFL','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableBlade','SawTableBladeBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawTableBlade','SawTableBladeBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawHorse','SawHorse',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawHorse','SawHorse','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawHorse','SawHorse',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SawHorse','SawHorse','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShearsTableTop','ShearsTableTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShearsTableTop','ShearsTableTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShearsTableTop','ShearsTableTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShearsTableTop','ShearsTableTopBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClothRollTableTop','ClothRollTableTop',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClothRollTableTop','ClothRollTableTop','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClothRollTableTop','ClothRollTableTop',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClothRollTableTop','ClothRollTableTop','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mold','MoldFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mold','MoldFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mold','MoldBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mold','MoldBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MoldTop','MoldTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MoldTop','MoldTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MoldTop','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MoldTop','EmptyWall','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Bellows','BellowsFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Bellows','BellowsFL','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Bellows','BellowsBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Bellows','BellowsBR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BellowsNozzle','BellowsNozzleFR',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BellowsNozzle','BellowsNozzleFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BellowsNozzle','BellowsNozzleBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BellowsNozzle','BellowsNozzleBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Furnace','FurnaceFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Furnace','FurnaceFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Furnace','FurnaceBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Furnace','FurnaceBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FurnaceFlame','FurnaceFlameFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FurnaceFlame','FurnaceFlameFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FurnaceFlame','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FurnaceFlame','EmptyWall','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Kiln','KilnFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Kiln','KilnFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Kiln','KilnBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Kiln','KilnBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KilnFlame','KilnFlameFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KilnFlame','KilnFlameFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KilnFlame','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KilnFlame','EmptyWall','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Anvil','AnvilFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Anvil','AnvilFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Anvil','AnvilBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Anvil','AnvilBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Trough','Trough','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Trough','Trough',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Trough','Trough','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Trough','Trough',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shed','ShedFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shed','ShedFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shed','ShedBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shed','ShedBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MetalBarPile','MetalBarPile','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MetalBarPile','MetalBarPile',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MetalBarPile','MetalBarPile',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MetalBarPile','MetalBarPile','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreenFish','GreenFish',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreenFish','GreenFish','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreenFish','GreenFishBack',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreenFish','GreenFishBack','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Panda','Panda',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Panda','Panda','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Panda','PandaBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Panda','PandaBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rabbit','Rabbit',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rabbit','Rabbit','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rabbit','RabbitBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rabbit','RabbitBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RabbitYoung','RabbitYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RabbitYoung','RabbitYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RabbitYoung','RabbitYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('RabbitYoung','RabbitYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chicken','Chicken',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chicken','Chicken','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chicken','ChickenBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chicken','ChickenBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChickenYoung','ChickenYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChickenYoung','ChickenYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChickenYoung','ChickenYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChickenYoung','ChickenYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigPink','PigPink',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigPink','PigPink','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigPink','PigPinkBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigPink','PigPinkBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYoung','PigYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYoung','PigYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYoung','PigYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYoung','PigYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYellow','PigYellow',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYellow','PigYellow','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYellow','PigYellowBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PigYellow','PigYellowBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Sheep','Sheep',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Sheep','Sheep','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Sheep','SheepBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Sheep','SheepBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYoung','SheepYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYoung','SheepYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYoung','SheepYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYoung','SheepYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Woodlouse','Woodlouse',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Woodlouse','Woodlouse','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Woodlouse','WoodlouseBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Woodlouse','WoodlouseBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Badger','Badger',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Badger','Badger','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Badger','BadgerBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Badger','BadgerBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Lizzard','Lizzard',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Lizzard','Lizzard','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Lizzard','LizzardBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Lizzard','LizzardBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlackBear','BlackBear',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlackBear','BlackBear','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlackBear','BlackBearBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlackBear','BlackBearBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Llama','Llama',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Llama','Llama','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Llama','LlamaBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Llama','LlamaBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('LlamaYoung','LlamaYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('LlamaYoung','LlamaYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('LlamaYoung','LlamaYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('LlamaYoung','LlamaYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Emu','Emu',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Emu','Emu','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Emu','EmuBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Emu','EmuBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('EmuYoung','EmuYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('EmuYoung','EmuYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('EmuYoung','EmuYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('EmuYoung','EmuYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cow','Cow',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cow','Cow','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cow','CowBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cow','CowBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CowYoung','CowYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CowYoung','CowYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CowYoung','CowYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CowYoung','CowYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Yak','Yak',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Yak','Yak','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Yak','YakBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Yak','YakBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('YakYoung','YakYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('YakYoung','YakYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('YakYoung','YakYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('YakYoung','YakYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Spider','Spider',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Spider','Spider','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Spider','SpiderBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Spider','SpiderBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Beetle','Beetle',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Beetle','Beetle','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Beetle','BeetleBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Beetle','BeetleBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Duck','Duck',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Duck','Duck','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Duck','DuckBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Duck','DuckBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DuckYoung','DuckYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DuckYoung','DuckYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DuckYoung','DuckYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DuckYoung','DuckYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goose','Goose',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goose','Goose','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goose','GooseBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goose','GooseBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GooseYoung','GooseYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GooseYoung','GooseYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GooseYoung','GooseYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GooseYoung','GooseYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shepherd','Shepherd',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shepherd','Shepherd','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shepherd','ShepherdBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Shepherd','ShepherdBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShepherdYoung','ShepherdYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShepherdYoung','ShepherdYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShepherdYoung','ShepherdYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ShepherdYoung','ShepherdYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatTabby','CatTabby',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatTabby','CatTabby','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatTabby','CatTabbyBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatTabby','CatTabbyBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatBlack','CatBlack',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatBlack','CatBlack','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatBlack','CatBlackBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CatBlack','CatBlackBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Porcupine','Porcupine',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Porcupine','Porcupine','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Porcupine','PorcupineBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Porcupine','PorcupineBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Fox','Fox',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Fox','Fox','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Fox','FoxBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Fox','FoxBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Wolf','Wolf',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Wolf','Wolf','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Wolf','WolfBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Wolf','WolfBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Stag','Stag',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Stag','Stag','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Stag','StagBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Stag','StagBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roe','Roe',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roe','Roe','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roe','RoeBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roe','RoeBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goat','Goat',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goat','Goat','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goat','GoatBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goat','GoatBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GoatYoung','GoatYoung',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GoatYoung','GoatYoung','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GoatYoung','GoatYoungBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GoatYoung','GoatYoungBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Squirrel','Squirrel',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Squirrel','Squirrel','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Squirrel','SquirrelBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Squirrel','SquirrelBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreyFish','GreyFish',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreyFish','GreyFish','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreyFish','GreyFishBack',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GreyFish','GreyFishBack','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goblin',NULL,'FlipHorizontal','FL','GoblinFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goblin',NULL,NULL,'FR','GoblinFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goblin',NULL,NULL,'BR','GoblinFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Goblin',NULL,'FlipHorizontal','BL','GoblinFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CrystalSnake','CrystalSnakeFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CrystalSnake','CrystalSnakeFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CrystalSnake','CrystalSnakeBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CrystalSnake','CrystalSnakeBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungBlue','ZygYoungBlueFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungBlue','ZygYoungBlueFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungBlue','ZygYoungBlueBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungBlue','ZygYoungBlueBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungRed','ZygYoungRedFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungRed','ZygYoungRedFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungRed','ZygYoungRedBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYoungRed','ZygYoungRedBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthBlue','ZygYouthBlueFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthBlue','ZygYouthBlueFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthBlue','ZygYouthBlueBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthBlue','ZygYouthBlueBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthRed','ZygYouthRedFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthRed','ZygYouthRedFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthRed','ZygYouthRedBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygYouthRed','ZygYouthRedBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultBlue','ZygAdultBlueFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultBlue','ZygAdultBlueFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultBlue','ZygAdultBlueBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultBlue','ZygAdultBlueBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultRed','ZygAdultRedFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultRed','ZygAdultRedFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultRed','ZygAdultRedBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygAdultRed','ZygAdultRedBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorBlue','ZygSeniorBlueFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorBlue','ZygSeniorBlueFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorBlue','ZygSeniorBlueBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorBlue','ZygSeniorBlueBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorRed','ZygSeniorRedFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorRed','ZygSeniorRedFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorRed','ZygSeniorRedBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ZygSeniorRed','ZygSeniorRedBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DyedCloth','DyedCloth',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DyedCloth','DyedCloth','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DyedCloth','DyedCloth',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('DyedCloth','DyedCloth','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cabinet','CabinetFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cabinet','CabinetFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cabinet','CabinetBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Cabinet','CabinetBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting1','Painting1',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting1','Painting1','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting1','Painting1',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting1','Painting1','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting2','Painting2',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting2','Painting2','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting2','Painting2',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting2','Painting2','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting3','Painting3',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting3','Painting3','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting3','Painting3',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting3','Painting3','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting4','Painting4',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting4','Painting4','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting4','Painting4',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting4','Painting4','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting5','Painting5',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting5','Painting5','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting5','Painting5',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting5','Painting5','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting6','Painting6',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting6','Painting6','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting6','Painting6',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting6','Painting6','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting7','Painting7',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting7','Painting7','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting7','Painting7',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting7','Painting7','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting8','Painting8',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting8','Painting8','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting8','Painting8',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Painting8','Painting8','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingFishRack','FishingFishRack',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingFishRack','FishingFishRack','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingFishRack','FishingFishRack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingFishRack','FishingFishRack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRack','FishingRackFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRack','FishingRackFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRack','FishingRackBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRack','FishingRackBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRods','FishingRodsFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRods','FishingRodsFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRods','FishingRodsBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('FishingRods','FishingRodsBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Palisade','Palisade',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Palisade','Palisade','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Palisade','Palisade',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Palisade','Palisade','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PalisadeTop','PalisadeTop',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PalisadeTop','PalisadeTop','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PalisadeTop','PalisadeTop',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PalisadeTop','PalisadeTop','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotN',NULL,NULL,'FR','BlockFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotN',NULL,NULL,'FL','BlockFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotN',NULL,NULL,'BL','BlockFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotN',NULL,NULL,'BR','BlockFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotE',NULL,NULL,'FR','BlockFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotE',NULL,NULL,'FL','BlockFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotE',NULL,NULL,'BL','BlockFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotE',NULL,NULL,'BR','BlockFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotS',NULL,NULL,'FR','BlockFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotS',NULL,NULL,'FL','BlockFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotS',NULL,NULL,'BL','BlockFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotS',NULL,NULL,'BR','BlockFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotW',NULL,NULL,'FR','BlockFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotW',NULL,NULL,'FL','BlockFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotW',NULL,NULL,'BL','BlockFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotW',NULL,NULL,'BR','BlockFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNS',NULL,NULL,'FR','BlockFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNS',NULL,NULL,'FL','BlockFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNS',NULL,NULL,'BL','BlockFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNS',NULL,NULL,'BR','BlockFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotEW',NULL,NULL,'FR','BlockFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotEW',NULL,NULL,'FL','BlockFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotEW',NULL,NULL,'BL','BlockFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotEW',NULL,NULL,'BR','BlockFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNE',NULL,NULL,'FR','BlockFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNE',NULL,NULL,'FL','BlockFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNE',NULL,NULL,'BL','BlockFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNE',NULL,NULL,'BR','BlockFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotES',NULL,NULL,'FR','BlockFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotES',NULL,NULL,'FL','BlockFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotES',NULL,NULL,'BL','BlockFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotES',NULL,NULL,'BR','BlockFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotSW',NULL,NULL,'FR','BlockFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotSW',NULL,NULL,'FL','BlockFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotSW',NULL,NULL,'BL','BlockFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotSW',NULL,NULL,'BR','BlockFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNW',NULL,NULL,'FR','BlockFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNW',NULL,NULL,'FL','BlockFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNW',NULL,NULL,'BL','BlockFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNW',NULL,NULL,'BR','BlockFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotESW',NULL,NULL,'FR','BlockFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotESW',NULL,NULL,'FL','BlockFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotESW',NULL,NULL,'BL','BlockFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotESW',NULL,NULL,'BR','BlockFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNSW',NULL,NULL,'FR','BlockFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNSW',NULL,NULL,'FL','BlockFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNSW',NULL,NULL,'BL','BlockFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNSW',NULL,NULL,'BR','BlockFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNEW',NULL,NULL,'FR','BlockFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNEW',NULL,NULL,'FL','BlockFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNEW',NULL,NULL,'BL','BlockFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNEW',NULL,NULL,'BR','BlockFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNES',NULL,NULL,'FR','BlockFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNES',NULL,NULL,'FL','BlockFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNES',NULL,NULL,'BL','BlockFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BlockFenceRotNES',NULL,NULL,'BR','BlockFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotN',NULL,NULL,'FR','CobbleStoneFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotN',NULL,NULL,'FL','CobbleStoneFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotN',NULL,NULL,'BL','CobbleStoneFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotN',NULL,NULL,'BR','CobbleStoneFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotE',NULL,NULL,'FR','CobbleStoneFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotE',NULL,NULL,'FL','CobbleStoneFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotE',NULL,NULL,'BL','CobbleStoneFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotE',NULL,NULL,'BR','CobbleStoneFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotS',NULL,NULL,'FR','CobbleStoneFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotS',NULL,NULL,'FL','CobbleStoneFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotS',NULL,NULL,'BL','CobbleStoneFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotS',NULL,NULL,'BR','CobbleStoneFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotW',NULL,NULL,'FR','CobbleStoneFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotW',NULL,NULL,'FL','CobbleStoneFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotW',NULL,NULL,'BL','CobbleStoneFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotW',NULL,NULL,'BR','CobbleStoneFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNS',NULL,NULL,'FR','CobbleStoneFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNS',NULL,NULL,'FL','CobbleStoneFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNS',NULL,NULL,'BL','CobbleStoneFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNS',NULL,NULL,'BR','CobbleStoneFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotEW',NULL,NULL,'FR','CobbleStoneFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotEW',NULL,NULL,'FL','CobbleStoneFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotEW',NULL,NULL,'BL','CobbleStoneFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotEW',NULL,NULL,'BR','CobbleStoneFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNE',NULL,NULL,'FR','CobbleStoneFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNE',NULL,NULL,'FL','CobbleStoneFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNE',NULL,NULL,'BL','CobbleStoneFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNE',NULL,NULL,'BR','CobbleStoneFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotES',NULL,NULL,'FR','CobbleStoneFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotES',NULL,NULL,'FL','CobbleStoneFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotES',NULL,NULL,'BL','CobbleStoneFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotES',NULL,NULL,'BR','CobbleStoneFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotSW',NULL,NULL,'FR','CobbleStoneFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotSW',NULL,NULL,'FL','CobbleStoneFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotSW',NULL,NULL,'BL','CobbleStoneFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotSW',NULL,NULL,'BR','CobbleStoneFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNW',NULL,NULL,'FR','CobbleStoneFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNW',NULL,NULL,'FL','CobbleStoneFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNW',NULL,NULL,'BL','CobbleStoneFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNW',NULL,NULL,'BR','CobbleStoneFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotESW',NULL,NULL,'FR','CobbleStoneFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotESW',NULL,NULL,'FL','CobbleStoneFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotESW',NULL,NULL,'BL','CobbleStoneFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotESW',NULL,NULL,'BR','CobbleStoneFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNSW',NULL,NULL,'FR','CobbleStoneFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNSW',NULL,NULL,'FL','CobbleStoneFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNSW',NULL,NULL,'BL','CobbleStoneFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNSW',NULL,NULL,'BR','CobbleStoneFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNEW',NULL,NULL,'FR','CobbleStoneFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNEW',NULL,NULL,'FL','CobbleStoneFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNEW',NULL,NULL,'BL','CobbleStoneFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNEW',NULL,NULL,'BR','CobbleStoneFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNES',NULL,NULL,'FR','CobbleStoneFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNES',NULL,NULL,'FL','CobbleStoneFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNES',NULL,NULL,'BL','CobbleStoneFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('CobbleStoneFenceRotNES',NULL,NULL,'BR','CobbleStoneFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotN',NULL,NULL,'FR','WoodFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotN',NULL,NULL,'FL','WoodFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotN',NULL,NULL,'BL','WoodFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotN',NULL,NULL,'BR','WoodFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotE',NULL,NULL,'FR','WoodFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotE',NULL,NULL,'FL','WoodFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotE',NULL,NULL,'BL','WoodFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotE',NULL,NULL,'BR','WoodFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotS',NULL,NULL,'FR','WoodFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotS',NULL,NULL,'FL','WoodFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotS',NULL,NULL,'BL','WoodFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotS',NULL,NULL,'BR','WoodFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotW',NULL,NULL,'FR','WoodFenceW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotW',NULL,NULL,'FL','WoodFenceN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotW',NULL,NULL,'BL','WoodFenceE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotW',NULL,NULL,'BR','WoodFenceS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNS',NULL,NULL,'FR','WoodFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNS',NULL,NULL,'FL','WoodFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNS',NULL,NULL,'BL','WoodFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNS',NULL,NULL,'BR','WoodFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotEW',NULL,NULL,'FR','WoodFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotEW',NULL,NULL,'FL','WoodFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotEW',NULL,NULL,'BL','WoodFenceEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotEW',NULL,NULL,'BR','WoodFenceNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNE',NULL,NULL,'FR','WoodFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNE',NULL,NULL,'FL','WoodFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNE',NULL,NULL,'BL','WoodFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNE',NULL,NULL,'BR','WoodFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotES',NULL,NULL,'FR','WoodFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotES',NULL,NULL,'FL','WoodFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotES',NULL,NULL,'BL','WoodFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotES',NULL,NULL,'BR','WoodFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotSW',NULL,NULL,'FR','WoodFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotSW',NULL,NULL,'FL','WoodFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotSW',NULL,NULL,'BL','WoodFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotSW',NULL,NULL,'BR','WoodFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNW',NULL,NULL,'FR','WoodFenceNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNW',NULL,NULL,'FL','WoodFenceNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNW',NULL,NULL,'BL','WoodFenceES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNW',NULL,NULL,'BR','WoodFenceSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotESW',NULL,NULL,'FR','WoodFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotESW',NULL,NULL,'FL','WoodFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotESW',NULL,NULL,'BL','WoodFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotESW',NULL,NULL,'BR','WoodFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNSW',NULL,NULL,'FR','WoodFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNSW',NULL,NULL,'FL','WoodFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNSW',NULL,NULL,'BL','WoodFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNSW',NULL,NULL,'BR','WoodFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNEW',NULL,NULL,'FR','WoodFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNEW',NULL,NULL,'FL','WoodFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNEW',NULL,NULL,'BL','WoodFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNEW',NULL,NULL,'BR','WoodFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNES',NULL,NULL,'FR','WoodFenceNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNES',NULL,NULL,'FL','WoodFenceESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNES',NULL,NULL,'BL','WoodFenceNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodFenceRotNES',NULL,NULL,'BR','WoodFenceNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rafter','RafterFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rafter','RafterFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rafter','RafterBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Rafter','RafterBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roofing','RoofingFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roofing','RoofingFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roofing','RoofingBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Roofing','RoofingBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WorkshopTable','WorkshopTable',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WorkshopTable','WorkshopTable',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WorkshopTable','WorkshopTable',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WorkshopTable','WorkshopTable',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChiselTableTop','ChiselTableTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChiselTableTop','ChiselTableTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChiselTableTop','ChiselTableTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ChiselTableTop','ChiselTableTopBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ButcherTableTop','ButcherTableTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ButcherTableTop','ButcherTableTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ButcherTableTop','ButcherTableTopBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ButcherTableTop','ButcherTableTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KitchenTableTop','KitchenTableTopFR','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KitchenTableTop','KitchenTableTopFR',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KitchenTableTop','KitchenTableTopBL','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('KitchenTableTop','KitchenTableTopBL',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('HammerTableTop','HammerTableTopBL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('HammerTableTop','HammerTableTopFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('HammerTableTop','HammerTableTopFR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('HammerTableTop','HammerTableTopBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Loom','LoomFR',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Loom','LoomFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Loom','LoomBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Loom','LoomBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayRamp','ClayRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayRamp','ClayRampFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayRamp','ClayRampBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayRamp','ClayRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRamp','StoneRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRamp','StoneRampFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRamp','StoneRampBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRamp','StoneRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRamp','ThatchRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRamp','ThatchRampFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRamp','ThatchRampBR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRamp','ThatchRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRampTop','ThatchRampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRampTop','ThatchRampTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRampTop','ThatchRampTopBR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchRampTop','ThatchRampTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRamp','ClayCornerRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRamp','ClayCornerRampFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRamp','ClayCornerRampBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRamp','ClayCornerRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRamp','StoneCornerRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRamp','StoneCornerRampFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRamp','StoneCornerRampBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRamp','StoneCornerRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURamp','ClayURampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURamp','ClayURampFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURamp','ClayURampBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURamp','ClayURampBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURamp','StoneURampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURamp','StoneURampFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURamp','StoneURampBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURamp','StoneURampBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRampTop','StoneRampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRampTop','StoneRampTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRampTop','StoneRampTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneRampTop','StoneRampTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRampTop','ClayCornerRampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRampTop','ClayCornerRampTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRampTop','ClayCornerRampTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayCornerRampTop','ClayCornerRampTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRampTop','StoneCornerRampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRampTop','StoneCornerRampTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRampTop','StoneCornerRampTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneCornerRampTop','StoneCornerRampTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayURampTop','ClayURampTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURampTop','StoneURampTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURampTop','StoneURampTopFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURampTop','StoneURampTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneURampTop','StoneURampTopBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilOuterCornerRamp','SoilOuterCornerRampBR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilOuterCornerRamp','SoilOuterCornerRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilOuterCornerRamp','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilOuterCornerRamp','SoilOuterCornerRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayOuterCornerRamp','ClayOuterCornerRampBR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayOuterCornerRamp','ClayOuterCornerRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayOuterCornerRamp','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ClayOuterCornerRamp','ClayOuterCornerRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneOuterCornerRamp','StoneOuterCornerRampBR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneOuterCornerRamp','StoneOuterCornerRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneOuterCornerRamp','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneOuterCornerRamp','StoneOuterCornerRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchOuterCornerRamp','ThatchOuterCornerRampBR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchOuterCornerRamp','ThatchOuterCornerRampFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchOuterCornerRamp','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('ThatchOuterCornerRamp','ThatchOuterCornerRampBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTop','AppleTreeTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTop','AppleTreeTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTop','AppleTreeTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTop','AppleTreeTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTopCorner','AppleTreeTopCornerFront',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTopCorner','AppleTreeTopCornerLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTopCorner','AppleTreeTopCornerBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeTopCorner','AppleTreeTopCornerRight',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottom','AppleTreeBottom',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottom','AppleTreeBottom',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottom','AppleTreeMiddle',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottom','AppleTreeMiddle',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottomCorner','AppleTreeBottomCornerFront',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottomCorner','AppleTreeBottomCornerLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottomCorner','AppleTreeMiddle',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('AppleTreeBottomCorner','AppleTreeBottomCornerRight',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree1','PineTree9',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree1','PineTree8',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree1','PineTree14',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree1','PineTree15',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree2','PineTree13',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree2','PineTree12',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree2','PineTree3',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree2','PineTree4',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree3','PineTree2',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree3','PineTree1',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree3','PineTree10',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree3','PineTree11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree4','PineTree17',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree4','PineTree16',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree4','PineTree14',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PineTree4','PineTree15',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTop','OrangeTreeTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTop','OrangeTreeTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTop','OrangeTreeTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTop','OrangeTreeTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTopCorner','OrangeTreeTopCornerFront',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTopCorner','OrangeTreeTopCornerLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTopCorner','OrangeTreeTopCornerBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeTopCorner','OrangeTreeTopCornerRight',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeMiddleCorner','OrangeTreeMiddleCornerFront',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeMiddleCorner','OrangeTreeMiddleCornerLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeMiddleCorner','OrangeTreeMiddleCornerBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeMiddleCorner','OrangeTreeMiddleCornerRight',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottom','OrangeTreeBottom',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottom','OrangeTreeBottom',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottom','OrangeTreeMiddle',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottom','OrangeTreeMiddle',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottomCorner','OrangeTreeBottomCornerFront',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottomCorner','OrangeTreeBottomCornerLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottomCorner','OrangeTreeMiddle',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OrangeTreeBottomCorner','OrangeTreeBottomCornerRight',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRamp','MushroomGrassRamp_3_FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRamp','MushroomGrassRamp_3_FR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRamp','MushroomGrassRamp_3_BL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRamp','MushroomGrassRamp_3_BR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRampTop','MushroomGrassRampTop_3_FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRampTop','MushroomGrassRampTop_3_FR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRampTop','MushroomGrassRampTop_3_BL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassRampTop','MushroomGrassRampTop_3_BR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRamp','MushroomGrassCornerRamp_3_FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRamp','MushroomGrassCornerRamp_3_FR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRamp','MushroomGrassCornerRamp_3_BL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRamp','MushroomGrassCornerRamp_3_BR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRampTop','MushroomGrassCornerRampTop_3_FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRampTop','MushroomGrassCornerRampTop_3_FR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRampTop','MushroomGrassCornerRampTop_3_BL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassCornerRampTop','MushroomGrassCornerRampTop_3_BR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURamp','MushroomGrassURamp_3_FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURamp','MushroomGrassURamp_3_FR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURamp','MushroomGrassURamp_3_FR',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURamp','MushroomGrassURamp_3_FL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURampTop','MushroomGrassURampTop_3_FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURampTop','MushroomGrassURampTop_3_FR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURampTop','MushroomGrassURampTop_3_FR',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MushroomGrassURampTop','MushroomGrassURampTop_3_FL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree1','OakTree1','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree1','OakTree6','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree1','OakTree3','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree1','OakTree5','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree10','OakTree10','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree10','OakTree8','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree10','OakTree12','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree10','OakTree12','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree11','OakTree11','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree11','OakTree9','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree11','OakTree12','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree11','OakTree7','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_1','OakTree12','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_1','OakTree10','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_1','OakTree12','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_1','OakTree8','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree2','OakTree2','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree2','OakTree6','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree2','OakTree4','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree2','OakTree6','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree210','OakTree210','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree210','OakTree26','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree210','OakTree28','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree210','OakTree24','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree211','OakTree211','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree211','OakTree27','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree211','OakTree23','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree211','OakTree25','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree23','OakTree23','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree23','OakTree211','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree23','OakTree25','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree23','OakTree27','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree24','OakTree24','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree24','OakTree28','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree24','OakTree26','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree24','OakTree210','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree25','OakTree25','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree25','OakTree23','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree25','OakTree27','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree25','OakTree211','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree26','OakTree26','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree26','OakTree24','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree26','OakTree210','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree26','OakTree28','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree27','OakTree27','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree27','OakTree25','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree27','OakTree211','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree27','OakTree23','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree28','OakTree28','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree28','OakTree210','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree28','OakTree24','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree28','OakTree26','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree29','OakTree29','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree29','OakTree29','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree29','OakTree29','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree29','OakTree29','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree3','OakTree3','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree3','OakTree1','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree3','OakTree5','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree3','OakTree6','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree4','OakTree4','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree4','OakTree2','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree4','OakTree6','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree4','OakTree6','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree5','OakTree5','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree5','OakTree3','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree5','OakTree6','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree5','OakTree1','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_1','OakTree6','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_1','OakTree4','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_1','OakTree6','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_1','OakTree2','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree7','OakTree7','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree7','OakTree12','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree7','OakTree9','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree7','OakTree11','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree8','OakTree8','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree8','OakTree12','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree8','OakTree10','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree8','OakTree12','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree9','OakTree9','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree9','OakTree7','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree9','OakTree11','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree9','OakTree12','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_2','OakTree6','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_2','OakTree5','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_2','OakTree1','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_2','OakTree3','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_3','OakTree6','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_3','OakTree6','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_3','OakTree2','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree6_3','OakTree4','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_3','OakTree12','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_3','OakTree12','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_3','OakTree8','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_3','OakTree10','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_2','OakTree12',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_2','OakTree11',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_2','OakTree9',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('OakTree12_2','OakTree7',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree1','WillowTree1','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree1','WillowTree6','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree1','WillowTree3','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree1','WillowTree5','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree10','WillowTree10','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree10','WillowTree8','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree10','WillowTree12','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree10','WillowTree12','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree11','WillowTree11','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree11','WillowTree9','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree11','WillowTree12','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree11','WillowTree7','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_1','WillowTree12','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_1','WillowTree10','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_1','WillowTree12','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_1','WillowTree8','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree2','WillowTree2','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree2','WillowTree6','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree2','WillowTree4','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree2','WillowTree6','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree210','WillowTree210','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree210','WillowTree26','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree210','WillowTree28','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree210','WillowTree24','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree211','WillowTree211','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree211','WillowTree27','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree211','WillowTree23','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree211','WillowTree25','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree23','WillowTree23','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree23','WillowTree211','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree23','WillowTree25','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree23','WillowTree27','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree24','WillowTree24','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree24','WillowTree28','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree24','WillowTree26','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree24','WillowTree210','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree25','WillowTree25','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree25','WillowTree23','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree25','WillowTree27','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree25','WillowTree211','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree26','WillowTree26','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree26','WillowTree24','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree26','WillowTree210','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree26','WillowTree28','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree27','WillowTree27','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree27','WillowTree25','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree27','WillowTree211','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree27','WillowTree23','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree28','WillowTree28','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree28','WillowTree210','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree28','WillowTree24','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree28','WillowTree26','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree29','WillowTree29','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree29','WillowTree29','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree29','WillowTree29','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree29','WillowTree29','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree3','WillowTree3','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree3','WillowTree1','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree3','WillowTree5','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree3','WillowTree6','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree4','WillowTree4','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree4','WillowTree2','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree4','WillowTree6','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree4','WillowTree6','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree5','WillowTree5','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree5','WillowTree3','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree5','WillowTree6','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree5','WillowTree1','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_1','WillowTree6','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_1','WillowTree4','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_1','WillowTree6','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_1','WillowTree2','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree7','WillowTree7','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree7','WillowTree12','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree7','WillowTree9','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree7','WillowTree11','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree8','WillowTree8','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree8','WillowTree12','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree8','WillowTree10','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree8','WillowTree12','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree9','WillowTree9','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree9','WillowTree7','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree9','WillowTree11','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree9','WillowTree12','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_2','WillowTree6','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_2','WillowTree5','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_2','WillowTree1','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_2','WillowTree3','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_3','WillowTree6','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_3','WillowTree6','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_3','WillowTree2','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree6_3','WillowTree4','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_3','WillowTree12','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_3','WillowTree12','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_3','WillowTree8','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_3','WillowTree10','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_2','WillowTree12',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_2','WillowTree11',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_2','WillowTree9',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WillowTree12_2','WillowTree7',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('UprightWeaponStand','UprightWeaponStandFR','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('UprightWeaponStand','UprightWeaponStandFR','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('UprightWeaponStand','UprightWeaponStandBL','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('UprightWeaponStand','UprightWeaponStandBL','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TrainingDummy','TrainingDummy','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TrainingDummy','TrainingDummy','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TrainingDummy','TrainingDummy','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('TrainingDummy','TrainingDummy','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepRed','SheepRed','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepRed','SheepRed','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepRed','SheepRedBack','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepRed','SheepRedBack','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepGreen','SheepGreen','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepGreen','SheepGreen','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepGreen','SheepGreenBack','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepGreen','SheepGreenBack','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepBlue','SheepBlue','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepBlue','SheepBlue','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepBlue','SheepBlueBack','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepBlue','SheepBlueBack','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYellow','SheepYellow','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYellow','SheepYellow','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYellow','SheepYellowBack','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepYellow','SheepYellowBack','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepPurple','SheepPurple','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepPurple','SheepPurple','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepPurple','SheepPurpleBack','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepPurple','SheepPurpleBack','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepCyan','SheepCyan','','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepCyan','SheepCyan','FlipHorizontal','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepCyan','SheepCyanBack','FlipHorizontal','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SheepCyan','SheepCyanBack','','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEngineBoiler',NULL,NULL,'FR','SteamEngineBoilerFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEngineBoiler',NULL,'FlipHorizontal','FL','SteamEngineBoilerFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEngineBoiler',NULL,NULL,'BL','SteamEngineBoilerBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEngineBoiler',NULL,'FlipHorizontal','BR','SteamEngineBoilerBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEnginePiston',NULL,NULL,'FR','SteamEnginePistonFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEnginePiston',NULL,'FlipHorizontal','FL','SteamEnginePistonFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEnginePiston',NULL,NULL,'BL','SteamEnginePistonBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SteamEnginePiston',NULL,'FlipHorizontal','BR','SteamEnginePistonBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Axle',NULL,NULL,'FR','AxleAnim');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Axle',NULL,'FlipHorizontal','FL','AxleAnim');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Axle',NULL,NULL,'BL','AxleAnim');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Axle',NULL,'FlipHorizontal','BR','AxleAnim');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotN','','','FR','PipeN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotN','','','FL','PipeE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotN','','','BL','PipeS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotN','','','BR','PipeW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotE','','','FR','PipeE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotE','','','FL','PipeS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotE','','','BL','PipeW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotE','','','BR','PipeN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotS','','','FR','PipeS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotS','','','FL','PipeW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotS','','','BL','PipeN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotS','','','BR','PipeE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotW','','','FR','PipeW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotW','','','FL','PipeN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotW','','','BL','PipeE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotW','','','BR','PipeS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNS','','','FR','PipeNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNS','','','FL','PipeEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNS','','','BL','PipeNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNS','','','BR','PipeEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotEW','','','FR','PipeEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotEW','','','FL','PipeNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotEW','','','BL','PipeEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotEW','','','BR','PipeNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNE','','','FR','PipeNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNE','','','FL','PipeES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNE','','','BL','PipeSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNE','','','BR','PipeNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotES','','','FR','PipeES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotES','','','FL','PipeSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotES','','','BL','PipeNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotES','','','BR','PipeNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotSW','','','FR','PipeSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotSW','','','FL','PipeNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotSW','','','BL','PipeNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotSW','','','BR','PipeES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNW','','','FR','PipeNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNW','','','FL','PipeNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNW','','','BL','PipeES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNW','','','BR','PipeSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotESW','','','FR','PipeESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotESW','','','FL','PipeNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotESW','','','BL','PipeNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotESW','','','BR','PipeNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNSW','','','FR','PipeNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNSW','','','FL','PipeNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNSW','','','BL','PipeNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNSW','','','BR','PipeESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNEW','','','FR','PipeNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNEW','','','FL','PipeNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNEW','','','BL','PipeESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNEW','','','BR','PipeNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNES','','','FR','PipeNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNES','','','FL','PipeESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNES','','','BL','PipeNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeRotNES','','','BR','PipeNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotN','','','FR','PipeExitN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotN','','','FL','PipeExitE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotN','','','BL','PipeExitS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotN','','','BR','PipeExitW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotE','','','FR','PipeExitE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotE','','','FL','PipeExitS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotE','','','BL','PipeExitW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotE','','','BR','PipeExitN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotS','','','FR','PipeExitS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotS','','','FL','PipeExitW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotS','','','BL','PipeExitN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotS','','','BR','PipeExitE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotW','','','FR','PipeExitW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotW','','','FL','PipeExitN');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotW','','','BL','PipeExitE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotW','','','BR','PipeExitS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNS','','','FR','PipeExitNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNS','','','FL','PipeExitEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNS','','','BL','PipeExitNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNS','','','BR','PipeExitEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotEW','','','FR','PipeExitEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotEW','','','FL','PipeExitNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotEW','','','BL','PipeExitEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotEW','','','BR','PipeExitNS');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNE','','','FR','PipeExitNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNE','','','FL','PipeExitES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNE','','','BL','PipeExitSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNE','','','BR','PipeExitNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotES','','','FR','PipeExitES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotES','','','FL','PipeExitSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotES','','','BL','PipeExitNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotES','','','BR','PipeExitNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotSW','','','FR','PipeExitSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotSW','','','FL','PipeExitNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotSW','','','BL','PipeExitNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotSW','','','BR','PipeExitES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNW','','','FR','PipeExitNW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNW','','','FL','PipeExitNE');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNW','','','BL','PipeExitES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNW','','','BR','PipeExitSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotESW','','','FR','PipeExitESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotESW','','','FL','PipeExitNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotESW','','','BL','PipeExitNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotESW','','','BR','PipeExitNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNSW','','','FR','PipeExitNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNSW','','','FL','PipeExitNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNSW','','','BL','PipeExitNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNSW','','','BR','PipeExitESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNEW','','','FR','PipeExitNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNEW','','','FL','PipeExitNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNEW','','','BL','PipeExitESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNEW','','','BR','PipeExitNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNES','','','FR','PipeExitNES');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNES','','','FL','PipeExitESW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNES','','','BL','PipeExitNSW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PipeExitRotNES','','','BR','PipeExitNEW');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree6','BirchTree6',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree6','BirchTree7',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree6','BirchTree8',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree6','BirchTree9',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree7','BirchTree7',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree7','BirchTree8',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree7','BirchTree9',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree7','BirchTree6',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree8','BirchTree8',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree8','BirchTree9',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree8','BirchTree6',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree8','BirchTree7',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree9','BirchTree9',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree9','BirchTree6',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree9','BirchTree7',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree9','BirchTree8',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5_10','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5_10','BirchTree10',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5_10','BirchTree5',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5_10','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10_5','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10_5','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10_5','BirchTree10',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10_5','BirchTree5',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5','BirchTree5',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree5','BirchTree10',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10','BirchTree10',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10','BirchTree5',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree10','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_1','BirchTree11',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_1','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_1','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_1','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_2','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_2','BirchTree11',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_2','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_2','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_3','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_3','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_3','BirchTree11',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_3','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_4','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_4','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_4','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_4','BirchTree11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_5','BirchTree11',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_5','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_5','BirchTree11',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_5','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_6','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_6','BirchTree11',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_6','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree11_6','BirchTree11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_1','BirchTree20',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_1','BirchTree19',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_1','BirchTree11',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_1','BirchTree11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_2','BirchTree19',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_2','BirchTree11',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_2','BirchTree11',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_2','BirchTree20',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_3','BirchTree11',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_3','BirchTree11',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_3','BirchTree20',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_3','BirchTree19',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_4','BirchTree11',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_4','BirchTree20',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_4','BirchTree19',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BirchTree20_4','BirchTree11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Handcrank','HandcrankFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Handcrank','HandcrankFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Handcrank','HandcrankBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Handcrank','HandcrankBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Automaton',NULL,NULL,'FR','AutomatonFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Automaton',NULL,'FlipHorizontal','FL','AutomatonFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Automaton',NULL,NULL,'BR','AutomatonBR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Automaton',NULL,'FlipHorizontal','BL','AutomatonBR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame1',NULL,NULL,'FR','WindmillSail1FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame1',NULL,'FlipHorizontal','FL','WindmillSail2FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame1',NULL,NULL,'BL','WindmillSail2BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame1',NULL,'FlipHorizontal','BR','WindmillSail1BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame2',NULL,NULL,'FR','WindmillSail2FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame2',NULL,'FlipHorizontal','FL','WindmillSail1FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame2',NULL,NULL,'BL','WindmillSail1BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame2',NULL,'FlipHorizontal','BR','WindmillSail2BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame3',NULL,NULL,'FR','WindmillSail3FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame3',NULL,'FlipHorizontal','FL','WindmillSail4FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame3',NULL,NULL,'BL','WindmillSail4BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame3',NULL,'FlipHorizontal','BR','WindmillSail3BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame4',NULL,NULL,'FR','WindmillSail4FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame4',NULL,'FlipHorizontal','FL','WindmillSail3FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame4',NULL,NULL,'BL','WindmillSail3BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailFrame4',NULL,'FlipHorizontal','BR','WindmillSail4BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase','WindmillBaseFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase','WindmillBaseFL','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase','WindmillBaseBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase','WindmillBaseBR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillRoof','WindmillRoofFL','','FL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillRoof','WindmillRoofFL','FlipHorizontal','FR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillRoof','WindmillRoofBR','','BR','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillRoof','WindmillRoofBR','FlipHorizontal','BL','');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase2','WindmillBase2FL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase2','WindmillBase2FL','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase2','WindmillBase2BR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillBase2','WindmillBase2BR','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairsTop','StairsTopFR',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairsTop','StairsTopFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairsTop','StairsTopBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairsTop','StairsTopBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairsTop','BlockStairsTopFR',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairsTop','BlockStairsTopFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairsTop','BlockStairsTopBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairsTop','BlockStairsTopBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairs','StairsFR',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairs','StairsFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairs','StairsBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SoilStairs','StairsBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairs','BlockStairsFR',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairs','BlockStairsFR','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairs','BlockStairsBL',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneStairs','BlockStairsBL','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodDoor','WoodDoorRight',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodDoor','WoodDoorLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodDoor','WoodDoorRight',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodDoor','WoodDoorLeft',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneDoor','StoneDoorRight',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneDoor','StoneDoorLeft',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneDoor','StoneDoorRight',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('StoneDoor','StoneDoorLeft',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodTable','WoodTable',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodTable','WoodTable','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodTable','WoodTable',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WoodTable','WoodTable','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedFrame','BoneBedFrameFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedFrame','BoneBedFrameFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedFrame','BoneBedFrameBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedFrame','BoneBedFrameBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedSheets','BoneBedSheetsFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedSheets','BoneBedSheetsFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedSheets','MattressBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BoneBedSheets','MattressBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth1','','','FR','WindmillSailCloth1FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth1','','FlipHorizontal','FL','WindmillSailCloth2FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth1','','','BL','WindmillSailCloth2BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth1','','FlipHorizontal','BR','WindmillSailCloth1BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth2','','','FR','WindmillSailCloth2FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth2','','FlipHorizontal','FL','WindmillSailCloth1FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth2','','','BL','WindmillSailCloth1BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth2','','FlipHorizontal','BR','WindmillSailCloth2BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth3','','','FR','WindmillSailCloth3FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth3','','FlipHorizontal','FL','WindmillSailCloth4FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth3','','','BL','WindmillSailCloth4BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth3','','FlipHorizontal','BR','WindmillSailCloth3BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth4','','','FR','WindmillSailCloth4FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth4','','FlipHorizontal','FL','WindmillSailCloth3FR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth4','','','BL','WindmillSailCloth3BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WindmillSailCloth4','','FlipHorizontal','BR','WindmillSailCloth4BL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Donkey','Donkey',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Donkey','Donkey','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Donkey','DonkeyBack',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Donkey','DonkeyBack','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_02','Mushroom2_4',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_02','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_02','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_02','Mushroom2_21',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_11','Mushroom2_15',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_11','Mushroom2_17',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_11','Mushroom2_23',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_11','Mushroom2_18',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_12','Mushroom2_4',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_12','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_12','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_12','Mushroom2_11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_21','Mushroom2_12',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_21','Mushroom2_9',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_21','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_21','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_22','Mushroom2_10',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_22','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_22','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_3_22','EmptyWall',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_10','Mushroom2_2',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_10','Mushroom2_1',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_10','Mushroom2_3',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_10','Mushroom2_5',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_11','Mushroom2_6',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_11','Mushroom2_7',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_11','EmptyWall',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom2_4_11','Mushroom2_8',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_10','Mushroom2_12',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_10','Mushroom2_4',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_10','Mushroom2_16',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_10','Mushroom2_16',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_11','Mushroom2_10',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_11','Mushroom2_9',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_11','Mushroom2_23',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_2_11','Mushroom2_11',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_3_10','EmptyWall',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_3_10','EmptyWall',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_3_10','Mushroom2_7',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Mushroom3_3_10','Mushroom2_8',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchFlame',NULL,NULL,'FR','WallTorchFlameFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchFlame',NULL,'FlipHorizontal','FL','WallTorchFlameFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchFlame',NULL,NULL,'BL','WallTorchFlameBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchFlame',NULL,'FlipHorizontal','BR','WallTorchFlameBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchBase',NULL,NULL,'FR','WallTorchBaseFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchBase',NULL,'FlipHorizontal','FL','WallTorchBaseFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchBase',NULL,NULL,'BL','WallTorchBaseBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('WallTorchBase',NULL,'FlipHorizontal','BR','WallTorchBaseBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairs','PlankStairsFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairs','PlankStairsFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairs','PlankStairsBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairs','PlankStairsBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairsTop','PlankStairsTopFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairsTop','PlankStairsTopFL',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairsTop','PlankStairsTopBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('PlankStairsTop','PlankStairsTopBR',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chest','Chest','FlipHorizontal','FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chest','Chest',NULL,'FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chest','Chest','FlipHorizontal','BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Chest','Chest',NULL,'BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfShelf','BookshelfFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfShelf','BookshelfFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfShelf','BookshelfBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfShelf','BookshelfBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfBooks','BookshelfBooksFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfBooks','BookshelfBooksFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfBooks','BookshelfBooksBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('BookshelfBooks','BookshelfBooksBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Dresser','DresserFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Dresser','DresserFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Dresser','DresserBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('Dresser','DresserBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GlassFurnace',NULL,NULL,'FR','GlassFurnaceFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GlassFurnace',NULL,'FlipHorizontal','FL','GlassFurnaceFR');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GlassFurnace',NULL,NULL,'BL','GlassFurnaceBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('GlassFurnace',NULL,'FlipHorizontal','BR','GlassFurnaceBL');\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MeatStack','MeatStackFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MeatStack','MeatStackFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MeatStack','MeatStackBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('MeatStack','MeatStackBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SausageStack','SausageStackFR',NULL,'FR',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SausageStack','SausageStackFR','FlipHorizontal','FL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SausageStack','SausageStackBL',NULL,'BL',NULL);\r\nINSERT INTO \"Sprites_Rotations\" (\"ID\",\"BaseSprite\",\"Effect\",\"Rotation\",\"Sprite\") VALUES ('SausageStack','SausageStackBL','FlipHorizontal','BR',NULL);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Pig',NULL,'PigPink',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Pig',NULL,'PigYellow',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygYoung',NULL,'ZygYoungBlue',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygYoung',NULL,'ZygYoungRed',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygYouth',NULL,'ZygYouthBlue',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygYouth',NULL,'ZygYouthRed',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygAdult',NULL,'ZygAdultBlue',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygAdult',NULL,'ZygAdultRed',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygSenior',NULL,'ZygSeniorBlue',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('ZygSenior',NULL,'ZygSeniorRed',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Painting',NULL,'Painting8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('AppleTreeApples',NULL,'AppleTreeApple1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('AppleTreeApples',NULL,'AppleTreeApple2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('AppleTreeApples',NULL,'AppleTreeApple3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('OrangeTreeOranges',NULL,'OrangeTreeOrange1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('OrangeTreeOranges',NULL,'OrangeTreeOrange2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('OrangeTreeOranges',NULL,'OrangeTreeOrange3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Grass',NULL,'Grass1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('Grass',NULL,'Grass5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail','EmptyFloor',NULL,50.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail',NULL,'GrassDetail1',10.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail',NULL,'GrassDetail2',10.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail',NULL,'GrassDetail3',10.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail',NULL,'GrassDetail4',10.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail',NULL,'GrassDetail5',10.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RRedFlower8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail1',NULL,'RBlueFlower8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RYellowFlower8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail2',NULL,'RPurpleFlower8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'ROrangeFlower8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail3',NULL,'RWhiteMushroom8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'RYellowMushroom8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail4',NULL,'ROrangeMushroom8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone0',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone1',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone2',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone3',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone4',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone5',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone6',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone7',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('GrassDetail5',NULL,'RStone8',0.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrass',NULL,'MushroomGrass1',20.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrass',NULL,'MushroomGrass2',20.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrass',NULL,'MushroomGrass3',20.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrass',NULL,'MushroomGrass4',20.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrass',NULL,'MushroomGrass5',20.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrassDetail','EmptyFloor',NULL,75.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrassDetail','MushroomGrassDetail1',NULL,5.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrassDetail','MushroomGrassDetail2',NULL,5.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrassDetail','MushroomGrassDetail3',NULL,5.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrassDetail','MushroomGrassDetail4',NULL,5.0);\r\nINSERT INTO \"Sprites_Random\" (\"ID\",\"BaseSprite\",\"Sprite\",\"Weight\") VALUES ('MushroomGrassDetail','MushroomGrassDetail5',NULL,5.0);\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GroundTorchFlame','GroundTorchFlame1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GroundTorchFlame','GroundTorchFlame2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GroundTorchFlame','GroundTorchFlame3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GroundTorchFlame','GroundTorchFlame4');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PentagramAnim','Pentagram1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PentagramAnim','Pentagram2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PentagramAnim','Pentagram3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PentagramAnim','Pentagram4');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('Sparkles','SparkleFrame1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('Sparkles','SparkleFrame2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('Sparkles','SparkleFrame3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('Sparkles','SparkleFrame4');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonFR','SteamEnginePiston1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonFR','SteamEnginePiston2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonFR','SteamEnginePiston3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonFR','SteamEnginePiston4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerFR','SteamEngineBoilerFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerFR','SteamEngineBoilerFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerFR','SteamEngineBoilerFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerFR','SteamEngineBoilerFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonBL','SteamEnginePiston1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonBL','SteamEnginePiston2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonBL','SteamEnginePiston3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEnginePistonBL','SteamEnginePiston4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerBL','SteamEngineBoilerBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerBL','SteamEngineBoilerBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerBL','SteamEngineBoilerBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('SteamEngineBoilerBL','SteamEngineBoilerBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('VerticalAxle','AxleUD1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('VerticalAxle','AxleUD2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('VerticalAxle','AxleUD3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('VerticalAxle','AxleUD2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('AxleAnim','Axle1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('AxleAnim','Axle2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('AxleAnim','Axle3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('AxleAnim','Axle4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpBase','PumpBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpBase','PumpBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpBase','PumpBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpBase','PumpBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpTop','PumpTop1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpTop','PumpTop2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpTop','PumpTop3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpTop','PumpTop1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpConnectors','PumpPipeConnectors');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpConnectors','PumpPipeConnectors');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpConnectors','PumpPipeConnectors');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('PumpConnectors','PumpPipeConnectors');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1FR','WindmillSail1_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1FR','WindmillSail1_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1FR','WindmillSail1_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1FR','WindmillSail1_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2FR','WindmillSail2_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2FR','WindmillSail2_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2FR','WindmillSail2_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2FR','WindmillSail2_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3FR','WindmillSail3_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3FR','WindmillSail3_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3FR','WindmillSail3_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3FR','WindmillSail3_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4FR','WindmillSail4_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4FR','WindmillSail4_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4FR','WindmillSail4_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4FR','WindmillSail4_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1BL','WindmillSail1_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1BL','WindmillSail1_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1BL','WindmillSail1_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail1BL','WindmillSail1_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2BL','WindmillSail2_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2BL','WindmillSail2_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2BL','WindmillSail2_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail2BL','WindmillSail2_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3BL','WindmillSail3_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3BL','WindmillSail3_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3BL','WindmillSail3_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail3BL','WindmillSail3_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4BL','WindmillSail4_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4BL','WindmillSail4_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4BL','WindmillSail4_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSail4BL','WindmillSail4_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1FR','WindmillSailCloth1_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1FR','WindmillSailCloth1_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1FR','WindmillSailCloth1_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1FR','WindmillSailCloth1_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2FR','WindmillSailCloth2_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2FR','WindmillSailCloth2_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2FR','WindmillSailCloth2_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2FR','WindmillSailCloth2_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3FR','WindmillSailCloth3_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3FR','WindmillSailCloth3_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3FR','WindmillSailCloth3_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3FR','WindmillSailCloth3_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4FR','WindmillSailCloth4_1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4FR','WindmillSailCloth4_2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4FR','WindmillSailCloth4_3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4FR','WindmillSailCloth4_4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1BL','WindmillSailCloth1_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1BL','WindmillSailCloth1_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1BL','WindmillSailCloth1_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth1BL','WindmillSailCloth1_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2BL','WindmillSailCloth2_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2BL','WindmillSailCloth2_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2BL','WindmillSailCloth2_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth2BL','WindmillSailCloth2_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3BL','WindmillSailCloth3_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3BL','WindmillSailCloth3_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3BL','WindmillSailCloth3_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth3BL','WindmillSailCloth3_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4BL','WindmillSailCloth4_1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4BL','WindmillSailCloth4_2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4BL','WindmillSailCloth4_3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WindmillSailCloth4BL','WindmillSailCloth4_4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameFR','WallTorchFlame1FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameFR','WallTorchFlame2FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameFR','WallTorchFlame3FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameFR','WallTorchFlame4FR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameBL','WallTorchFlame1BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameBL','WallTorchFlame2BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameBL','WallTorchFlame3BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchFlameBL','WallTorchFlame4BL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseFR','WallTorchBaseFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseFR','WallTorchBaseFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseFR','WallTorchBaseFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseFR','WallTorchBaseFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseBL','WallTorchBaseBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseBL','WallTorchBaseBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseBL','WallTorchBaseBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('WallTorchBaseBL','WallTorchBaseBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchFlame','BigTorchFlame1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchFlame','BigTorchFlame2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchFlame','BigTorchFlame3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchFlame','BigTorchFlame4');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierFlame','BrazierFlame1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierFlame','BrazierFlame2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierFlame','BrazierFlame3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierFlame','BrazierFlame4');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchBase','BigTorchBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchBase','BigTorchBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchBase','BigTorchBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BigTorchBase','BigTorchBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierBase','BrazierBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierBase','BrazierBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierBase','BrazierBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('BrazierBase','BrazierBase');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceFlame','GlassFurnaceFlame1');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceFlame','GlassFurnaceFlame2');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceFlame','GlassFurnaceFlame3');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceFlame','GlassFurnaceFlame4');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceOven','GlassFurnaceFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceOven','GlassFurnaceFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceOven','GlassFurnaceFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceOven','GlassFurnaceFR');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceBL','GlassFurnaceBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceBL','GlassFurnaceBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceBL','GlassFurnaceBL');\r\nINSERT INTO \"Sprites_Frames\" (\"ID\",\"BaseSprite\") VALUES ('GlassFurnaceBL','GlassFurnaceBL');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodBed',NULL,NULL,'WoodBedFrame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodBed',NULL,NULL,'WoodBedSheets',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FancyBed',NULL,NULL,'FancyWoodBedFrame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FancyBed',NULL,NULL,'FancyWoodBedSheets',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MarketStallWithTop',NULL,NULL,'MarketStallBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MarketStallWithTop',NULL,NULL,'MarketStallTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CarpenterStandWithTools',NULL,NULL,'CarpenterStand',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CarpenterStandWithTools',NULL,NULL,'CarpenterStandTools',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('SawTable_TableSaw',NULL,NULL,'SawTable',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('SawTable_TableSaw',NULL,NULL,'TableSaw',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ThoughtBubbleThirsty',NULL,NULL,'ThoughtBubble',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ThoughtBubbleThirsty',NULL,NULL,'StatusThirsty',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ThoughtBubbleHungry',NULL,NULL,'ThoughtBubble',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ThoughtBubbleHungry',NULL,NULL,'StatusHungry',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ThoughtBubbleCombat',NULL,NULL,'ThoughtBubble',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ThoughtBubbleCombat',NULL,NULL,'StatusCombat',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GroundTorch',NULL,NULL,'GroundTorchFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GroundTorch',NULL,NULL,'GroundTorchBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('SawTableLeft_SawTableBlade',NULL,NULL,'SawTableLeft','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('SawTableLeft_SawTableBlade',NULL,NULL,'SawTableBlade','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AlarmBell',NULL,NULL,'AlarmBellBell',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AlarmBell',NULL,NULL,'AlarmBellBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ForgeWithTop',NULL,NULL,'Forge',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('ForgeWithTop',NULL,NULL,'ForgeTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MoldWithTop',NULL,NULL,'Mold',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MoldWithTop',NULL,NULL,'MoldTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BellowsWithNozzle',NULL,NULL,'Bellows',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BellowsWithNozzle',NULL,NULL,'BellowsNozzle',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FurnaceWithFlame',NULL,NULL,'Furnace',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FurnaceWithFlame',NULL,NULL,'FurnaceFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('KilnWithFlame',NULL,NULL,'Kiln',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('KilnWithFlame',NULL,NULL,'KilnFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinArmLeft',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinHandLeft',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinTorso',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinHead',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinFootLeft',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinFootRight',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinArmRight',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GoblinFR','GoblinHandRight',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FishingRodRack',NULL,NULL,'FishingRack',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FishingRodRack',NULL,NULL,'FishingRods',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceN','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceN','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceE','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceE','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceS','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceS','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNS','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNS','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNS','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceEW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceEW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceEW','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNE','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNE','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNE','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceES','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceES','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceES','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceSW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceSW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceSW','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNW','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceESW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceESW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceESW','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceESW','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNSW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNSW','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNSW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNSW','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNEW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNEW','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNEW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNEW','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNES','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNES','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNES','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceNES','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceRotNESW','BlockFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceRotNESW','BlockFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceRotNESW','BlockFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceRotNESW','BlockFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BlockFenceRotNESW','BlockFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceN','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceN','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceE','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceE','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceS','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceS','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNS','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNS','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNS','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceEW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceEW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceEW','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNE','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNE','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNE','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceES','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceES','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceES','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceSW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceSW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceSW','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNW','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceESW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceESW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceESW','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceESW','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNSW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNSW','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNSW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNSW','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNEW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNEW','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNEW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNEW','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNES','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNES','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNES','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceNES','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceRotNESW','CobbleStoneFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceRotNESW','CobbleStoneFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceRotNESW','CobbleStoneFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceRotNESW','CobbleStoneFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CobbleStoneFenceRotNESW','CobbleStoneFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceN','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceN','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceE','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceE','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceS','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceS','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNS','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNS','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNS','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceEW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceEW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceEW','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNE','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNE','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNE','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceES','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceES','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceES','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceSW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceSW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceSW','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNW','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceESW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceESW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceESW','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceESW','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNSW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNSW','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNSW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNSW','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNEW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNEW','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNEW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNEW','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNES','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNES','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNES','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceNES','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceRotNESW','WoodFenceWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceRotNESW','WoodFenceNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceRotNESW','WoodFencePost',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceRotNESW','WoodFenceEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WoodFenceRotNESW','WoodFenceSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CombinedRoof',NULL,NULL,'Rafter',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('CombinedRoof',NULL,NULL,'Roofing',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Knife',NULL,NULL,'KnifeBlade',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Knife',NULL,NULL,'KnifeHilt',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Pickaxe',NULL,NULL,'PickaxeHead',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Pickaxe',NULL,NULL,'PickaxeBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FellingAxe',NULL,NULL,'FellingAxeHead',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('FellingAxe',NULL,NULL,'FellingAxeBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_AxeBench','WorkshopTable',NULL,NULL,'Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_AxeBench','AxeBenchFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_KitchenTableTop',NULL,NULL,'WorkshopTable',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_KitchenTableTop',NULL,NULL,'KitchenTableTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Hammer',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Hammer',NULL,NULL,'HammerTableTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_RawGem',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_RawGem','RawGem','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Gem',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Gem','Gem','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_JewelryPile',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_JewelryPile','JewelryPile','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Vise',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Vise','ViseTableTop',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Cloth',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Cloth','Fiber','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ClothRollTableTop',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ClothRollTableTop','ClothRollTableTop','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ShearsTableTop',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ShearsTableTop','ShearsTableTopFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_String',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_String','String','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Statuette',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Statuette','Statuette','0 -8',NULL,'Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Skull',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Skull','Skull','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_BoneNeedle',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_BoneNeedle','BoneNeedle','0 -4',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ChiselTableTop',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ChiselTableTop',NULL,NULL,'ChiselTableTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Meat',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Meat','Meat','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ButcherTableTop',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ButcherTableTop',NULL,NULL,'ButcherTableTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Hammer','HammerHead','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Hammer','HammerBase','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ProspectorOre',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ProspectorOre','ProspectorTableOreTop',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ProspectorSliver',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_ProspectorSliver','ProspectorTableSliverTop',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilRamp',NULL,NULL,'SoilRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilRamp',NULL,NULL,'GrassRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilRampTop',NULL,NULL,'SoilRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilRampTop',NULL,NULL,'GrassRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilCornerRamp',NULL,NULL,'SoilCornerRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilCornerRamp',NULL,NULL,'GrassCornerRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilCornerRampTop',NULL,NULL,'SoilCornerRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilCornerRampTop',NULL,NULL,'GrassCornerRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilURamp',NULL,NULL,'SoilURamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilURamp',NULL,NULL,'GrassURamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilURampTop',NULL,NULL,'SoilURampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassSoilURampTop',NULL,NULL,'GrassURampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AppleTreeTopWithFruit',NULL,NULL,'AppleTreeTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AppleTreeTopWithFruit',NULL,NULL,'AppleTreeApples',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AppleTreeTopCornerWithFruit',NULL,NULL,'AppleTreeTopCorner',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AppleTreeTopCornerWithFruit',NULL,NULL,'AppleTreeApples',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AppleTreeMiddleWithFruit',NULL,NULL,'AppleTreeMiddle',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AppleTreeMiddleWithFruit',NULL,NULL,'AppleTreeApples',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeTopWithFruit',NULL,NULL,'OrangeTreeTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeTopWithFruit',NULL,NULL,'OrangeTreeOranges',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeMiddleCornerWithFruit',NULL,NULL,'OrangeTreeMiddleCorner',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeMiddleCornerWithFruit',NULL,NULL,'OrangeTreeOranges',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeTopCornerWithFruit',NULL,NULL,'OrangeTreeTopCorner',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeTopCornerWithFruit',NULL,NULL,'OrangeTreeOranges',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeMiddleWithFruit',NULL,NULL,'OrangeTreeMiddle',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('OrangeTreeMiddleWithFruit',NULL,NULL,'OrangeTreeOranges',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassWithDetail',NULL,NULL,'Grass',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GrassWithDetail',NULL,NULL,'GrassDetail',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassWithDetail',NULL,NULL,'MushroomGrass',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassWithDetail',NULL,NULL,'MushroomGrassDetail',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilRamp',NULL,NULL,'SoilRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilRamp',NULL,NULL,'MushroomGrassRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilRampTop',NULL,NULL,'SoilRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilRampTop',NULL,NULL,'MushroomGrassRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilCornerRamp',NULL,NULL,'SoilCornerRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilCornerRamp',NULL,NULL,'MushroomGrassCornerRamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilCornerRampTop',NULL,NULL,'SoilCornerRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilCornerRampTop',NULL,NULL,'MushroomGrassCornerRampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilURamp',NULL,NULL,'SoilURamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilURamp',NULL,NULL,'MushroomGrassURamp',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilURampTop',NULL,NULL,'SoilURampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('MushroomGrassSoilURampTop',NULL,NULL,'MushroomGrassURampTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Sword',NULL,NULL,'SwordBlade',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Sword',NULL,NULL,'SwordBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GearBox',NULL,NULL,'GearBoxBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GearBox',NULL,NULL,'GearBoxFrame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('SteamEngine',NULL,NULL,'SteamEngineBoiler',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('SteamEngine',NULL,NULL,'SteamEnginePiston',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeN','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeN','PipePost','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeE','PipePost','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeE','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeS','PipePost','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeS','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeW','PipePost','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNE','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNE','PipeFittingNE','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNE','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeES','PipeFittingES','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeES','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeES','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeSW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeSW','PipeFittingSW','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeSW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNW','PipeFittingNW','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeESW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeESW','PipeFittingESW','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeESW','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeESW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNSW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNSW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNSW','PipeFittingNSW','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNSW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNEW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNEW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNEW','PipeFittingNEW','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNEW','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNES','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNES','PipeFittingNES','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNES','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeNES','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeRotNESW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeRotNESW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeRotNESW','PipePost','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeRotNESW','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeRotNESW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Pump',NULL,NULL,'PumpConnectors',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Pump',NULL,NULL,'PumpBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitN','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitN','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitE','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitE','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitS','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitS','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNE','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNE','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNE','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitES','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitES','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitES','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitSW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitSW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitSW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitESW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitESW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitESW','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitESW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNSW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNSW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNSW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNSW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNEW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNEW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNEW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNEW','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNES','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNES','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNES','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNES','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitRotNESW','PipeWest','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitRotNESW','PipeNorth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitRotNESW','PipeFittingItem','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitRotNESW','PipeEast','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitRotNESW','PipeSouth','','','');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNS','PipeNorth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNS','PipeFittingItem',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitNS','PipeSouth',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitEW','PipeWest',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitEW','PipeFittingItem',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('PipeExitEW','PipeEast',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Pump',NULL,NULL,'PumpTop',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('LeverOn',NULL,NULL,'LeverBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('LeverOn','LeverOnFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('LeverOff',NULL,NULL,'LeverBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('LeverOff','LeverOffFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Wrench',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Wrench','Wrench','0 -8',NULL,'Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Blueprint',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Blueprint','BlueprintTableTop','0 -1',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Bar',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Bar','Bar','0 -8',NULL,'Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Wheel',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Wheel','Gear','0 -8',NULL,'Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonFR','AutomatonLeftFootFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonFR','AutomatonRightFootFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonFR','AutomatonTorsoFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonFR','AutomatonLeftArmFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonFR','AutomatonRightArmFR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonBR','AutomatonLeftFootBR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonBR','AutomatonRightFootBR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonBR','AutomatonTorsoBR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonBR','AutomatonLeftArmBR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('AutomatonBR','AutomatonRightArmBR',NULL,NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BoneBed',NULL,NULL,'BoneBedFrame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BoneBed',NULL,NULL,'BoneBedSheets',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail1',NULL,'0 0','WindmillSailFrame1',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail1',NULL,'0 0','WindmillSailCloth1',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail2',NULL,'0 0','WindmillSailFrame2',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail2',NULL,'0 0','WindmillSailCloth2',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail3',NULL,'0 0','WindmillSailFrame3',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail3',NULL,'0 0','WindmillSailCloth3',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail4',NULL,'0 0','WindmillSailFrame4',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WindmillSail4',NULL,'0 0','WindmillSailCloth4',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Warhammer','WarhammerHead','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Warhammer','WarhammerBase','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Claymore','ClaymoreBlade','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Claymore','ClaymoreBase','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('HandAxe','HandAxeHead','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('HandAxe','HandAxeBase','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BattleAxe','BattleAxeHead','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BattleAxe','BattleAxeBase','0 0',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WallTorch',NULL,NULL,'WallTorchBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WallTorch',NULL,NULL,'WallTorchFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Bookshelf',NULL,NULL,'BookshelfShelf',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Bookshelf',NULL,NULL,'BookshelfBooks',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BigTorch',NULL,NULL,'BigTorchBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('BigTorch',NULL,NULL,'BigTorchFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Brazier',NULL,NULL,'BrazierBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('Brazier',NULL,NULL,'BrazierFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GlassFurnaceFR',NULL,NULL,'GlassFurnaceOven','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('GlassFurnaceFR',NULL,NULL,'GlassFurnaceFlame',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Mosaic',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_Mosaic','MosaicTile','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_GlassIngot',NULL,NULL,'WorkshopTable','Material');\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('WorkshopTable_GlassIngot','GlassIngot','0 -8',NULL,NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('UIPickaxe',NULL,NULL,'UIPickaxeHead',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('UIPickaxe',NULL,NULL,'UIPickaxeBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('UIFellingAxe',NULL,NULL,'UIFellingAxeHead',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('UIFellingAxe',NULL,NULL,'UIFellingAxeBase',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('UISword',NULL,NULL,'UISwordBlade',NULL);\r\nINSERT INTO \"Sprites_Combine\" (\"ID\",\"BaseSprite\",\"Offset\",\"Sprite\",\"Tint\") VALUES ('UISword',NULL,NULL,'UISwordBase',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Chair',NULL,'Stone','StoneChair');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Chair',NULL,'Bone','BoneChair');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Chair',NULL,'Wood','WoodChair');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('StairsTop',NULL,'Soil','SoilStairsTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('StairsTop',NULL,'Stone','StoneStairsTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Stairs',NULL,'Soil','SoilStairs');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Stairs',NULL,'Stone','StoneStairs');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Door',NULL,'Wood','WoodDoor');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Door',NULL,'Stone','StoneDoor');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Table',NULL,'Wood','WoodTable');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Table','StoneTable','Stone',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Table','BoneTable','Bone',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughFloor','RoughSoilFloor','Soil',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughFloor','RoughSandFloor','Sand',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughFloor','RoughClayFloor','Clay',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughFloor',NULL,'Stone','RoughStoneFloor2');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWall','RoughSoilWall','Soil',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWall','RoughSandWall','Sand',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWall','RoughClayWall','Clay',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWall',NULL,'Stone','RoughStoneWall2');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWallShort','RoughSoilWallShort','Soil',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWallShort','RoughSandWallShort','Sand',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWallShort','RoughClayWallShort','Clay',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RoughWallShort',NULL,'Stone','RoughStoneFloor3');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Floor',NULL,'Stone',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Floor','MetalFloor','Metal',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Floor','LogFloor','Wood',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('LogFloor','LogFloor','Wood',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Wall',NULL,'Stone',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Wall','MetalWall','Metal',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Wall','LogWall','Wood',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('LogWall','LogWall','Wood',NULL);\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Ramp',NULL,'Soil','SoilRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Ramp',NULL,'Sand','SoilRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Ramp',NULL,'Clay','ClayRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Ramp',NULL,'Stone','StoneRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRamp',NULL,'Soil','SoilCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRamp',NULL,'Sand','SoilCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRamp',NULL,'Clay','ClayCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRamp',NULL,'Stone','StoneCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URamp',NULL,'Soil','SoilURamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URamp',NULL,'Sand','SoilURamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URamp',NULL,'Clay','ClayURamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URamp',NULL,'Stone','StoneURamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RampTop',NULL,'Soil','SoilRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RampTop',NULL,'Sand','SoilRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RampTop',NULL,'Clay','ClayRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('RampTop',NULL,'Stone','StoneRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRampTop',NULL,'Soil','SoilCornerRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRampTop',NULL,'Sand','SoilCornerRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRampTop',NULL,'Clay','ClayCornerRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('CornerRampTop',NULL,'Stone','StoneCornerRampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URampTop',NULL,'Soil','SoilURampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URampTop',NULL,'Sand','SoilURampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URampTop',NULL,'Clay','ClayURampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('URampTop',NULL,'Stone','StoneURampTop');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('OuterCornerRamp',NULL,'Soil','SoilOuterCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('OuterCornerRamp',NULL,'Sand','SoilOuterCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('OuterCornerRamp',NULL,'Clay','ClayOuterCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('OuterCornerRamp',NULL,'Stone','StoneOuterCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('OuterCornerRamp',NULL,'Grain','ThatchOuterCornerRamp');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Bed',NULL,'Wood','WoodBed');\r\nINSERT INTO \"Sprites_ByMaterialTypes\" (\"ID\",\"BaseSprite\",\"MaterialType\",\"Sprite\") VALUES ('Bed',NULL,'Bone','BoneBed');\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Panda','Rot90','Panda',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Rabbit','Rot90','Rabbit',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Chicken','Rot90','Chicken',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','PigPink','Rot90','PigPink',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','PigYellow','Rot90','PigYellow',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Sheep','Rot90','Sheep',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Woodlouse','Rot90','Woodlouse',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Badger','Rot90','Badger',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Lizzard','Rot90','Lizzard',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','BlackBear','Rot90','BlackBear',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Llama','Rot90','Llama',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Yak','Rot90','Yak',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Emu','Rot90','Emu',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Spider','Rot90','Spider',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Beetle','Rot90','Beetle',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','RabbitYoung','Rot90','RabbitYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','ChickenYoung','Rot90','ChickenYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','PigYoung','Rot90','PigYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','SheepYoung','Rot90','SheepYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','LlamaYoung','Rot90','LlamaYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','YakYoung','Rot90','YakYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','EmuYoung','Rot90','EmuYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Duck','Rot90','Duck',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Cow','Rot90','Cow',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','CowYoung','Rot90','CowYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','DuckYoung','Rot90','DuckYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Goose','Rot90','Goose',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','GooseYoung','Rot90','GooseYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Shepherd','Rot90','Shepherd',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','ShepherdYoung','Rot90','ShepherdYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','CatTabby','Rot90','CatTabby',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','CatBlack','Rot90','CatBlack',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Porcupine','Rot90','Porcupine',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Fox','Rot90','Fox',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Wolf','Rot90','Wolf',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Stag','Rot90','Stag',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Roe','Rot90','Roe',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Goat','Rot90','Goat',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','GoatYoung','Rot90','GoatYoung',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','Squirrel','Rot90','Squirrel',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','GreyFish','Rot90','GreyFish',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','GreenFish','Rot90','GreenFish',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Corpse','GreenFishBack','Rot90','GreenFishBack',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('MonsterCorpse',NULL,'Rot90','Goblin','GoblinFR');\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Fruit','Melon','none','Melon',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Fruit','Pumpkin','none','Pumpkin',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Fruit','Pineapple','none','Pineapple',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Fruit','Strawberry','none','Strawberry',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Fruit','Apple','none','Apple',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Fruit','Orange','none','Orange',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Carrot','none','Carrot',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Onion','none','Onion',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Potato','none','Potato',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Cabbage','none','Cabbage',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Asparagus','none','Asparagus',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Broccoli','none','Broccoli',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Cauliflower','none','Cauliflower',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Cucumber','none','Cucumber',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Garlic','none','Garlic',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Parsnip','none','Parsnip',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Radish','none','Radish',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Turnip','none','Turnip',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Lettuce','none','Lettuce',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Sugarbeet','none','Sugarbeet',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Peas','none','Peas',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','BeetRoot','none','BeetRoot',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Corn','none','Corn',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Leek','none','Leek',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Beans','none','Beans',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Artichoke','none','Artichoke',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Bottlegourd','none','Bottlegourd',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Woad','none','Woad',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Tomato','none','Tomato',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Vegetable','Capsicum','none','Capsicum',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Berries','Blackberry','none','Blackberry',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Berries','Grape','none','Grape',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Leaves','Tea','none','Tea',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Leaves','Tobacco','none','Tobacco',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Leaves','DyersWeed','none','DyersWeed',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Mushroom',NULL,'none','none',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','CarrotPlant','none','Carrot',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','OnionPlant','none','Onion',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','PotatoPlant','none','Potato',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','CabbagePlant','none','Cabbage',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','AsparagusPlant','none','Asparagus',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','BroccoliPlant','none','Broccoli',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','CauliflowerPlant','none','Cauliflower',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','CucumberPlant','none','Cucumber',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','RicePlant','none','Rice',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','GarlicPlant','none','Garlic',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','ParsnipPlant','none','Parsnip',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','RadishPlant','none','Radish',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','TurnipPlant','none','Turnip',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','LettucePlant','none','Lettuce',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','MelonPlant','none','Melon',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','SugarbeetPlant','none','Sugarbeet',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','PumpkinPlant','none','Pumpkin',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','PeasPlant','none','Peas',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','BeetRoot','none','BeetRoot',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','StrawberryPlant','none','Strawberry',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('Plant','CottonPlant','none','Cotton',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','CarrotPlantWithFruit','none','Carrot',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','OnionPlantWithFruit','none','Onion',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','PotatoPlantWithFruit','none','Potato',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','CabbagePlantWithFruit','none','Cabbage',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','AsparagusPlantWithFruit','none','Asparagus',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','BroccoliPlantWithFruit','none','Broccoli',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','CauliflowerPlantWithFruit','none','Cauliflower',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','CucumberPlantWithFruit','none','Cucumber',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','RicePlantWithFruit','none','Rice',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','GarlicPlantWithFruit','none','Garlic',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','ParsnipPlantWithFruit','none','Parsnip',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','RadishPlantWithFruit','none','Radish',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','TurnipPlantWithFruit','none','Turnip',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','LettucePlantWithFruit','none','Lettuce',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','MelonPlantWithFruit','none','Melon',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','SugarbeetPlantWithFruit','none','Sugarbeet',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','PumpkinPlantWithFruit','none','Pumpkin',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','PeasPlantWithFruit','none','Peas',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','BeetRoot','none','BeetRoot',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','StrawberryPlantWithFruit','none','Strawberry',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantWithFruit','CottonPlantWithFruit','none','Cotton',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','TeaPlant','none','Tea',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','TobaccoPlant','none','Tobacco',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','PineapplePlant','none','Pineapple',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','CornPlant','none','Corn',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','LeekPlant','none','Leek',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','BeansPlant','none','Beans',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','BlackberryPlant','none','Blackberry',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','ArtichokePlant','none','Artichoke',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','BottlegourdPlant','none','Bottlegourd',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','WoadPlant','none','Woad',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','DyersWeedPlant','none','DyersWeed',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','GrapePlant','none','Grape',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','TomatoPlant','none','Tomato',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','CapsicumPlant','none','Capsicum',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','BarleyPlant','none','Barley',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','OatPlant','none','Oat',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','MilletPlant','none','Millet',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLarge','WheatPlant','none','Wheat',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','TeaPlantWithFruit','none','Tea',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','TobaccoPlantWithFruit','none','Tobacco',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','PineapplePlantWithFruit','none','Pineapple',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','CornPlantWithFruit','none','Corn',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','LeekPlantWithFruit','none','Leek',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','BeansPlantWithFruit','none','Beans',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','BlackberryPlantWithFruit','none','Blackberry',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','ArtichokePlantWithFruit','none','Artichoke',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','BottlegourdPlantWithFruit','none','Bottlegourd',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','WoadPlantWithFruit','none','Woad',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','DyersWeedPlantWithFruit','none','DyersWeed',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','GrapePlantWithFruit','none','Grape',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','TomatoPlantWithFruit','none','Tomato',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','CapsicumPlantWithFruit','none','Capsicum',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','BarleyPlantWithFruit','none','Barley',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','OatPlantWithFruit','none','Oat',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','MilletPlantWithFruit','none','Millet',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('PlantLargeWithFruit','WheatPlantWithFruit','none','Wheat',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','BasaltWall','none','Basalt',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','GraniteWall','none','Granite',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','SerpentineWall','none','Serpentine',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','BauxiteWall','none','Bauxite',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','SandstoneWall','none','Sandstone',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','LapisWall','none','LapisLazuli',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneWall2','MarbleWall','none','Marble',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','BasaltFloor','none','Basalt',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','GraniteFloor','none','Granite',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','SerpentineFloor','none','Serpentine',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','BauxiteFloor','none','Bauxite',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','SandstoneFloor','none','Sandstone',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','LapisFloor','none','LapisLazuli',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor2','MarbleFloor','none','Marble',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','BasaltFloor','none','Basalt',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','GraniteFloor','none','Granite',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','SerpentineFloor','none','Serpentine',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','BauxiteFloor','none','Bauxite',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','SandstoneFloor','none','Sandstone',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','LapisFloor','none','LapisLazuli',NULL);\r\nINSERT INTO \"Sprites_ByMaterials\" (\"ID\",\"BaseSprite\",\"Effect\",\"MaterialID\",\"Sprite\") VALUES ('RoughStoneFloor3','MarbleFloor','none','Marble',NULL);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SelectionFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SelectionWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SolidSelectionFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SolidSelectionWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SolidSelectionWallShort',0,'SolidSelectionWall',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MiningJobWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MiningJobWallShort',0,'MiningJobWall',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SelectionWallShort',0,'SelectionWall',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mattress',0,'MattressFR',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodBedFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodBedSheets',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodBed',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FancyWoodBedFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FancyWoodBedSheets',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FancyBed',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodChair',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneChair',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneChair',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Chair',0,NULL,0,'0 0',0,'Material','Wood',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StairsTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Stairs',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterLeftWall_',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterRightWall_',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTree',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTreeNoLeaves',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTree',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeNoLeaves',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTreeNoLeaves',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sapling',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TilledSoil',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantedSoil',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Statue',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Door',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Table',0,NULL,0,'0 0',0,'Material','Wood',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Well',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WellTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawSoil',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawStone',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawWood',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawCoal',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawOre',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawGem',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RawHide',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Block',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Plank',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bar',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Gem',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bolt',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bandage',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallWithTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarpenterStandTools',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarpenterStand',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarpenterStandWithTools',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TableSaw',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawTable',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawTable_TableSaw',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Workbench',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Workmat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AxeBench',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Keg',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopWaterTub',0,'WorkshopWaterTub',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Distill',0,'Distill',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TanningRack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodPile',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GiantStoneBlock',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneBlockPile',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThoughtBubble',0,'ThoughtBubble',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StatusTired',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StatusSleeping',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThoughtBubbleThirsty',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThoughtBubbleHungry',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThoughtBubbleCombat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StatusThirsty',0,'StatusThirsty',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StatusHungry',0,'StatusHungry',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StatusCombat',0,'StatusCombat',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LittleBlood1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LittleBlood2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BigBlood1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BigBlood2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Crate',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Barrel',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bag',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Egg',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Meat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bread',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sausage',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sandwich',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bone',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Skull',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GroundTorch',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GroundTorchBase',0,'GroundTorchBase',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GroundTorchFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Coin',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Statuette',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SelectionFloorTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SelectionWallTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChiseledBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChiseledBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PetRock',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Gear',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CuttingWheel',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Spring',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HatchFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HatchFrameItem',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpikeTrapSpike2',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpikeTrapItemSpike',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BladeTrapBlade3',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BladeTrapItemBlade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClaymoreBlade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PuzzleBox',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Clipping',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpikeTrapSpike1',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BladeTrapBlade1',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BladeTrapBlade2',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StonePillar',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AmmoPouch',0,'GnomeAmmoPouch',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreTorso',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreHead',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreArmRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreArmLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreHandRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreHandLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreFootRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OgreFootLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreTorso',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreHeadRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreHeadLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreArmRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreArmLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreHandRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreHandLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreFootRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlueOgreFootLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantTorso',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantHead',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantAntennaeRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantAntennaeLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantArmRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantArmLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantLegRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MantLegLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BeetleTorso',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BeetleHead',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cocoon',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieTorso',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieHead',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieArmRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieArmLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieHandRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieHandLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieFootRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZombieFootLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonTorso',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonHead',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonArmRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonArmLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonHandRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonHandLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonFootRight',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkeletonFootLeft',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('String',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillBlade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cylinder',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Spike',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grain',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Chisel',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Wrench',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StrawBed',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ArmorPlate',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherPanel',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherStrip',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneNeedle',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleOnGround',0,'Apple',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlankWall',0,'PlankWall',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlankFloor',0,'PlankFloor',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StarEngravedBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StarEngravedBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpiralEngravedBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpiralEngravedBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MoonEngravedBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MoonEngravedBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterEngravedBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterEngravedBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('EngravedBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('EngravedBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneShirt',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MechanicalWallClosed',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpScrew1',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpScrew2',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpScrew3',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpScrew4',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Screw',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawTableLeft_SawTableBlade',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawTableLeft',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawTableRight',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawTableBlade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CrateLog',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CratePlank',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawHorse',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ShearsTableTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClothRollTableTop',0,NULL,0,'0 8',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('JewelryPile',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoltRoundPile',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MusketRoundPile',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MetalSliver',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTree',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeNoLeaves',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomPlant',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomItem',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cheese',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Omelette',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FishingRod',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AlarmBellBase',0,'AlarmBellBase',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AlarmBellBell',0,'AlarmBellBell',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AlarmBell',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TowerShieldBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TowerShield',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ScaffoldFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Scaffold',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bucket',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sack',0,'Sack',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GolemArmRight',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GolemArmLeft',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GolemLegRight',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GolemLegLeft',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFloorFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodCrossFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodVFloorFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodVFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodPanelledFloorFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodPanelledFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmoothStoneFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmoothStoneWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CeramicFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CeramicWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarvedStoneFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarvedStoneWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Silica',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughSoilWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughClayWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughStoneWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LogWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FancyBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarvedStoneWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlankWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MetalWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThatchWall',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThatchFloor',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MetalHighlightWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChiseledBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StarEngravedBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpiralEngravedBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MoonEngravedBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterEngravedBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('EngravedBlockWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThatchWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmoothStoneWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CeramicWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarvedWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FancyBlockFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FancyBlockWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('EmbeddedOre',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('EmbeddedGem',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LavaFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Forge',0,'Forge',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ForgeTop',0,'ForgeTop',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ForgeWithTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mold',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MoldTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MoldWithTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bellows',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BellowsNozzle',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BellowsWithNozzle',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CoalPile',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrePile',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Furnace',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FurnaceFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FurnaceWithFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Kiln',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KilnFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KilnWithFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Anvil',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WaterTrough',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BeeHiveEmpty',0,'BeeHiveEmpty',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BeeHiveFull',0,'BeeHiveFull',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Trough',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Shed',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MetalBarPile',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GreenFish',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Corpse',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Panda',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Rabbit',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RabbitYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Chicken',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChickenYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Pig',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PigPink',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PigYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PigYellow',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sheep',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Woodlouse',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Badger',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Lizzard',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlackBear',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Llama',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LlamaYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Emu',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('EmuYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cow',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CowYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Yak',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('YakYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Spider',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Beetle',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Duck',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DuckYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Goose',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GooseYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Shepherd',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ShepherdYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CatTabby',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CatBlack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Porcupine',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Fox',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Wolf',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Stag',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Roe',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Goat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GoatYoung',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Squirrel',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Snake',0,'Snake',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GreyFish',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MonsterCorpse',0,NULL,0,'0 0',1,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Goblin',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GoblinFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CrystalSnake',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygYoung',0,NULL,1,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygYoungBlue',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygYoungRed',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygYouth',0,NULL,1,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygYouthBlue',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygYouthRed',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygAdult',0,NULL,1,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygAdultBlue',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygAdultRed',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygSenior',0,NULL,1,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygSeniorBlue',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ZygSeniorRed',0,NULL,0,'0 0',0,NULL,NULL,1);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Fruit',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Vegetable',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Berries',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Leaves',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Plant',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantWithFruit',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantLarge',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantLargeWithFruit',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantGrowHelper1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantGrowHelper2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlantGrowHelper3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Seed',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Wheat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Fiber',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineCone',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Oak',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowSeed',0,'Seed',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StrawMushroom',0,'StrawMushroom',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodMushroom',0,'WoodMushroom',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FibreMushroom',0,'FibreMushroom',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrainMushroom',0,'GrainMushroom',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Pigment',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DyedCloth',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodTub',0,'WoodTub',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Dye',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Dresser',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cabinet',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Painting8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TrainingDummy',0,'TrainingDummy',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Wheelbarrow',0,'Wheelbarrow',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FishingFishRack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FishingRack',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FishingRods',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FishingRodRack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FishingVat',0,'FishingVat',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockWall',0,'BlockWall100',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFloor25',0,'BlockFloor25',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFloor50',0,'BlockFloor50',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFloor75',0,'BlockFloor75',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFloor100',0,'BlockFloor100',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Palisade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PalisadeTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFence',0,'BlockFencePost',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceN',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceNS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceNE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceNW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceNSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceNEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceNES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRot',0,'BlockFencePost',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotN',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlockFenceRotNESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFence',0,'CobbleStoneFencePost',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceN',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceNS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceNE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceNW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceNSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceNEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceNES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRot',0,'CobbleStoneFencePost',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotN',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CobbleStoneFenceRotNESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFence',0,'WoodFencePost',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceN',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceNS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceNE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceNW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceNSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceNEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceNES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRot',0,'WoodFencePost',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotN',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNS',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNE',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNSW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNEW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNES',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodFenceRotNESW',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Rafter',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Roofing',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CombinedRoof',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KnifeBlade',0,'KnifeBlade',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KnifeHilt',0,'KnifeHilt',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Hilt',0,'KnifeHilt',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Knife',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Pickaxe',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PickaxeHead',0,'PickaxeHead',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PickaxeBase',0,'PickaxeBase',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FellingAxe',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FellingAxeBase',0,'FellingAxeBase',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FellingAxeHead',0,'FellingAxeHead',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_AxeBench',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_KitchenTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Hammer',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_RawGem',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Gem',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_JewelryPile',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Vise',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Cloth',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_ClothRollTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_ShearsTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_String',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Statuette',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Skull',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_BoneNeedle',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_ChiselTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChiselTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Meat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_ButcherTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ButcherTableTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KitchenTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HammerTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('File',0,'Sword',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HammerHead',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Loom',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_ProspectorOre',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_ProspectorSliver',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SwordBlade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HandAxeHead',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Shield',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BattleAxeHead',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WarhammerHead',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SwordBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HandAxeBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HammerBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ShieldBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BattleAxeBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WarhammerBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClaymoreBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlunderbussBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BlunderbussBarrel',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PistolBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PistolBarrel',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CrossbowBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Crossbow',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughStoneWall',0,'RoughStoneWall',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughStoneFloor',0,'RoughStoneFloor',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Floor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LogFloor',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Wall',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LogWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Ramp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('URamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CornerRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('URampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThatchRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThatchRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayCornerRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneCornerRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayURamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneURamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayRampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneRampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayCornerRampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneCornerRampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayURampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneURampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassSoilRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassSoilRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassSoilCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassSoilCornerRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassSoilURamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassSoilURampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OuterCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilOuterCornerRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClayOuterCornerRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneOuterCornerRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThatchOuterCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeTopWithFruit',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeTopCornerWithFruit',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeTopCorner',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeMiddle',0,'AppleTreeMiddle',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeMiddleWithFruit',0,NULL,1,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeMiddleTop',0,'AppleTreeMiddle',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeBottom',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeBottomCorner',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeTrunkMiddle',0,'AppleTreeTrunkMiddle',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeTrunkBottom',0,'AppleTreeTrunkBottom',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeApples',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeApple1',0,'AppleTreeApple1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeApple2',0,'AppleTreeApple2',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AppleTreeApple3',0,'AppleTreeApple3',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTrunk1',0,'PineTrunk1',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTrunk2',0,'PineTrunk2',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTree1',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTree2',0,NULL,0,'0 -6',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTree3',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTree4',0,NULL,0,'0 -2',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PineTop',0,'PineTreeTop',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeTopWithFruit',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeMiddleCornerWithFruit',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeTopCornerWithFruit',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeTopCorner',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeMiddleCorner',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeMiddle',0,'OrangeTreeMiddle',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeMiddleWithFruit',0,NULL,1,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeMiddleTop',0,'OrangeTreeMiddle',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeBottom',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeBottomCorner',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeTrunkMiddle',0,'OrangeTreeTrunkMiddle',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeTrunkBottom',0,'OrangeTreeTrunkBottom',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeOranges',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeOrange1',0,'OrangeTreeOrange1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeOrange2',0,'OrangeTreeOrange2',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OrangeTreeOrange3',0,'OrangeTreeOrange3',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree1',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree2',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree3',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree4',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree5',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree6_1',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree7',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree8',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree9',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree10',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree11',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree12_1',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree13',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree14',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree21',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree22',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree23',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree24',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree25',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree26',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree27',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree28',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree29',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree210',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree211',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree212',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree213',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree214',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree6_1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree9',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree10',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree11',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree12_1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree13',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree14',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree21',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree22',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree23',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree24',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree25',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree26',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree27',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree28',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree29',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree210',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree211',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree212',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree213',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree214',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassWithDetail',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Grass',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassDetail',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RRedFlower8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RBlueFlower8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowFlower8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RPurpleFlower8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeFlower8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RWhiteMushroom8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RYellowMushroom8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ROrangeMushroom8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone0',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RStone8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassDetail1',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassDetail2',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassDetail3',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassDetail4',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassDetail5',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassOuterCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassCornerRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassURamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrassURampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilRampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilCornerRamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilCornerRampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilURamp',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilURampTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Pentagram',0,'Pentagram1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PentagramAnim',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sparkles',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassWithDetail',0,NULL,1,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrass',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrass1',0,'MushroomGrass1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrass2',0,'MushroomGrass2',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrass3',0,'MushroomGrass3',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrass4',0,'MushroomGrass4',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrass5',0,'MushroomGrass5',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassDetail',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CrystalPole',0,'CrystalPole',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CrystalShroom',0,'CrystalShroom',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassCornerRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassURamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassURampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassSoilRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassSoilRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassSoilCornerRamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassSoilCornerRampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassSoilURamp',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MushroomGrassSoilURampTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom1_1',0,'Mushroom1_1',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom1_2',0,'Mushroom1_2',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom1_3',0,'Mushroom1_3',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom1_4',0,'Mushroom1_4',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_1',0,'Mushroom2_1',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_2',0,'Mushroom2_2',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_3',0,'Mushroom2_3',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_4',0,'Mushroom2_4',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_5',0,'Mushroom2_5',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_6',0,'Mushroom2_6',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_7',0,'Mushroom2_7',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_8',0,'Mushroom2_8',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_6_2',0,'Mushroom2_6',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_7_2',0,'Mushroom2_7',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_8_2',0,'Mushroom2_8',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_9',0,'Mushroom2_9',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_10',0,'Mushroom2_10',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_4_2',0,'Mushroom2_4',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_9_2',0,'Mushroom2_9',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_10_2',0,'Mushroom2_10',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_11_2',0,'Mushroom2_11',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_12_2',0,'Mushroom2_12',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_11',0,'Mushroom2_11',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_12',0,'Mushroom2_12',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_13',0,'Mushroom2_13',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_14',0,'Mushroom2_14',0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_15',0,'Mushroom2_15',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_16',0,'Mushroom2_16',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_17',0,'Mushroom2_17',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_18',0,'Mushroom2_18',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_19',0,'Mushroom2_19',0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_20',0,'Mushroom2_20',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_21',0,'Mushroom2_21',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_22',0,'Mushroom2_22',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_23',0,'Mushroom2_23',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_24',0,'Mushroom2_24',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_25',0,'Mushroom2_25',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_26',0,'Mushroom2_26',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_27',0,'Mushroom2_27',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_28',0,'Mushroom2_28',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_29',0,'Mushroom2_29',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_30',0,'Mushroom2_30',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_31',0,'Mushroom2_31',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_32',0,'Mushroom2_32',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_33',0,'Mushroom2_33',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_34',0,'Mushroom2_34',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Breastplate',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Helmet',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree6_2',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree6_3',0,NULL,0,'0 -8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree12_2',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OakTree12_3',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree6_2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree6_3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree12_2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WillowTree12_3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UprightWeaponStand','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherArmorHead',0,'LeatherArmorHead',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherArmorChest',0,'LeatherArmorChest',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherArmorArms',0,'LeatherArmorArms',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherArmorLegs',0,'LeatherArmorLegs',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherArmorHands',0,'LeatherArmorHands',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherArmorFeet',0,'LeatherArmorFeet',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChainArmorHead',0,'ChainArmorHead',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChainArmorChest',0,'ChainArmorChest',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChainArmorArms',0,'ChainArmorArms',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChainArmorHands',0,'ChainArmorHands',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChainArmorLegs',0,'ChainArmorLegs',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChainArmorFeet',0,'ChainArmorFeet',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlateArmorHead',0,'PlateArmorHead',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlateArmorChest',0,'PlateArmorChest',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlateArmorArms',0,'PlateArmorArms',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlateArmorHands',0,'PlateArmorHands',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlateArmorLegs',0,'PlateArmorLegs',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlateArmorFeet',0,'PlateArmorFeet',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HeavyPlateArmorHead',0,'HeavyPlateArmorHead',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HeavyPlateArmorChest',0,'HeavyPlateArmorChest',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HeavyPlateArmorArms',0,'HeavyPlateArmorArms',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HeavyPlateArmorHands',0,'HeavyPlateArmorHands',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HeavyPlateArmorLegs',0,'HeavyPlateArmorLegs',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HeavyPlateArmorFeet',0,'HeavyPlateArmorFeet',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sword',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneArmorChest','false','BoneArmorChest','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GearBoxBase',0,'GearBoxBase',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GearBoxFrame',0,'GearBoxFrame',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GearBox',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Spring',0,'Spring',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cylinder',0,'Cylinder',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Axle',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('VerticalAxle',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopInputIndicator',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepRed','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepGreen','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepBlue','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepYellow','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepPurple','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SheepCyan','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEngineBoilerFR',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEnginePistonFR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEngineBoilerBL',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEnginePistonBL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEngine',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEngineBoiler',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SteamEnginePiston',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AxleAnim',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Pipe',0,'PipePost',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeN',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeE',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeS',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeNS',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeEW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeNE',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeES',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeSW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeNW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeESW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeNSW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeNEW',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeNES',0,'',0,'0 0',0,NULL,'',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRot',0,'PipePost',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotN',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotE',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotS',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNS',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotEW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNE',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotES',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotSW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotESW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNSW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNEW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNES',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeRotNESW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeItem',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeFittingItem',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Pump',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpBase',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpTop',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExit',0,'PipeFittingItem',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitN',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitE',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitS',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitNS',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitEW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitNE',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitES',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitSW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitNW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitESW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitNSW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitNEW',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitNES',0,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRot',0,'PipeFittingItem',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotN',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotE',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotS',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNS',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotEW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNE',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotES',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotSW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotESW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNSW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNEW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNES',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PipeExitRotNESW',0,'',0,'0 0',0,'Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PumpConnectors',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree1',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree2',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree3',0,NULL,0,'0 -4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree5',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree9',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree10',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree12',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree13',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree14',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree15',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree16',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree17',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree18',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree19',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree20',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree5_10',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree10_5',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11_1',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11_2',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11_3',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11_4',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11_5',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree11_6',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree20_1',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree20_2',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree20_3',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BirchTree20_4',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeverOff',0,NULL,0,'0 0',NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeverOn',0,NULL,0,'0 0',NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeverBase',0,'LeverBaseFR',0,'0 0',NULL,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Wrench',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Blueprint',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Bar',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Wheel',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Handcrank',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpikeTrapItem','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MechanicalWallItem',0,'MechanicalWallClosed',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MechanicalWallOpen',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MechanicalWallShort',0,'MechanicalWallOpen',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonCore',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonBR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Automaton',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail1FR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail2FR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail3FR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail4FR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail1BL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail2BL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail3BL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail4BL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailFrame1',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailFrame2',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailFrame3',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailFrame4',1,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillRoof',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FlourSack',0,'Sack',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillBase2',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilStairsTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneStairsTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SoilStairs',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneStairs',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodDoor',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneDoor',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodTable',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkullWall',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SkullWallShort',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneBedFrame',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneBedSheets',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BoneBed',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bed',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth1FR',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth2FR',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth3FR',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth4FR',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth1BL',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth2BL',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth3BL',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth4BL',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth1',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth2',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth3',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSailCloth4',1,'',0,'0 0',0,'','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail1',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail2',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail3',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WindmillSail4',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FlourSack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FlourSackPile',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Donkey',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_3_02',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_3_11',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_3_12',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_3_21',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_3_22',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_4_10',0,NULL,0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom2_4_11',0,NULL,0,'0 12',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom3_2_10',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom3_2_11',0,NULL,0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mushroom3_3_10',0,NULL,0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth000',0,'MammothFL17',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth010',0,'MammothFL13',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth020',0,'MammothFL4',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth100',0,'MammothFL1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth110',0,'MammothFL2',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth120',0,'MammothFL3',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth001',0,'MammothFL12',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth011',0,'MammothFL12',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth021',0,'MammothFL5',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth101',0,'MammothFL8',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth111',0,'MammothFL7',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth121',0,'MammothFL6',0,'0 4',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth002',0,'MammothFL16',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth012',0,'MammothFL15',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth022',0,'MammothFL14',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth102',0,'MammothFL9',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth112',0,'MammothFL10',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Mammoth122',0,'MammothFL11',0,'0 8',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Straw',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Hay',0,'HayBale',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower1',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower4',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower5',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower6',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower7',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower8',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower1Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower2Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower3Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower4Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower5Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower6Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower7Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Flower8Young',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Honey','false','','false','0 0','false','','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Hammer',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Warhammer',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Claymore',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HandAxe',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BattleAxe',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughStoneWall2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughStoneFloor2',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughStoneFloor3',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorch',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorchBase',1,NULL,0,'0 0',NULL,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorchFlame',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorchFlameFR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorchFlameBL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorchBaseFR',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WallTorchBaseBL',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlankStairs',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PlankStairsTop',0,NULL,NULL,'0 0',NULL,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Chest','false','','false','0 0','false','Material','',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BookshelfShelf',0,NULL,NULL,'0 0',NULL,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BookshelfBooks',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Bookshelf',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BigTorchBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BigTorchFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BrazierBase',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BrazierFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BigTorch',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Brazier',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth1FL',NULL,'Sabretooth1FL',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth2FL',NULL,'Sabretooth2FL',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth1FR',NULL,'Sabretooth1FR',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth2FR',NULL,'Sabretooth2FR',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth1BR',NULL,'Sabretooth1BR',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth2BR',NULL,'Sabretooth2BR',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth1BL',NULL,'Sabretooth1BL',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sabretooth2BL',NULL,'Sabretooth2BL',NULL,NULL,NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Backpack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SandContainer',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassFurnace',1,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassFurnaceFlame',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassFurnaceOven',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassFurnaceFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassFurnaceBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_Mosaic',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WorkshopTable_GlassIngot',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassIngot',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('RoughGlassGem',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MosaicTile',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MosaicFloor',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MosaicWall',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MosaicWallShort',0,'MosaicFloor',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BowsRackBL',0,'BowsRackB',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BowsRackFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassWorkPipeBL',0,'GlassWorkPipeB',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassWorkPipeFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassIngotStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TargetBR',0,NULL,0,'0 0',NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TargetFL',0,NULL,0,'0 0',NULL,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('IngotMouldBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('IngotMouldFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('IngotMouldTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AlchemyVialsFL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodCarverStockBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('WoodCarverStockFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ArrowBucket',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MortarAndPestle',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AlchemyStill',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarpenterStock',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneCarverTableTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OilMillFL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OilMillBR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('OilStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PaperPress',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PaperMakerTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassBottleStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassPanelStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AlchemyStillFrame',1,'AlchemyStillFrame1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarpenterTableTopBR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CarpenterTableTopBR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PaperRack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CharcoalKilnBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CharcoalKilnFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CharcoalKilnFrame',1,'CharcoalKilnFrame1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassBlowerStockBL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassBlowerStockFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawMillTable',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SawMillBlade',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CoalPile',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherCrate',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DyeTableTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DyedClothStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CartBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CartFL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CrateSealed',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HideStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherSuitFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherSuitBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('LeatherSheet',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneWorkTools',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('VatBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('VatFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallTopBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketStallTopFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AnimalStallBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AnimalStallFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TanningVatBL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TanningVatFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('CharcoalKilnFrame',1,'CharcoalKilnFrame1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChiselMasonFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ChiselMasonBR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneRubble',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DyeVatBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DyeVatFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StovePanTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketSackFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MarketSackBL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoolWood',0,NULL,0,'0 0',0,'Material','Wood',0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneCarveBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoneCarveFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoveBL',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoveFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BrewVat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('BrewVatTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KitchenHearth',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KitchenPot',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PotTop',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoveCookBL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('StoveCookFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FruitPress',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('KilnFlame',1,'KilnFlame1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FurnaceFlame',1,'FurnaceFlame1',0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TailorStand',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ClothStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpinningWheelBR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpinningWheelFR',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpinningWheelTopBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SpinningWheelTopFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ArmourSuitBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ArmourSuitFR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrindStoneTop',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GrindStone',0,NULL,0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ThreadStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MeatStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SausageStack',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MeatGrinderBR',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MeatGrinderFL',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIChainmailArmorHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIChainmailArmorChest',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIChainmailArmorArms',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIChainmailArmorHands',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIChainmailArmorLegs',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIChainmailArmorFeet',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPlateArmorHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPlateArmorChest',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPlateArmorArms',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPlateArmorHands',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPlateArmorLegs',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPlateArmorFeet',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIHeavyPlateArmorHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIHeavyPlateArmorChest',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIHeavyPlateArmorArms',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIHeavyPlateArmorHands',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIHeavyPlateArmorLegs',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIHeavyPlateArmorFeet',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UILeatherArmorHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UILeatherArmorChest',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UILeatherArmorArms',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UILeatherArmorHands',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UILeatherArmorLegs',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UILeatherArmorFeet',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIBoneArmorHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIBoneArmorChest',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIBoneArmorArms',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIBoneArmorHands',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIBoneArmorLegs',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIBoneArmorFeet',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotChest',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotArms',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotHands',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotLegs',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotFeet',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotShield',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotNeck',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotBack',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotRing',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIEmptySlotWeapon',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UITorch',0,NULL,0,'0 -16',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPickaxe',0,NULL,0,'0 -16',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPickaxeHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIPickaxeBase',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIFellingAxe',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIFellingAxeBase',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UIFellingAxeHead',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UISword',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UISwordBlade',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('UISwordBase',0,NULL,0,'0 -16',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Milk',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Wine',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Beer',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('TeaCup',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Cider',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Vinegar',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Sugar',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('DropCandy',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('ShepherdsPie',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('Biscuit',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PickledFruit',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FruitPreserve',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmokedMeat',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmokedSausage',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FruitBread',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FreshCheese',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('HardCheese',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('MeatPie',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PickledVegetable',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('PickledEgg',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('VegetablePreserve',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmokedBird',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('SmokedFish',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FlatBread',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FruitPie',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('VeggiePie',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('FineMeatPie',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassJar',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('GlassBottle',0,NULL,0,'0 0',0,NULL,NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonTorso',0,'AutomatonTorsoFR',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonHead',0,'AutomatonHeadFR',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonArm',0,'AutomatonRightArmFR',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Sprites\" (\"ID\",\"Anim\",\"BaseSprite\",\"HasRandom\",\"Offset\",\"Rot90\",\"Tint\",\"DefaultMaterial\",\"HasTransp\") VALUES ('AutomatonFoot',0,'AutomatonRightFootFR',0,'0 0',0,'Material',NULL,0);\r\nINSERT INTO \"Spells\" (\"ID\",\"EffectRequirements\",\"Effects\",\"Radius\",\"SkillID\") VALUES ('SpeedGrowth','Plant','PlantGrowth','HalfSkill','MagicNature');\r\nINSERT INTO \"Spells\" (\"ID\",\"EffectRequirements\",\"Effects\",\"Radius\",\"SkillID\") VALUES ('RevealOre','EmbeddedMaterial','Reveal','Skill','MagicGeomancy');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Mining','Pickaxe','Stone');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Masonry',NULL,'Stone');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Stonecarving',NULL,'Stone');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Woodcutting','FellingAxe','Wood');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Carpentry',NULL,'Wood');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Woodcarving',NULL,'Wood');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Smelting',NULL,'Metal');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Blacksmithing',NULL,'Metal');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Metalworking',NULL,'Metal');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('WeaponCrafting',NULL,'Metal');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('ArmorCrafting',NULL,'Metal');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Gemcutting',NULL,'Gem');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('JewelryMaking',NULL,'Gem');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Weaving',NULL,'Cloth');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Tailoring',NULL,'Cloth');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Dyeing',NULL,'Cloth');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Pottery',NULL,'Misc Craft');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Leatherworking',NULL,'Misc Craft');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Bonecarving',NULL,'Misc Craft');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Prospecting',NULL,'Misc Craft');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Tinkering',NULL,'Engineer');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Machining',NULL,'Engineer');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Engineering',NULL,'Engineer');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Mechanic',NULL,'Engineer');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('AnimalHusbandry',NULL,'Rancher');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Butchery',NULL,'Rancher');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Fishing',NULL,'Rancher');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Horticulture',NULL,'Agriculture');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Farming',NULL,'Agriculture');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Cooking',NULL,'Agriculture');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Brewing',NULL,'Agriculture');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Construction',NULL,'Misc');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Hauling',NULL,'Misc');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Unarmed',NULL,'Combat');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Melee',NULL,'Combat');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Ranged',NULL,'Combat');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Thrown',NULL,'Combat');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Dodge',NULL,'Defense');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Block',NULL,'Defense');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Armor',NULL,'Defense');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Crossbow',NULL,'Combat');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Gun',NULL,'Combat');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Medic',NULL,'Doctor');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('Caretaking',NULL,'Doctor');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('MagicNature',NULL,'Magic');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('MagicGeomancy',NULL,'Magic');\r\nINSERT INTO \"Skills\" (\"ID\",\"RequiredToolItemID\",\"SkillGroup\") VALUES ('GlassMaking',NULL,'Gem');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Stone','160 160 160 255',1.0,'Mining|Masonry|Stonecarving','Stone');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Wood','175 114 86 255',2.0,'Woodcutting|Carpentry|Woodcarving','Wood');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Metal','120 120 120 255',3.0,'Smelting|Blacksmithing|Metalworking|WeaponCrafting|ArmorCrafting','Metal');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Gem','112 155 175 255',4.0,'Gemcutting|JewelryMaking|GlassMaking','Gem');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Cloth','135 175 150 255',5.0,'Weaving|Tailoring|Dyeing','Cloth');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('MiscCraft','165 105 175 255',6.0,'Pottery|Leatherworking|Bonecarving|Prospecting','Misc Craft');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Engineer','175 45 123 255',7.0,'Tinkering|Machining|Engineering|Mechanic','Engineer');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Rancher','134 175 105 255',8.0,'AnimalHusbandry|Butchery|Fishing','Rancher');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Agriculture','255 106 0 255',9.0,'Horticulture|Farming|Cooking|Brewing','Agriculture');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Doctor','173 6 29 255',10.0,'Medic|Caretaking','Doctor');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Misc','160 160 160 255',11.0,'Construction|Hauling','Misc');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Magic','175 175 200 255',12.0,'MagicNature|MagicGeomancy','Magic');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Combat','140 140 140 255',13.0,'Unarmed|Melee|Ranged|Thrown','Combat');\r\nINSERT INTO \"SkillGroups\" (\"ID\",\"Color\",\"Position\",\"SkillID\",\"Text\") VALUES ('Defense','173 142 112 255',14.0,'Dodge|Block|Armor','Defense');\r\nINSERT INTO \"Seasons\" (\"ID\",\"NextSeason\",\"NumDays\",\"SunRiseFirst\",\"SunsetFirst\") VALUES ('Spring','Summer',12.0,'6:14','18:23');\r\nINSERT INTO \"Seasons\" (\"ID\",\"NextSeason\",\"NumDays\",\"SunRiseFirst\",\"SunsetFirst\") VALUES ('Summer','Autumn',12.0,'4:54','21:30');\r\nINSERT INTO \"Seasons\" (\"ID\",\"NextSeason\",\"NumDays\",\"SunRiseFirst\",\"SunsetFirst\") VALUES ('Autumn','Winter',12.0,'6:52','19:14');\r\nINSERT INTO \"Seasons\" (\"ID\",\"NextSeason\",\"NumDays\",\"SunRiseFirst\",\"SunsetFirst\") VALUES ('Winter','Spring',12.0,'8:12','16:04');\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Granite',0,0,20,20,0,20,20,20);\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Basalt',0,0,0,10,0,30,30,30);\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Marble',30,30,20,0,0,20,0,0);\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Sandstone',50,50,0,0,0,0,0,0);\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Bauxite',20,20,20,20,20,0,0,0);\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Serpentine',10,10,20,20,20,10,10,0);\r\nINSERT INTO \"RandomMetals\" (\"ID\",\"Copper\",\"Tin\",\"Malachite\",\"Iron\",\"Lead\",\"Silver\",\"Gold\",\"Platinum\") VALUES ('Dirt',50,50,0,0,0,0,0,0);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Acceptable',1,0.8);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Average',2,1.0);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Good',3,1.2);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Excellent',4,1.5);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Outstanding',5,1.8);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Legendary',6,3.0);\r\nINSERT INTO \"Quality\" (\"ID\",\"Rank\",\"Modifier\") VALUES ('Bad',0,0.6);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Strawberry',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Strawberry',0,1.2,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Strawberry',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Carrot',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Carrot',0,1.5,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Carrot',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Onion',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Onion',0,1.3,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Onion',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Potato',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Potato',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Potato',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cabbage',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cabbage',0,1.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cabbage',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Asparagus',0,2.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Asparagus',0,3.5,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Asparagus',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Broccoli',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Broccoli',0,2.5,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Broccoli',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cauliflower',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cauliflower',0,3.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cauliflower',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cucumber',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cucumber',0,2.75,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cucumber',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Garlic',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Garlic',0,3.5,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Garlic',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Parsnip',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Parsnip',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Parsnip',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Radish',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Radish',0,1.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Radish',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Turnip',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Turnip',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Turnip',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Lettuce',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Lettuce',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Lettuce',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Melon',0,2.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Melon',0,3.5,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Melon',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Sugarbeet',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Sugarbeet',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Sugarbeet',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Pumpkin',0,2.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Pumpkin',0,3.5,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Pumpkin',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Peas',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Peas',0,1.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Peas',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('BeetRoot',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('BeetRoot',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('BeetRoot',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Wheat',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Wheat',0,2.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Wheat',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Barley',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Barley',0,2.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Barley',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Oat',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Oat',0,2.6,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Oat',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Millet',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Millet',0,2.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Millet',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cotton',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cotton',0,2.0,0.0,0,'GrownNoFruits',NULL,'Plant',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Cotton',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tea',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tea',0,3.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tea',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tobacco',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tobacco',0,3.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tobacco',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Pineapple',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Pineapple',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Pineapple',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Corn',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Corn',0,3.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Corn',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Leek',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Leek',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Leek',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Beans',0,1.0,0.7,0,'Planted',NULL,'PlantGrowHelper2',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Beans',0,2.0,0.7,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Beans',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Blackberry',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Blackberry',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Blackberry',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Artichoke',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Artichoke',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Artichoke',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Bottlegourd',0,1.0,0.0,0,'Planted',NULL,'PlantGrowHelper2',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Bottlegourd',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Bottlegourd',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Grape',0,1.0,0.0,0,'Planted',NULL,'PlantGrowHelper3',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Grape',0,3.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Grape',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tomato',0,1.0,0.0,0,'Planted',NULL,'PlantGrowHelper1',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tomato',0,3.5,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Tomato',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Capsicum',0,1.0,0.0,0,'Planted',NULL,'PlantGrowHelper1',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Capsicum',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Capsicum',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Woad',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Woad',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Woad',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('DyersWeed',0,1.0,0.0,0,'Planted',NULL,'PlantedSoil',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('DyersWeed',0,2.0,0.0,0,'GrownNoFruits',NULL,'PlantLarge',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('DyersWeed',0,0.0,0.0,1,'GrownHasFruits',NULL,'PlantLargeWithFruit',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('PineTree',0,1.1,0.0,0,'Sapling',NULL,'Sapling',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('PineTree',0,6.5,0.0,0,'NoLeaves',NULL,'PineTreeNoLeaves',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('PineTree',1,0.0,0.0,0,'FullyGrown','PineTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('AppleTree',0,3.0,0.0,0,'Sapling',NULL,'Sapling',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('AppleTree',0,3.0,0.0,0,'NoLeaves',NULL,'AppleTreeNoLeaves',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('AppleTree',1,5.0,0.0,0,'FullyGrown','AppleTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('AppleTree',1,0.0,0.0,1,'FullyGrownWithFruit','AppleTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OrangeTree',0,3.0,0.0,0,'Sapling',NULL,'Sapling',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OrangeTree',0,3.0,0.0,0,'NoLeaves',NULL,'OrangeTreeNoLeaves',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OrangeTree',1,5.0,0.0,0,'FullyGrown','OrangeTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OrangeTree',1,0.0,0.0,1,'FullyGrownWithFruit','OrangeTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OakTree',0,1.1,0.0,0,'Sapling',NULL,'Sapling',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OakTree',0,6.5,0.0,0,'NoLeaves',NULL,'PineTreeNoLeaves',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('OakTree',1,0.0,0.0,0,'Sapling','OakTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('WillowTree',0,1.1,0.0,0,'Sapling',NULL,'Sapling',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('WillowTree',0,6.5,0.0,0,'NoLeaves',NULL,'PineTreeNoLeaves',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('WillowTree',1,0.0,0.0,0,'Sapling','WillowTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Mushroom1',1,0.0,0.0,0,'FullyGrown','Mushroom1','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Mushroom2',1,0.0,0.0,0,'FullyGrown','Mushroom2','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Mushroom3',1,0.0,0.0,0,'FullyGrown','Mushroom3','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('StrawMushroom',0,0.0,0.0,0,'FullyGrown',NULL,'StrawMushroom',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('WoodMushroom',0,0.0,0.0,0,'FullyGrown',NULL,'WoodMushroom',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('FibreMushroom',0,0.0,0.0,0,'FullyGrown',NULL,'FibreMushroom',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('GrainMushroom',0,0.0,0.0,0,'FullyGrown',NULL,'GrainMushroom',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('BirchTree',0,1.2,0.0,0,'Sapling',NULL,'Sapling',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('BirchTree',0,6.3,0.0,0,'NoLeaves',NULL,'BirchTree',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('BirchTree',1,0.0,0.0,0,'Sapling','BirchTree','none',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower1',0,2.0,0.0,0,'Planted',NULL,'Flower1Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower1',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower1',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower2',0,2.0,0.0,0,'Planted',NULL,'Flower2Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower2',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower2',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower3',0,2.0,0.0,0,'Planted',NULL,'Flower3Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower3',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower3',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower4',0,2.0,0.0,0,'Planted',NULL,'Flower4Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower4',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower4',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower5',0,2.0,0.0,0,'Planted',NULL,'Flower5Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower5',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower5',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower6',0,2.0,0.0,0,'Planted',NULL,'Flower6Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower6',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower6',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower7',0,2.0,0.0,0,'Planted',NULL,'Flower7Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower7',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower7',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower8',0,2.0,0.0,0,'Planted',NULL,'Flower8Young',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower8',0,3.0,0.0,0,'GrownNoFruits',NULL,'Flower8',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower1',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower1',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower2',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower2',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower3',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower3',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower4',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower4',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower5',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower5',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower6',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower6',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower7',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower7',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('Flower8',0,0.0,0.0,1,'GrownHasFruits',NULL,'Flower8',NULL,NULL);\r\nINSERT INTO \"Plants_States\" (\"ID\",\"Fell\",\"GrowTime\",\"GrowTimeDeviation\",\"Harvest\",\"ID2\",\"Layout\",\"SpriteID\",\"HasAlpha\",\"LightIntensity\") VALUES ('GlowShroom',0,0.0,0.0,0,'FullyGrown',NULL,'CrystalShroom',1,8);\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Strawberry',0.0,'Fruit','Strawberry');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Strawberry',0.0,'Seed','Strawberry');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Strawberry',0.5,'Seed','Strawberry');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Carrot',0.0,'Vegetable','Carrot');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Carrot',0.0,'Seed','Carrot');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Carrot',0.5,'Seed','Carrot');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Onion',0.0,'Vegetable','Onion');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Onion',0.0,'Vegetable','Onion');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Onion',0.0,'Seed','Onion');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Onion',0.3,'Seed','Onion');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Potato',0.0,'Vegetable','Potato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Potato',0.0,'Vegetable','Potato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Potato',0.0,'Seed','Potato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Potato',0.3,'Seed','Potato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cabbage',0.0,'Vegetable','Cabbage');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cabbage',0.0,'Seed','Cabbage');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cabbage',0.5,'Seed','Cabbage');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Asparagus',0.0,'Vegetable','Asparagus');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Asparagus',0.0,'Seed','Asparagus');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Asparagus',0.5,'Seed','Asparagus');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Broccoli',0.0,'Vegetable','Broccoli');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Broccoli',0.0,'Seed','Broccoli');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Broccoli',0.5,'Seed','Broccoli');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cauliflower',0.0,'Vegetable','Cauliflower');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cauliflower',0.0,'Seed','Cauliflower');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cauliflower',0.5,'Seed','Cauliflower');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cucumber',0.0,'Vegetable','Cucumber');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cucumber',0.0,'Seed','Cucumber');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cucumber',0.5,'Seed','Cucumber');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Garlic',0.0,'Vegetable','Garlic');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Garlic',0.0,'Seed','Garlic');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Garlic',0.5,'Seed','Garlic');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Parsnip',0.0,'Vegetable','Parsnip');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Parsnip',0.0,'Seed','Parsnip');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Parsnip',0.5,'Seed','Parsnip');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Radish',0.0,'Vegetable','Radish');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Radish',0.0,'Seed','Radish');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Radish',0.5,'Seed','Radish');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Turnip',0.0,'Vegetable','Turnip');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Turnip',0.0,'Seed','Turnip');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Turnip',0.5,'Seed','Turnip');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Lettuce',0.0,'Vegetable','Lettuce');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Lettuce',0.0,'Seed','Lettuce');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Lettuce',0.5,'Seed','Lettuce');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Melon',0.0,'Fruit','Melon');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Melon',0.0,'Seed','Melon');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Melon',0.5,'Seed','Melon');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Sugarbeet',0.0,'Vegetable','Sugarbeet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Sugarbeet',0.0,'Seed','Sugarbeet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Sugarbeet',0.5,'Seed','Sugarbeet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Pumpkin',0.0,'Fruit','Pumpkin');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Pumpkin',0.0,'Seed','Pumpkin');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Pumpkin',0.5,'Seed','Pumpkin');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Peas',0.0,'Vegetable','Peas');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Peas',0.0,'Seed','Peas');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Peas',0.5,'Seed','Peas');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('BeetRoot',0.0,'Vegetable','BeetRoot');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('BeetRoot',0.0,'Seed','BeetRoot');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('BeetRoot',0.5,'Seed','BeetRoot');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Wheat',0.0,'Grain','Wheat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Wheat',0.0,'Straw','Wheat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Wheat',0.0,'Seed','Wheat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Wheat',0.3,'Seed','Wheat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Barley',0.0,'Grain','Barley');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Barley',0.0,'Straw','Barley');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Barley',0.0,'Seed','Barley');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Barley',0.3,'Seed','Barley');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Oat',0.0,'Grain','Oat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Oat',0.0,'Straw','Oat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Oat',0.0,'Seed','Oat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Oat',0.3,'Seed','Oat');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Millet',0.0,'Grain','Millet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Millet',0.0,'Straw','Millet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Millet',0.0,'Seed','Millet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Millet',0.3,'Seed','Millet');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cotton',0.0,'RawCloth','Cotton');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cotton',0.0,'Seed','Cotton');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Cotton',0.3,'Seed','Cotton');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tea',0.0,'Leaves','Tea');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tea',0.0,'Seed','Tea');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tea',0.5,'Seed','Tea');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tobacco',0.0,'Leaves','Tobacco');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tobacco',0.0,'Seed','Tobacco');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tobacco',0.5,'Seed','Tobacco');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Pineapple',0.0,'Fruit','Pineapple');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Pineapple',0.0,'Seed','Pineapple');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Pineapple',0.5,'Seed','Pineapple');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Corn',0.0,'Vegetable','Corn');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Corn',0.0,'Seed','Corn');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Corn',0.5,'Seed','Corn');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Leek',0.0,'Vegetable','Leek');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Leek',0.0,'Seed','Leek');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Leek',0.5,'Seed','Leek');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Beans',0.0,'Vegetable','Beans');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Beans',0.0,'Seed','Beans');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Beans',0.5,'Seed','Beans');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Blackberry',0.0,'Berries','Blackberry');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Blackberry',0.0,'Seed','Blackberry');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Blackberry',0.5,'Seed','Blackberry');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Artichoke',0.0,'Vegetable','Artichoke');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Artichoke',0.0,'Seed','Artichoke');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Artichoke',0.5,'Seed','Artichoke');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Bottlegourd',0.0,'Vegetable','Bottlegourd');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Bottlegourd',0.0,'Seed','Bottlegourd');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Bottlegourd',0.5,'Seed','Bottlegourd');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Grape',0.0,'Berries','Grape');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Grape',0.0,'Seed','Grape');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Grape',0.5,'Seed','Grape');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tomato',0.0,'Vegetable','Tomato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tomato',0.0,'Seed','Tomato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Tomato',0.5,'Seed','Tomato');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Capsicum',0.0,'Vegetable','Capsicum');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Capsicum',0.0,'Seed','Capsicum');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Capsicum',0.5,'Seed','Capsicum');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Woad',0.0,'Leaves','Woad');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Woad',0.0,'Seed','Woad');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Woad',0.5,'Seed','Woad');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('DyersWeed',0.0,'Leaves','DyersWeed');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('DyersWeed',0.0,'Seed','DyersWeed');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('DyersWeed',0.5,'Seed','DyersWeed');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('AppleTree',0.0,'Fruit','Apple');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('OrangeTree',0.0,'Fruit','Orange');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower1',0.0,'Seed','Flower1');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower1',0.0,'Seed','Flower1');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower2',0.0,'Seed','Flower2');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower2',0.0,'Seed','Flower2');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower3',0.0,'Seed','Flower3');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower3',0.0,'Seed','Flower3');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower4',0.0,'Seed','Flower4');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower4',0.0,'Seed','Flower4');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower5',0.0,'Seed','Flower5');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower5',0.0,'Seed','Flower5');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower6',0.0,'Seed','Flower6');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower6',0.0,'Seed','Flower6');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower7',0.0,'Seed','Flower7');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower7',0.0,'Seed','Flower7');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower8',0.0,'Seed','Flower8');\r\nINSERT INTO \"Plants_OnHarvest_HarvestedItem\" (\"ID\",\"Chance\",\"ItemID\",\"MaterialID\") VALUES ('Flower8',0.0,'Seed','Flower8');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Strawberry','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Carrot','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Onion','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Potato','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Cabbage','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Asparagus','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Broccoli','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Cauliflower','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Cucumber','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Garlic','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Parsnip','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Radish','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Turnip','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Lettuce','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Melon','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Sugarbeet','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Pumpkin','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Peas','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('BeetRoot','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Wheat','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Barley','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Oat','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Millet','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Cotton','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Tea','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Tobacco','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Pineapple','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Corn','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Leek','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Beans','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Blackberry','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Artichoke','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Bottlegourd','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Grape','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Tomato','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Capsicum','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Woad','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('DyersWeed','StateOneBack');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('AppleTree','ReduceFruitCount');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('OrangeTree','ReduceFruitCount');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower1','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower2','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower3','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower4','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower5','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower6','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower7','Destroy');\r\nINSERT INTO \"Plants_OnHarvest\" (\"ID\",\"Action\") VALUES ('Flower8','Destroy');\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('PineTree','RawWood','Pine',0.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('PineTree','Cone','Pine',3.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('AppleTree','RawWood','AppleWood',0.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('OrangeTree','RawWood','OrangeWood',0.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('OakTree','RawWood','Oak',0.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('OakTree','Oak','Oak',3.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('WillowTree','RawWood','Willow',0.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('WillowTree','Seed','Willow',2.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('BirchTree','RawWood','Birch',0.0);\r\nINSERT INTO \"Plants_OnFell\" (\"ID\",\"ItemID\",\"MaterialID\",\"Random\") VALUES ('BirchTree','Seed','Birch',3.0);\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Strawberry',1,NULL,'Sun','Spring|Summer|Autumn',NULL,0,'Winter','Strawberry',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Carrot',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Carrot',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Onion',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Onion',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Potato',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Potato',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Cabbage',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Cabbage',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Asparagus',0,NULL,'Sun','Spring|Summer|Autumn',NULL,0,'Winter','Asparagus',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Broccoli',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Broccoli',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Cauliflower',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Cauliflower',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Cucumber',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Cucumber',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Garlic',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Garlic',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Parsnip',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Parsnip',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Radish',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Radish',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Turnip',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Turnip',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Lettuce',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Lettuce',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Melon',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Melon',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Sugarbeet',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Sugarbeet',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Pumpkin',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Pumpkin',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Peas',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Peas',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('BeetRoot',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'BeetRoot',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Wheat',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Wheat',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Barley',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Barley',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Oat',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Oat',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Millet',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Millet',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Cotton',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Cotton',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Tea',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Tea',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Tobacco',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Tobacco',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Pineapple',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Pineapple',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Corn',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Corn',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Leek',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Leek',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Beans',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Beans',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Blackberry',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Blackberry',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Artichoke',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Artichoke',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Bottlegourd',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Bottlegourd',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Grape',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Grape',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Tomato',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Tomato',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Capsicum',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Capsicum',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Woad',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Woad',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('DyersWeed',0,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'DyersWeed',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('PineTree',0,NULL,'Sun','Spring|Summer|Autumn',NULL,0,NULL,'Pine',0.0,'Cone','PineTree','Tree');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('AppleTree',0,'Fruit','Sun','Spring|Summer|Autumn',NULL,0,'Winter','Apple',9.0,'Fruit','AppleTree','Tree');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('OrangeTree',0,'Fruit','Sun','Spring|Summer|Autumn',NULL,0,'Winter','Orange',9.0,'Fruit','OrangeTree','Tree');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('OakTree',0,NULL,'Sun','Spring|Summer|Autumn',NULL,0,NULL,'Oak',0.0,'Oak','OakTree212','Tree');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('WillowTree',0,NULL,'Sun','Spring|Summer|Autumn',NULL,0,NULL,'Willow',0.0,'Seed','WillowTree212','Tree');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Mushroom1',0,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,1,NULL,'Mushroom',0.0,NULL,NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Mushroom2',0,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,1,NULL,'Mushroom',0.0,NULL,NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Mushroom3',0,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,1,NULL,'Mushroom',0.0,NULL,NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('StrawMushroom',1,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,0,NULL,'Mushroom',0.0,'Spore',NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('WoodMushroom',1,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,0,NULL,'Mushroom',0.0,'Spore',NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('FibreMushroom',1,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,0,NULL,'Mushroom',0.0,'Spore',NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('GrainMushroom',1,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,0,NULL,'Mushroom',0.0,'Spore',NULL,'Mushroom');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('BirchTree',0,NULL,'Sun','Spring|Summer|Autumn',NULL,0,NULL,'Birch',0.0,'Seed','BirchTree','Tree');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower1',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower1',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower2',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower2',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower3',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower3',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower4',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower4',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower5',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower5',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower6',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower6',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower7',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower7',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('Flower8',1,NULL,'Sun','Spring|Summer|Autumn','Winter',0,NULL,'Flower8',0.0,'Seed',NULL,'Plant');\r\nINSERT INTO \"Plants\" (\"ID\",\"AllowInWild\",\"FruitItemID\",\"GrowsIn\",\"GrowsInSeason\",\"IsKilledInSeason\",\"IsLarge\",\"LosesFruitInSeason\",\"Material\",\"NumFruitsPerSeason\",\"SeedItemID\",\"ToolButtonSprite\",\"Type\") VALUES ('GlowShroom',1,NULL,'Dark','Spring|Summer|Autumn|Winter',NULL,0,NULL,'Mushroom',0.0,'Spore',NULL,'Mushroom');\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('SleepDeadTired','Dex','Attribute',-5.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('SleepDeadTired','Happiness','Need',-20.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('SleepVerySleepy','Dex','Attribute',-2.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('HungerStarving','Str','Attribute',-5.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('HungerStarving','Happiness','Need',-20.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('HungerVeryHungry','Str','Attribute',-2.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('HungerVeryHungry','Happiness','Need',-10.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('HungerHungry','Str','Attribute',-1.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('ThirstDehydrated','Int','Attribute',-5.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('ThirstDehydrated','Happiness','Need',-20.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('ThirstVeryThirsty','Int','Attribute',-2.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('ThirstVeryThirsty','Happiness','Need',-10.0);\r\nINSERT INTO \"Needs_States_Modifiers\" (\"ID\",\"Attribute\",\"Type\",\"Value_\") VALUES ('ThirstThirsty','Int','Attribute',-1.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Sleep','FallAsleepOnSpot','DeadTired',3.0,'Sleeping',0.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Sleep','Sleep','VerySleepy',2.0,NULL,25.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Hunger','Die','StarvedToDeath',0.0,NULL,-100.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Hunger','EatClosest','Starving',5.0,'Hungry',0.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Hunger','Eat','VeryHungry',4.0,'Hungry',15.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Hunger','EatBest','Hungry',3.0,'Hungry',30.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Thirst','Die','DiedFromThirst',0.0,NULL,-100.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Thirst','DrinkClosest','Dehydrated',5.0,'Thirsty',0.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Thirst','Drink','VeryThirsty',4.0,'Thirsty',15.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Thirst','DrinkBest','Thirsty',3.0,'Thirsty',30.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Happiness',NULL,'VeryHappy',0.0,NULL,80.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Happiness',NULL,'Happy',0.0,NULL,60.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Happiness',NULL,'Unhappy',0.0,NULL,40.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Happiness',NULL,'VeryUnhappy',0.0,NULL,20.0);\r\nINSERT INTO \"Needs_States\" (\"ID\",\"Action\",\"ID2\",\"Priority\",\"ThoughtBubble\",\"Threshold\") VALUES ('Happiness',NULL,'Depressed',0.0,NULL,0.0);\r\nINSERT INTO \"Needs\" (\"ID\",\"BarColor\",\"DecayPerMinute\",\"GainFromSleep\",\"Max_\",\"Creature\") VALUES ('Sleep','#FFFFA0',-0.03,0.35,100.0,'Gnome');\r\nINSERT INTO \"Needs\" (\"ID\",\"BarColor\",\"DecayPerMinute\",\"GainFromSleep\",\"Max_\",\"Creature\") VALUES ('Hunger','#FFA0A0',-0.025,0.0,100.0,'Gnome');\r\nINSERT INTO \"Needs\" (\"ID\",\"BarColor\",\"DecayPerMinute\",\"GainFromSleep\",\"Max_\",\"Creature\") VALUES ('Thirst','#A0A0FF',-0.025,0.0,100.0,'Gnome');\r\nINSERT INTO \"Needs\" (\"ID\",\"BarColor\",\"DecayPerMinute\",\"GainFromSleep\",\"Max_\",\"Creature\") VALUES ('Happiness','#C050C0',0.0,0.0,100.0,'Gnome');\r\nINSERT INTO \"Needs\" (\"ID\",\"BarColor\",\"DecayPerMinute\",\"GainFromSleep\",\"Max_\",\"Creature\") VALUES ('Fuel','#707070',-0.5,0.0,3000.0,'Automaton');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bartleby','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bartlett','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('beeblebrox','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bembledack','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bingledack','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('blart','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('blerg','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bunwalla','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dambleban','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dangle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dindlebert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dinkledoodle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dimperdoodle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('doodle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('engelbert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fishtybuns','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fistelvase','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizban','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzy','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fondle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('foodle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jeff','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gnapoleon','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gnemo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gneo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gnick','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gnomeo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hugh','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('humperdinck','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('humptyback','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('klingybun','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('kringelbert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('perrywinkle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('slartibartfast','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('steviebuns','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('versenwald','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('vingelbert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wangledack','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wingelbert','M      ');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wingledanck','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('winkle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wizzy','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wocket','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('yingybert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zangelbert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zifnab','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zindledack','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zingelbert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zoltan','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('grimm','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('twosprocket','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gashweld','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizwhistle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wobbletop','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzlespit','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzwizzle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzlebizz','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mixilpixil','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('spark','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('whindlebolt','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzlespinner','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('booms','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('doohickey','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('thistlefuzz','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('baubbletump','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mekkatorque','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tinker','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('lemkenilli','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('twizzlefixit','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('Ulf Ulfson son of Ulf','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hinkles','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gimrizz','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gimble','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gaffer','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('flickin','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fimble','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dink','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('deek','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('crazzle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('craggle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cog','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('caz','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('boog','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('binjy','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bingus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bimble','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('billibub','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('belbi','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('loosegrip','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('togglevolt','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gyromate','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('spindlenut','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wizzle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wemble','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('twilbur','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tickin','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('spackle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rizzle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('razzle','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pithwick','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ozzie','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('milo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mazzer','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gabriel','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('abibo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ado','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('amos','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('anno','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('axel','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('azas','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bacchus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('baltram','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bardo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('barlow','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('barr','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('basil','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bean','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bruno','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('casper','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cass','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cato','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cecil','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('chester','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ciro','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('conan','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('crispin','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cyr','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dewey','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('didymus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dion','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dolph','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('drogo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('elmer','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('enzio','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('eunus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('eustace','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ewald','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fabian','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('falco','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('felix','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fergus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('festus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('filbert','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('finbarr','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fintan','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fulk','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gall','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gaspar','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gaston','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gene','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('giles','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gummar','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hero','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hugo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('iago','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('igor','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ivar','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jasper','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jerome','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jesse','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('joris','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('justus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('karl','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('kellan','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('klas','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('knute','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('kurt','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('linus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('lipo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('lullus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mace','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('manfred','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('melvin','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('merry','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('milo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('naldo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('napper','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ned','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('nestor','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('odo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('olaf','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('omer','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('otto','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pambo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pepin','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pinian','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('poppo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('remi','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rex','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rufus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('titus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tito','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ugo','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ulmer','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ursus','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('west','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zeno','M');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bartlett','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('beeblebrox','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bembledack','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bingledack','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bunwalla','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dangle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dindlebert','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dinkledoodle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dimperdoodle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('doodle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('engelbert','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fishtybuns','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fistelvase','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizban','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzy','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fondle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('foodle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jeff','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('klingybun','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('perrywinkle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('versenwald','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wangledack','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wingledanck','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('winkle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wizzy','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zifnab','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zindledack','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('twosprocket','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gashweld','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizwhistle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wobbletop','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzlespit','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzwizzle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzlebizz','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mixilpixil','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('spark','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('whindlebolt','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzlespinner','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('booms','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('doohickey','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('thistlefuzz','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('baubbletump','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mekkatorque','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tinker','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('lemkenilli','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('twizzlefixit','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jinky','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jennabink','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hinkles','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('flickin','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fizzle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fimble','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dink','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('deek','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('caz','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('boog','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bipsi','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('binni','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bink','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('binjy','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bingus','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bimble','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('belbi','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('trini','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('togglevolt','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bubblefizz','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('spindlenut','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wizzle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wemble','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('twilbur','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('trixie','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tink','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tilli','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tickin','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tally','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('sprite','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('spackle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rizzle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rixa','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rillie','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('razzle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pithwick','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ozzie','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('minx','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('milo','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('milli','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mazzer','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jeska','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('azas','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('basil','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bean','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cass','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cato','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cecil','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('crispin','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cyr','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dewey','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('dion','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('falco','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hero','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jasper','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('jesse','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('justus','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('kellan','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('merry','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pambo','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pepin','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pinian','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('poppo','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('remi','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('west','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zeno','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ada','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('alba','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('aura','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ava','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('balbina','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bassa','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('belina','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bess','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('bobilia','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cera','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('clara','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cleo','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('cyra','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('daisy','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('daria','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('enid','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('etta','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('eve','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fay','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('fifi','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('flora','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gemma','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gladys','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('goldie','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('gwen','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hallie','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hedwig','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('hester','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('june','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('lelia','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('mimi','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('myrtle','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('nanette','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('nell','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('nessa','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('nimmia','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('nona','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ola','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('olive','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('oona','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pearl','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('pia','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('polly','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('rose','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ruby','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('silva','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('stella','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tatiana','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('thea','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('tilda','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('ursula','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('violet','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('wanda','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('xina','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zara','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('zita','F');\r\nINSERT INTO \"Names\" (\"ID\",\"Gender\") VALUES ('grog','M');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Faction','Compound_Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Faction','The|Adjective|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Faction','Land|of|Noun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Faction','The|Adjective|Kingdom');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Faction','The|Noun_Singular|Kingdom');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Faction','The|Verb_PastParticiple|Land');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Verb_PresentParticiple|Noun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Verb_PresentParticiple|Noun_Plural|Of|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Adjective|Noun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Verb_PastParticiple|Noun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Adjective|Noun_Plural|Of|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','Adjective|Noun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','Verb_PastParticiple|Noun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Adjective|ActionNoun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','Adjective|ActionNoun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Adjective|ActionNoun_Plural|Of|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Compound_ActionNoun_Plural|Of|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Squad','The|Compound_ActionNoun_Plural');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Noun_Singular|Of|The|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Adjective|Noun_Singular|Of|The|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|ActionNoun_Singular|Of|The|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Adjective|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Adjective|ActionNoun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Verb_PresentParticiple|Of|The|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Verb_PresentParticiple|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Verb_PastParticiple|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Verb_PastParticiple|ActionNoun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','Compound_Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Compound_Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','Compound_ActionNoun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Compound_ActionNoun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Compound_Verb_PresentParticiple');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|GenericNoun|Of|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Verb_PresentParticiple|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('Item','The|Adjective|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('EnemyName','ProperNoun|The|Compound_ActionNoun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('EnemyName','ProperNoun|The|ActionNoun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('EnemyName','ProperNoun|The|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('EnemyName','ProperNoun|The|Verb_PresentParticiple|Noun_Singular');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('EnemyName','ProperNoun|The|GenericNoun|Of|Noun');\r\nINSERT INTO \"Namerules_Rule\" (\"ID\",\"Part\") VALUES ('EnemyName','ProperNoun|The|Adjective|Noun');\r\nINSERT INTO \"Namerules\" (\"ID\") VALUES ('Faction');\r\nINSERT INTO \"Namerules\" (\"ID\") VALUES ('Squad');\r\nINSERT INTO \"Namerules\" (\"ID\") VALUES ('Item');\r\nINSERT INTO \"Namerules\" (\"ID\") VALUES ('EnemyName');\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',1,30);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',2,35);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',3,40);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',4,45);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',5,50);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',6,55);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',7,60);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',8,65);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',9,70);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',10,75);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',11,80);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',12,85);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',13,90);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',14,95);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',15,100);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',16,105);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',17,110);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',18,115);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',19,120);\r\nINSERT INTO \"MoveSpeed\" (\"Creature\",\"Skill\",\"Speed\") VALUES ('Gnome',20,125);\r\nINSERT INTO \"Monsters_Levels\" (\"ID\",\"Level\",\"Sprite\") VALUES ('Goblin',0.0,'Goblin');\r\nINSERT INTO \"Monsters\" (\"ID\",\"BehaviorTree\",\"Food\") VALUES ('Goblin','Monster','Vegetable');\r\nINSERT INTO \"Monsters\" (\"ID\",\"BehaviorTree\",\"Food\") VALUES ('MantWorker','MantWorker',NULL);\r\nINSERT INTO \"Monsters\" (\"ID\",\"BehaviorTree\",\"Food\") VALUES ('MantSoldier','MantSoldier',NULL);\r\nINSERT INTO \"Monsters\" (\"ID\",\"BehaviorTree\",\"Food\") VALUES ('MantQueen','MantQueen',NULL);\r\nINSERT INTO \"Missions\" (\"ID\",\"TypeInt\",\"MinGnomes\",\"MaxGnomes\",\"Target\",\"Actions\") VALUES ('Explore',1,1,1,NULL,NULL);\r\nINSERT INTO \"Missions\" (\"ID\",\"TypeInt\",\"MinGnomes\",\"MaxGnomes\",\"Target\",\"Actions\") VALUES ('Spy',2,1,1,'Kingdom',NULL);\r\nINSERT INTO \"Missions\" (\"ID\",\"TypeInt\",\"MinGnomes\",\"MaxGnomes\",\"Target\",\"Actions\") VALUES ('Emissary',3,1,1,'Kingdom','Improve|Insult|InviteTrader|InviteAmbassador');\r\nINSERT INTO \"Missions\" (\"ID\",\"TypeInt\",\"MinGnomes\",\"MaxGnomes\",\"Target\",\"Actions\") VALUES ('Raid',4,3,5,'Kingdom',NULL);\r\nINSERT INTO \"Missions\" (\"ID\",\"TypeInt\",\"MinGnomes\",\"MaxGnomes\",\"Target\",\"Actions\") VALUES ('Sabotage',5,3,5,'Kingdom',NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('GearBox',NULL,1,NULL,NULL,0,0,0,'false',NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('Axle',NULL,1,NULL,NULL,0,0,0,'true',NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('VerticalAxle',NULL,1,'Axle','AxleUD1',0,0,0,'true',NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('SteamEngine','Active|Fuel',1,NULL,NULL,5000,25,0,'true',NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('Lever','Active',1,NULL,NULL,0,0,0,'false','LeverOn','LeverOff',NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('Pump',NULL,0,NULL,NULL,0,0,10,'true',NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('MechanicalWall','Invert',1,NULL,NULL,0,0,5,'false','MechanicalWallOpen','MechanicalWallClosed',NULL, NULL,'Floor','Wall');\r\nINSERT INTO \"Mechanism\" (\"ID\",\"GUI\",\"Buildable\",\"Item\",\"Sprite\",\"MaxFuel\",\"ProducePower\",\"ConsumePower\",\"Anim\",\"WallSpriteOn\",\"WallSpriteOff\",\"FloorSpriteOn\",\"FloorSpriteOff\",\"EffectOn\",\"EffectOff\") VALUES ('PressurePlate','Invert',1,NULL,NULL,0,0,0,'false',NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Wood',1.0,1.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Dirt',1.0,0.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Sand',1.0,0.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Clay',1.0,0.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('FlintStone',1.0,2.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Stone',2.0,2.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Basalt',3.0,2.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Granite',4.0,2.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Sandstone',1.0,1.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Copper',2.0,2.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Bronze',3.0,3.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Iron',3.0,4.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Steel',4.0,5.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Diamond',5.0,6.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Platinum',4.0,5.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Tin',1.0,2.0);\r\nINSERT INTO \"MaterialToToolLevel\" (\"ID\",\"RequiredToolLevel\",\"ToolLevel\") VALUES ('Metal',2.0,2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('None','255 255 255 240',0.0,'None',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Grass','255 255 255 255',0.0,'Plant',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Dirt','171 125 35 255',0.5,'Soil',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Sand','235 235 100 255',0.5,'Sand',1.2);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Clay','144 88 78 255',0.5,'Clay',1.2);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Granite','128 128 128 255',0.7,'Stone',1.5);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Basalt','64 64 64 255',0.7,'Stone',1.8);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Marble','255 255 255 255',0.7,'Stone',1.3);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Sandstone','192 118 67 255',0.7,'Stone',1.2);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Bauxite','127 63 63 255',0.7,'Stone',1.3);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Serpentine','137 168 106 255',0.7,'Stone',1.5);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('LapisLazuli','75 93 255 255',0.7,'Stone',1.7);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Obsidian','16 16 16 255',3.4,'Stone',5.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Water','0 0 255 128',0.1,'Liquid',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Lava','255 90 0 255',1.0,'Liquid',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Pine','199 134 54 255',0.5,'Wood',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Oak','169 104 54 255',0.7,'Wood',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('AppleWood','199 101 54 255',0.5,'Wood',1.5);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Birch','242 210 105 255',0.5,'Wood',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Coal','64 64 64 255',0.5,'Coal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Copper','214 74 0 255',1.0,'Metal',6.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Malachite','28 140 70 255',1.0,'Metal',10.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Tin','127 127 127 255',0.5,'Metal',6.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Bronze','166 125 61 255',1.9,'Metal',15.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Iron','76 76 76 255',3.4,'Metal',10.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Steel','70 130 180 255',5.2,'Metal',25.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Lead','118 136 143 255',0.75,'Metal',15.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Silver','192 192 192 255',0.75,'Metal',50.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Gold','255 215 0 255',0.5,'Metal',75.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('RoseGold','183 110 121 255',0.5,'Metal',60.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Platinum','229 228 226 255',0.5,'Metal',90.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('FlintStone','10 10 10 255',0.7,'Gem',3.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Emerald','25 233 25 255',3.0,'Gem',4.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Amethyst','173 15 255 255',3.0,'Gem',4.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Diamond','255 255 255 255',3.0,'Gem',10.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Sapphire','0 0 160 255',3.0,'Gem',4.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Ruby','255 0 0 255',3.0,'Gem',4.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Amber','239 75 5 255',3.0,'Gem',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Beryll','0 154 58 255',3.0,'Gem',4.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Topaz','255 255 128 255',3.0,'Gem',4.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Wool','255 255 255 255',0.1,'Cloth',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('OrangeWood','198 161 115 255',0.5,'Wood',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Mushroom','255 255 255 255',0.1,'Plant',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Ceramic','164 79 58 255',0.7,'Stone',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Glass','255 255 255 255',0.1,'Glass',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Chicken','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Emu','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Yak','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Sheep','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Pig','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cow','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Rabbit','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Llama','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Duck','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Goose','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Dog','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cat','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Porcupine','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Fox','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Wolf','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Deer','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Badger','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('BlackBear','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Goat','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Squirrel','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('GreyFish','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('GreenFish','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('ChickenBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('EmuBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('YakBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('SheepBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('PigBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('CowBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('RabbitBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('LlamaBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('DuckBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('GooseBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('DogBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('CatBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('PorcupineBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('FoxBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('WolfBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('DeerBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('GoatBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('BadgerBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('BlackBearBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('SquirrelBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('GreyFishBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('GreenFishBone','255 255 255 255',0.1,'Bone',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('JobYellow','255 255 0 60',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('JobGreen','128 255 128 60',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('JobPurple','255 0 255 60',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('RendererStockpile','200 255 50 64',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('RendererGrove','128 255 255 64',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('RendererFarm','255 128 255 64',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('RendererWorkshop','245 140 180 64',NULL,'System',0.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Green','0 255 0 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Red','255 0 0 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Blue','0 0 255 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Purple','255 0 255 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cyan','0 255 255 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Yellow','255 255 0 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Grey','120 120 120 255',NULL,'Dye',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Goblin','255 255 255 255',NULL,'Monster',2.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Strawberry','255 255 255 255',0.1,'Fruit',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Apple','255 255 255 255',0.1,'Fruit',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Orange','255 255 255 255',0.1,'Fruit',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Wheat','253 196 23 255',0.25,'Grain',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cotton','255 255 255 255',0.1,'Cloth',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Carrot','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Onion','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Potato','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cabbage','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Asparagus','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Broccoli','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cauliflower','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Cucumber','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Garlic','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Parsnip','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Radish','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Turnip','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Lettuce','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Melon','255 255 255 255',0.1,'Fruit',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Sugarbeet','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Pumpkin','255 255 255 255',0.1,'Fruit',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Peas','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Tea','255 255 255 255',0.1,'Leaves',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Tobacco','255 255 255 255',0.1,'Leaves',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Pineapple','255 255 255 255',0.1,'Fruit',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Leek','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Corn','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Beans','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Blackberry','255 255 255 255',0.1,'Berries',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Artichoke','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Bottlegourd','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Tomato','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Capsicum','255 255 255 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Grape','255 255 255 255',0.1,'Berries',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('BeetRoot','255 0 0 255',0.1,'Vegetable',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Woad','255 255 255 255',0.1,'Leaves',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('DyersWeed','255 255 255 255',0.1,'Leaves',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Barley','255 255 255 255',0.1,'Grain',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Oat','255 255 255 255',0.1,'Grain',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Millet','255 255 255 255',0.1,'Grain',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower1','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower2','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower3','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower4','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower5','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower6','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower7','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Flower8','255 255 255 255',0.1,'Flower',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Bee','255 255 255 255',0.1,'Animal',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('YakLeather','255 255 255 255',0.5,'Leather',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('CowLeather','255 255 255 255',0.5,'Leather',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('EmuLeather','255 255 255 255',0.5,'Leather',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('BearLeather','255 255 255 255',0.5,'Leather',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('WolfLeather','255 255 255 255',0.5,'Leather',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('StagLeather','255 255 255 255',0.5,'Leather',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Glass','255 255 255 255',0.8,'Glass',1.0);\r\nINSERT INTO \"Materials\" (\"ID\",\"Color\",\"Strength\",\"Type\",\"Value\") VALUES ('Willow','189 124 74 255',0.7,'Wood',1.0);\r\nINSERT INTO \"Magic\" (\"ID\",\"Color\",\"Spells\") VALUES ('Nature','255 106 0 255','SpeedGrowth');\r\nINSERT INTO \"Magic\" (\"ID\",\"Color\",\"Spells\") VALUES ('Geomancy','175 114 86 255','RevealOre');\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Queen','5 5 0',0,0,2);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','7 3 0',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','3 3 0',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','3 7 0',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','7 7 0',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','11 15 3',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','12 15 3',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','11 16 3',0,0,1);\r\nINSERT INTO \"Lairs_Spawns\" (\"ID\",\"Type\",\"Offset\",\"Level\",\"Rotation\",\"Gender\") VALUES ('MantLair1','Soldier','12 16 3',0,0,1);\r\nINSERT INTO \"Lairs\" (\"ID\",\"Type\",\"Size\",\"Layout\") VALUES ('MantLair1','Mant','16 23 4','2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 1 1 2 3 3 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 2 2 2 0 0 2 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 2 2 1 1 1 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 1 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 3 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 3 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 1 2 2 1 1 2 2 2 2 2 2 2 2 2 2 1 1 1 2 1 1 2 2 1 2 2 2 2 2 2 1 1 1 1 1 1 1 2 1 1 1 2 2 2 2 2 2 1 1 1 2 1 1 1 1 1 1 1 2 2 2 2 2 2 1 2 2 1 1 2 1 1 1 2 2 2 2 2 2 2 2 2 2 1 1 2 2 1 2 2 2 2 2 2 2 2 2 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 2 2 2 1 1 1 2 2 2 2 2 2 2 1 1 2 2 1 2 2 1 1 2 2 2 2 2 2 2 1 1 1 1 1 1 2 1 1 2 2 2 2 2 2 2 1 1 2 2 1 2 2 3 3 2 2 2 2 2 2 2 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Fish',NULL,200,NULL,'0 0 0','Fish');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Mine',NULL,50,NULL,'0 0 0','MineWall');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('DigHole',NULL,20,NULL,'0 0 0','DigHole');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('ExplorativeMine',NULL,50,NULL,'0 0 0','ExplorativeMineWall');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('RemoveRamp',NULL,50,NULL,'0 0 0','RemoveRamp');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('RemoveFloor',NULL,50,NULL,'0 0 0','MineFloor');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Deconstruct',NULL,50,NULL,'0 0 0','Deconstruct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('RemovePlant',NULL,10,NULL,'0 0 0','RemovePlant');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('MineStairsUp',NULL,0,NULL,'0 0 0','ConstructDugStairs');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('DigStairsDown',NULL,50,NULL,'0 0 -1','ConstructDugStairs');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('DigRampDown','Ramp',50,NULL,'0 0 -1','ConstructDugRamp');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildWall','Wall',50,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildFence','Fence',50,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildFloor','Floor',20,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildWallFloor','WallFloor',100,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildStairs','Stairs',30,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildScaffold','Scaffold',10,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildRamp','ThatchRamp',20,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildRampCorner','RampCorner',10,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildWorkshop','Workshop',20,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildItem','Item',10,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildStorage','Storage',10,'SelectedMaterial','0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildFurniture','Furniture',10,NULL,'0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildDoor','Door',10,NULL,'0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('BuildTorch','Torch',10,NULL,'0 0 0','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Harvest',NULL,10,NULL,'0 0 0','Harvest');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('HarvestTree',NULL,10,NULL,'0 0 0','Harvest');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('PlantTree',NULL,10,NULL,'0 0 0','PlantTree');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Till',NULL,10,NULL,'0 0 0','Till');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Plant',NULL,10,NULL,'0 0 0','Plant');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('PlantFarm',NULL,10,NULL,'0 0 0','Plant');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('FellTree',NULL,10,NULL,'0 0 0','FellTree');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('CraftAtWorkshop',NULL,'$Craft',NULL,'0 0 0','Craft');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('ManMarketStall',NULL,10000,NULL,'0 0 0','Trade');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('ButcherCorpse',NULL,50,NULL,'0 0 0','ButcherCorpse');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('ButcherFish',NULL,50,NULL,'0 0 0','ButcherFish');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Magic_Nature_SpeedGrowth',NULL,0,NULL,'0 0 0','PrepareSpell');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Magic_Nature_SpeedGrowth',NULL,100,NULL,'0 0 0','CastSpell');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Magic_Nature_SpeedGrowth',NULL,0,NULL,'0 0 0','FinishSpell');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Magic_Geomancy_RevealOre',NULL,0,NULL,'0 0 0','PrepareSpell');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Magic_Geomancy_RevealOre',NULL,100,NULL,'0 0 0','CastSpell');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Magic_Geomancy_RevealOre',NULL,0,NULL,'0 0 0','FinishSpell');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('SwitchMechanism',NULL,10,NULL,'0 0 0','SwitchMechanism');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Refuel',NULL,30,NULL,'0 0 0','Refuel');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('InvertMechanism',NULL,10,NULL,'0 0 0','InvertMechanism');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Install',NULL,30,NULL,'0 0 0','Install');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('Uninstall',NULL,30,NULL,'0 0 0','Uninstall');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('FillTrough',NULL,10,NULL,'0 0 0','FillTrough');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('FillHole','Wall',50,'SelectedMaterial','0 0 -1','Construct');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('HarvestHay',NULL,10,NULL,'0 0 0','HarvestHay');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('SoundAlarm','',5,'','0 0 0','SoundAlarm');\r\nINSERT INTO \"Jobs_Tasks\" (\"ID\",\"ConstructionID\",\"Duration\",\"Material\",\"Offset\",\"Task\") VALUES ('EquipItem','',5,'','0 0 0','EquipItem');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Mine','0 0 0',0,'MiningJobWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigHole','0 0 -1',0,'MiningJobWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigHole','0 0 0',0,'SolidSelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('ExplorativeMine','0 0 0',0,'MiningJobWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('RemoveRamp','0 0 0',0,'MiningJobWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('RemoveFloor','0 0 0',0,'SolidSelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Deconstruct','0 0 0',0,'SelectionWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('RemovePlant','0 0 0',0,'SelectionWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('MineStairsUp','0 0 0',1,'Stairs',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('MineStairsUp','0 0 1',1,'StairsTop','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigStairsDown','0 0 -1',1,'Stairs',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigStairsDown','0 0 0',1,'StairsTop','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigStairsDown','0 0 0',0,'SelectionWall','Wall');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigRampDown','0 0 -1',1,'Ramp',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('DigRampDown','0 0 0',1,'RampTop','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildWall','0 0 0',0,'SolidSelectionWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildFence','0 0 0',0,'WoodFence',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildFloor','0 0 0',0,'SolidSelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildWallFloor','0 0 0',0,'SelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildWallFloor','0 0 0',0,'SelectionWall','Wall');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildStairs','0 0 0',1,'Stairs',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildStairs','0 0 1',1,'StairsTop','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildScaffold','0 0 0',0,'Scaffold','Wall');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildScaffold','0 0 1',0,'ScaffoldFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildRamp','0 0 0',1,'ThatchRamp',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildRamp','0 0 1',0,'ThatchRampTop','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('BuildRampCorner','0 0 0',1,'OuterCornerRamp',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Harvest','0 0 0',0,'SolidSelectionWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('HarvestTree','0 0 0',0,'SolidSelectionWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('PlantTree','0 0 0',0,'Sapling',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Till','0 0 0',0,'SolidSelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Plant','0 0 0',0,'SelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('PlantFarm','0 0 0',0,'SelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('FellTree','0 0 0',0,'SolidSelectionWall',NULL);\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Magic_Nature_SpeedGrowth','0 0 0',0,'Pentagram','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('Magic_Geomancy_RevealOre','0 0 0',0,'Pentagram','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('FillHole','0 0 0',0,'SelectionFloor','Floor');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('FillHole','0 0 -1',0,'SolidSelectionWall','Wall');\r\nINSERT INTO \"Jobs_SpriteID\" (\"ID\",\"Offset\",\"Rotate\",\"SpriteID\",\"Type\") VALUES ('SoundAlarm','0 0 0',0,'SelectionWall','Wall');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('HauleItem',NULL,0,NULL,NULL,NULL,'Hauling',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('HauleMultipleItems',NULL,0,NULL,NULL,NULL,'Hauling',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Fish',NULL,0,NULL,NULL,NULL,'Fishing',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Mine',NULL,0,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('DigHole',NULL,1,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('ExplorativeMine',NULL,0,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('RemoveRamp',NULL,0,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('RemoveFloor',NULL,1,'Pickaxe','ByFloorMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Deconstruct',NULL,0,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('RemovePlant',NULL,0,NULL,NULL,NULL,'Farming',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('MineStairsUp',NULL,0,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('DigStairsDown',NULL,0,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('DigRampDown',NULL,0,'Pickaxe','ByWallMaterial',NULL,'Mining',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildWall','Wall',1,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildFence','Fence',1,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildFloor','Floor',0,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildWallFloor','WallFloor',1,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildStairs','Stairs',0,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildScaffold','Scaffold',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildRamp','Ramp',0,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildRampCorner','RampCorner',0,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildWorkshop','Workshop',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildItem','Item',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildStorage','Storage',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildFurniture','Furniture',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildDoor','Door',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('BuildTorch','Torch',0,NULL,NULL,NULL,'Construction',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Harvest',NULL,0,NULL,NULL,NULL,'Farming',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('HarvestTree',NULL,0,NULL,NULL,NULL,'Horticulture',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('PlantTree',NULL,0,NULL,NULL,NULL,'Horticulture',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Till',NULL,0,NULL,NULL,NULL,'Farming',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Plant','Plant',0,NULL,NULL,NULL,'Farming',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('PlantFarm','Plant',0,NULL,NULL,NULL,'Farming',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('FellTree',NULL,0,'FellingAxe','ByPlantMaterial',NULL,'Woodcutting',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('CraftAtWorkshop',NULL,0,NULL,NULL,'$Craft','WorkshopSkill','$Craft','0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('ManMarketStall',NULL,0,NULL,NULL,NULL,'Trading',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('ButcherCorpse',NULL,0,NULL,NULL,NULL,'Butchery',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('ButcherFish',NULL,0,NULL,NULL,NULL,'Butchery',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('LeadAnimalToPasture',NULL,0,NULL,NULL,NULL,'AnimalHusbandry',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('HarvestAnimal',NULL,0,NULL,NULL,NULL,'AnimalHusbandry',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('TameAnimal',NULL,0,NULL,NULL,NULL,'AnimalHusbandry',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('ButcherAnimal',NULL,0,NULL,NULL,NULL,'Butchery',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Magic_Nature_SpeedGrowth',NULL,0,NULL,NULL,NULL,'MagicNature',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Magic_Geomancy_RevealOre',NULL,0,NULL,NULL,NULL,'MagicGeomancy',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('SwitchMechanism',NULL,0,NULL,NULL,NULL,'Machining',NULL,'0 0 0|-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Refuel',NULL,0,NULL,NULL,NULL,'Machining',NULL,'0 0 0|-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('InvertMechanism',NULL,0,NULL,NULL,NULL,'Machining',NULL,'0 0 0|-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Install',NULL,0,NULL,NULL,NULL,'Machining',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('Uninstall',NULL,0,NULL,NULL,NULL,'Machining',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('FillTrough',NULL,0,NULL,NULL,NULL,'AnimalHusbandry',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('FillHole','Wall',1,NULL,NULL,NULL,'Construction',NULL,'-1 0 0|0 -1 0|1 0 0|0 1 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('HarvestHay',NULL,0,NULL,NULL,NULL,'Farming',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('EquipItem',NULL,0,NULL,NULL,NULL,'Hauling',NULL,'0 0 0');\r\nINSERT INTO \"Jobs\" (\"ID\",\"ConstructionType\",\"MayTrapGnome\",\"RequiredToolItemID\",\"RequiredToolLevel\",\"SkillGain\",\"SkillID\",\"TechGain\",\"WorkPosition\") VALUES ('SoundAlarm','',0,'','','','Machining','','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Bed','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('FancyBed','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Chair','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Table','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Cabinet','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Dresser','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Bookshelf','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Painting','Wall|Tree|Construction|Plant|Job','Floor|AllowFurniture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Crate','Wall|Tree|Construction|Plant|Job','Floor|Stockpile','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Barrel','Wall|Tree|Construction|Plant|Job','Floor|Stockpile','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Bag','Wall|Tree|Construction|Plant|Job','Floor|Stockpile','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Door','Wall|Tree|Construction|Plant|Job|Designation','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Torch','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Statue','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Trough','Wall|Tree|Construction|Plant|Job','Floor|Pasture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Shed','Wall|Tree|Construction|Plant|Job','Floor|Pasture','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('BeeHive','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Sack','Wall|Tree|Construction|Plant|Job','Floor|Stockpile','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Axle','Wall|Tree|Plant|Job|Mechanism','Floor','FloorHidden','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('VerticalAxle','Wall|Tree|Construction|Plant|Job','GearBox','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('SteamEngine','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('GearBox','Wall|Tree|Construction|Plant|Job','Floor','Floor','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Pump','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Lever','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('MechanicalWall','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('PressurePlate','Wall|Tree|Construction|Plant|Job','Floor','Floor','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('AlarmBell','Wall|Tree|Construction|Plant|Job','Floor|AllowBell','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('WallTorch','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('WallTorch',NULL,'Wall','Wall','-1 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Chest','Wall|Tree|Construction|Plant|Job','Floor|Stockpile','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('BigTorch','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Tiles\" (\"ID\",\"Forbidden\",\"Required\",\"Location\",\"Offset\") VALUES ('Brazier','Wall|Tree|Construction|Plant|Job','Floor','Wall','0 0 0');\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('WoodBed','WoodBedFrame',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('WoodBed','Mattress',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('FancyBed','FancyBedFrame',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('FancyBed','Mattress',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Knife','KnifeBlade',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Knife','KnifeHilt',1);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Pickaxe','PickaxeHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Pickaxe','PickaxeBase',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('FellingAxe','FellingAxeHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('FellingAxe','FellingAxeBase',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('AlarmBell','AlarmBellBell',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('AlarmBell','AlarmBellBase',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Sword','SwordBlade',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Sword','Hilt',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('GearBox','GearBoxBase',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('GearBox','GearBoxFrame',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('MechanismBase','Gear',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('MechanismBase','Spring',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('SteamEngine','Cylinder',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('SteamEngine','MechanismBase',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('SteamEngine','Gear',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('SteamEngine','Rod',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Lever','LeverBase',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Lever','LeverHandle',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Automaton','AutomatonHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Automaton','AutomatonTorso',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Automaton','AutomatonArm',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Automaton','AutomatonArm',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Automaton','AutomatonLeg',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Automaton','AutomatonLeg',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Hammer','HammerHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Hammer','Haft',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Warhammer','WarhammerHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Warhammer','Haft',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Claymore','ClaymoreBlade',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('Claymore','Hilt',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('HandAxe','HandAxeHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('HandAxe','Haft',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('BattleAxe','BattleAxeHead',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('BattleAxe','Haft',0);\r\nINSERT INTO \"Items_Components\" (\"ID\",\"ItemID\",\"NoMaterial\") VALUES ('WallTorch','Torch',0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawSoil','RawSoil','Materials','Soil',20,0,1,0,0,0,0,0,0,'Soil|Sand',NULL,NULL,'Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawStone','RawStone','Materials','Stone',10,0,1,0,0,0,0,0,0,'Stone',NULL,NULL,'Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawWood','RawWood','Materials','Wood',1,0,1,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawCoal','RawCoal','Materials','Wood',20,0,2,0,0,0,0,0,0,'Coal',NULL,'Crate','Wheelbarrow',0,3000);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawOre','RawOre','Materials','Metal',20,0,2,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawGem','RawGem','Materials','Gem',4,0,1,0,0,0,0,0,0,'Gem',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Gem','Gem','Materials','Gem',4,0,2,0,0,0,0,0,0,'Gem',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Seed','Seed','Grown','Plant',1,0,1,0,0,0,0,0,0,'Vegetable|Fruit|Flower|Grain|Leaves|Berries','Cotton','Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bed','Bed','Furniture','Beds',1,1,10,0,0,0,0,0,0,'Wood|Bone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('WoodBedFrame','WoodBedFrame','Furniture','Parts',1,1,10,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FancyBedFrame','FancyWoodBedFrame','Furniture','Parts',1,1,9,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FancyBed','FancyBed','Furniture','Beds',1,1,10,0,0,0,0,0,1,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Mattress','Mattress','Furniture','Parts',1,1,9,0,0,0,0,0,0,'Cloth',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Chair','Chair','Furniture','Chairs',1,1,9,0,0,0,0,0,0,'Wood|Stone|Bone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Table','Table','Furniture','Tables',1,1,12,0,0,0,0,0,0,'Wood|Stone|Bone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Cabinet','Cabinet','Furniture','Cabinets',1,1,13,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Dresser','Dresser','Furniture','Cabinets',1,1,13,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Painting','Painting','Furniture','Misc',1,1,200,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Stick','FellingAxeBase','Materials','Wood',1,0,3,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sawblade','Gear','Workshop','Tools',1,1,3,0,0,0,0,0,0,'Metal|Stone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bone','Bone','Butchery','Bones',1,0,1,0,0,0,0,0,0,'Bone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FishBone','Bone','Butchery','Bones',1,0,1,0,0,0,0,0,0,'Bone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Skull','Skull','Butchery','Bones',1,0,1,0,0,0,0,0,0,'Bone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Hide','RawHide','Butchery','Hides',1,0,1,0,0,0,0,0,0,'Animal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawCloth','Fiber','Cloth','Unprocessed',1,0,1,0,0,0,0,0,0,'Cloth',NULL,'Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Plank','Plank','Materials','Wood',1,0,6,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Workbench','Workbench','Workshop','Workplaces',1,1,13,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Chisel','Chisel','Workshop','Tools',1,1,3,0,0,0,0,0,0,'Stone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Crate','Crate','Containers','Immovable',1,1,9,0,0,1,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Barrel','Barrel','Containers','Immovable',1,1,9,0,0,1,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bag','Bag','Containers','Movable',1,1,13,0,0,1,0,0,0,'Cloth',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sack','Sack','Containers','Immovable',1,1,13,0,0,1,0,0,0,'Cloth',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bucket','Bucket','Containers','Movable',1,1,9,0,0,1,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Block','Block','Materials','Stone',1,0,2,0,0,0,0,0,0,'Stone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Brick','Block','Materials','Soil',1,0,3,0,0,0,0,0,0,NULL,'Clay|Sand','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Hilt','SwordBase','Weapons','WeaponsComponents',1,0,4,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Haft','FellingAxeBase','Weapons','WeaponsComponents',1,0,4,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('KnifeBlade','KnifeBlade','Workshop','Tools',1,0,3,0,0,0,0,0,0,'Stone|Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('KnifeHilt','KnifeHilt','Workshop','Tools',1,0,10,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Knife','Knife','Workshop','Tools',1,1,5,0,0,0,1,0,1,'Stone|Metal',NULL,'Crate','Wheelbarrow',5,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PickaxeHead','PickaxeHead','Workshop','Tools',1,1,29,0,0,0,0,0,0,'Wood|Stone|Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PickaxeBase','PickaxeBase','Workshop','Tools',1,0,4,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Pickaxe','Pickaxe','Workshop','Tools',1,1,5,0,0,0,1,0,1,'Wood|Stone|Metal',NULL,'Crate','Wheelbarrow',5,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Door','Door','Utility','Doors',1,0,9,0,0,0,0,0,0,'Wood|Stone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Torch','GroundTorch','Utility','Lights',1,0,4,0,0,0,0,21,0,'Wood',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('CrystalMushroom','CrystalShroom','Food','Raw',1,0,10,10,0,0,0,0,0,'Mushroom',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Mold','Mold','Workshop','Tools',1,0,9,0,0,0,0,0,0,'Stone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Hearth','Forge','Workshop','Tools',1,0,13,0,0,0,0,0,0,'Stone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bellows','BellowsWithNozzle','Workshop','Tools',1,0,5,0,0,0,0,0,0,'Wood',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bar','Bar','Materials','Metal',1,0,20,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Furnace','Furnace','Workshop','Workplaces',1,0,21,0,0,0,0,0,0,'Stone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Anvil','Anvil','Workshop','Workplaces',1,0,225,0,0,0,0,0,0,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('CuttingWheel','Gear','Workshop','Tools',1,0,29,0,0,0,0,0,0,'Metal|Stone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FellingAxeHead','FellingAxeHead','Workshop','Tools',1,0,29,0,0,0,0,0,0,'Wood|Stone|Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FellingAxeBase','FellingAxeBase','Workshop','Tools',1,0,10,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FellingAxe','FellingAxe','Workshop','Tools',1,1,30,0,0,0,1,0,1,'Wood|Stone|Metal',NULL,'Crate','Wheelbarrow',5,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('File','File','Workshop','Tools',1,0,29,0,0,0,0,0,0,'Metal',NULL,NULL,'Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BallPeenHammer','Hammer','Workshop','Tools',1,0,29,0,0,0,0,0,0,'Metal',NULL,'Crate',NULL,5,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AlarmBellBase','AlarmBellBase','Furniture','Parts',1,0,10,0,0,0,0,0,0,'Wood',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AlarmBellBell','AlarmBellBell','Furniture','Parts',1,0,10,0,0,0,0,0,0,'Metal',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AlarmBell','AlarmBell','Utility','Other',1,0,57,0,0,0,0,0,1,'Metal',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Statue','Statue','Furniture','Misc',1,1,100,0,0,0,0,0,0,'Wood|Stone|Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Statuette','Statuette','Furniture','Misc',1,1,25,0,0,0,0,0,0,'Wood|Stone|Metal',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Coin','Coin','Furniture','Misc',1,1,25,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Loom','Loom','Workshop','Workplaces',1,0,13,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bolt','Bolt','Cloth','ClothProducts',1,0,6,0,0,0,0,0,0,'Cloth',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Trough','Trough','Utility','Farm',1,0,9,0,0,0,0,0,0,'Stone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Shed','Shed','Utility','Farm',1,0,20,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BeeHive','BeeHiveEmpty','Utility','Farm',1,0,20,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Pillar','StonePillar','Furniture','Misc',1,0,9,0,0,0,0,0,0,'Stone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PetRock','PetRock','Furniture','Misc',1,1,3,0,0,0,0,0,0,'Stone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PuzzleBox','PuzzleBox','Furniture','Misc',1,1,3,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Ring','JewelryPile','Jewelry','JewelryProducts',1,1,29,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GemmedRing','JewelryPile','Jewelry','JewelryProducts',1,1,29,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Necklace','JewelryPile','Jewelry','JewelryProducts',1,1,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GemmedNecklace','JewelryPile','Jewelry','JewelryProducts',1,1,29,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Needle','BoneNeedle','Workshop','Tools',1,0,2,0,0,0,0,0,0,'Metal|Bone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('String','String','Cloth','ClothProducts',1,0,3,0,0,0,0,0,0,'Cloth',NULL,'Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Straw','Straw','Grown','Plant',10,0,1,0,0,0,0,0,0,'Grain',NULL,NULL,'Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bandage','Bandage','Cloth','ClothProducts',1,0,3,0,0,0,0,0,0,'Cloth',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Padding','Fiber','Cloth','ClothProducts',1,0,4,0,0,0,0,0,0,'Cloth',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherStrap','LeatherStrip','Cloth','ClothProducts',1,0,2,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SkullHelmet','Skull','Armor','BoneArmor',1,0,2,0,0,0,0,0,0,'Bone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BoneShirt','BoneShirt','Armor','BoneArmor',1,0,5,0,0,0,0,0,0,'Bone',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('WoodTub','WoodTub','Workshop','Workplaces',1,0,10,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Dye','Dye','Workshop','Materials',1,0,5,0,0,0,0,0,0,'Dye',NULL,'Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AmmoPouch','AmmoPouch','Armor','Leather',1,1,4,0,0,0,0,0,0,NULL,'Cow|Yak|Emu','Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Wheelbarrow','Wheelbarrow','Containers','Movable',1,1,9,0,0,0,1,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FishingRod','FishingRod','Workshop','Tools',1,1,4,0,0,0,1,0,0,'Wood',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Fish','GreenFish','Butchery','Corpses',10,0,1,0,0,0,0,0,0,NULL,'GreenFish|GreyFish','Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AnimalCorpse','Corpse','Butchery','Corpses',1,0,0,0,0,0,0,0,0,'Animal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GoblinCorpse','MonsterCorpse','Butchery','Corpses',1,0,0,0,0,0,0,0,0,'Goblin',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Cone','PineCone','Grown','Tree',1,0,0,0,0,0,0,0,0,NULL,'Pine','Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Oak','Oak','Grown','Tree',1,0,0,0,0,0,0,0,0,NULL,'Oak','Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Corpse',NULL,'Butchery','Corpses',1,0,0,0,0,0,0,0,0,'Animal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Meat','Meat','Food','Raw',1,0,1,0,0,0,0,0,0,'Animal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FishMeat','Meat','Food','Raw',1,0,1,0,0,0,0,0,0,NULL,'GreenFish|GreyFish','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Egg','Egg','Food','Raw',1,0,1,0,0,0,0,0,0,NULL,'Chicken|Duck|Goose|Emu','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Milk','Milk','Drinks','NonAlcoholic',1,0,1,0,30,0,0,0,0,NULL,'Cow|Yak','Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bread','Bread','Food','Cooked',1,1,10,25,0,0,0,0,0,'Grain',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sandwich','Sandwich','Food','Cooked',1,1,30,50,0,0,0,0,0,'Grain',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Wine','Wine','Drinks','Alcoholic',1,1,2,0,40,0,0,0,0,'Fruit|Berries',NULL,'Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Beer','Beer','Drinks','Alcoholic',1,1,2,0,50,0,0,0,0,'Grain',NULL,'Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Tea','TeaCup','Drinks','NonAlcoholic',1,1,2,0,30,0,0,0,0,NULL,'Tea','Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('CheeseOmelette','Omelette','Food','Cooked',1,1,10,40,0,0,0,0,0,NULL,NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('MushroomOmelette','Omelette','Food','Cooked',1,1,10,40,0,0,0,0,0,NULL,NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sausage','Sausage','Food','Cooked',1,1,10,30,0,0,0,0,0,'Animal|Monster',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SausageOmelette','Omelette','Food','Cooked',1,1,10,50,0,0,0,0,0,NULL,NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Cheese','Cheese','Food','Cooked',1,1,10,25,0,0,0,0,0,NULL,'Cow|Yak','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Fruit','Fruit','Food','Raw',1,0,1,20,0,0,0,0,0,'Fruit',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Vegetable','Vegetable','Food','Raw',1,0,1,20,0,0,0,0,0,'Vegetable',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Berries','Berries','Food','Raw',1,0,1,10,0,0,0,0,0,'Berries',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Leaves','Leaves','Food','Other',1,0,1,0,0,0,0,0,0,'Leaves',NULL,'Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Mushroom','MushroomItem','Food','Raw',1,0,1,0,0,0,0,0,0,'Mushroom',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Grain','Grain','Grown','Plant',1,0,1,0,0,0,0,0,0,'Grain',NULL,'Sack','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sliver','MetalSliver','Materials','Metal',1,0,11,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RawHide','RawHide','Butchery','Hides',1,0,1,0,0,0,0,0,0,NULL,'Cow|Yak|Emu','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherArmorPanel','LeatherPanel','Armor','Leather',1,1,2,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherHelm','LeatherArmorHead','Armor','Leather',1,1,7,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherCuirass','LeatherArmorChest','Armor','Leather',1,1,9,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherBoot','LeatherArmorFeet','Armor','Leather',1,1,5,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherPants','LeatherArmorLegs','Armor','Leather',1,1,1,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherBracer','LeatherArmorArms','Armor','Leather',1,1,5,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeatherGlove','LeatherArmorHands','Armor','Leather',1,1,5,0,0,0,0,0,0,NULL,'CowLeather|YakLeather|EmuLeather','Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ChainHelm','ChainArmorHead','Armor','Chainmail',1,1,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ChainShirt','ChainArmorChest','Armor','Chainmail',1,1,113,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ChainBracer','ChainArmorArms','Armor','Chainmail',1,1,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ChainGlove','ChainArmorHands','Armor','Chainmail',1,1,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ChainPants','ChainArmorLegs','Armor','Chainmail',1,1,85,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ChainBoot','ChainArmorFeet','Armor','Chainmail',1,1,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PlateHelm','PlateArmorHead','Armor','Plate',1,1,229,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PlateChest','PlateArmorChest','Armor','Plate',1,1,457,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PlatePauldron','PlateArmorArms','Armor','Plate',1,1,229,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PlateGlove','PlateArmorHands','Armor','Plate',1,1,229,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PlateGreaves','PlateArmorLegs','Armor','Plate',1,1,343,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PlateBoot','PlateArmorFeet','Armor','Plate',1,1,229,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HeavyPlateHelm','HeavyPlateArmorHead','Armor','HeavyPlate',1,1,457,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HeavyPlateChest','HeavyPlateArmorChest','Armor','HeavyPlate',1,1,913,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HeavyPlatePauldron','HeavyPlateArmorArms','Armor','HeavyPlate',1,1,457,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HeavyPlateGlove','HeavyPlateArmorHands','Armor','HeavyPlate',1,1,457,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HeavyPlateGreaves','HeavyPlateArmorLegs','Armor','HeavyPlate',1,1,685,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HeavyPlateBoot','HeavyPlateArmorFeet','Armor','HeavyPlate',1,1,457,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ArmorPlate','ArmorPlate','Armor','Plate',1,0,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sword','Sword','Weapons','WeaponsMetal',1,1,142,0,0,0,0,0,1,'Wood|Stone|Metal',NULL,'Crate','Wheelbarrow',10,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SwordBlade','SwordBlade','Weapons','WeaponsComponents',1,1,141,0,0,0,0,0,0,'Wood|Stone|Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('TrainingDummy','TrainingDummy','Workshop','Workplaces',1,0,7,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GearBox','GearBox','Utility','Mechanism',1,0,100,0,0,0,0,0,1,NULL,NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GearBoxBase','GearBoxBase','Parts','Mechanism',1,0,50,0,0,0,0,0,0,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GearBoxFrame','GearBoxFrame','Parts','Mechanism',1,0,50,0,0,0,0,0,0,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SteamEngine','SteamEngine','Utility','Mechanism',1,0,60,0,0,0,0,0,1,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Gear','Gear','Parts','Mechanism',1,0,29,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Rod','FellingAxeBase','Parts','Mechanism',1,0,29,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('MechanismBase','GearBoxFrame','Parts','Mechanism',1,0,59,0,0,0,0,0,1,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Spring','Spring','Parts','Mechanism',1,0,29,0,0,0,0,0,0,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Cylinder','Cylinder','Parts','Mechanism',1,0,57,0,0,0,0,0,0,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Axle','Axle','Utility','Mechanism',1,0,30,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('VerticalAxle','VerticalAxle','Utility','Mechanism',1,0,20,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Pipe','PipeItem','Utility','Hydraulics',1,0,20,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PipeExit','PipeFittingItem','Utility','Hydraulics',1,0,20,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Pump','Pump','Utility','Hydraulics',1,0,50,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Lever','LeverOff','Utility','Mechanism',1,0,60,0,0,0,0,0,1,'Metal',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeverBase','LeverBase','Parts','Mechanism',1,0,30,0,0,0,0,0,0,'Metal',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('LeverHandle','FellingAxeBase','Parts','Mechanism',1,0,20,0,0,0,0,0,0,'Wood',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Wrench','Wrench','Workshop','Tools',1,1,29,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Spike','Spike','Parts','Mechanism',1,1,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Screw','Screw','Parts','Mechanism',1,0,57,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Handcrank','Handcrank','Utility','Mechanism',1,0,60,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('TrapBase','GearBoxFrame','Parts','Mechanism',1,0,60,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SpikeTrap','SpikeTrapItem','Utility','Mechanism',1,0,172,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BladeTrap','BladeTrapItemBlade','Utility','Mechanism',1,0,142,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('MechanicalWall','MechanicalWallItem','Utility','Mechanism',1,0,60,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('WindmillBlade','WindmillBlade','Parts','Mechanism',1,0,3,0,0,0,0,0,0,'Wood',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PressurePlate','MechanicalWallOpen','Utility','Mechanism',1,0,60,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Hatch','HatchFrameItem','Utility','Mechanism',1,0,60,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Automaton','Automaton','Utility','Automaton',1,0,459,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AutomatonHead','AutomatonHead','Parts','Automaton',1,0,172,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AutomatonTorso','AutomatonTorso','Parts','Automaton',1,0,286,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AutomatonArm','AutomatonArm','Parts','Automaton',1,0,172,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AutomatonLeg','AutomatonFoot','Parts','Automaton',1,0,229,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AutomatonCoreMark1','AutomatonCore','Parts','Automaton',1,0,115,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('AutomatonCoreMark2','AutomatonCore','Parts','Automaton',1,0,229,0,0,0,0,0,0,'Metal',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Flour','FlourSack','Food','Other',1,0,58,0,0,0,0,0,0,'Grain',NULL,'Sack','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BoneBedFrame','BoneBedFrame','Furniture','Parts',1,1,7,0,0,0,0,0,0,'Bone',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Hay','Hay','Grown','Plant',20,0,1,0,0,0,0,0,0,'Grass','Grass',NULL,'Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Honey','Honey','Food','Raw',1,0,1,0,0,0,0,0,0,NULL,'Bee','Barrel',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HammerHead','HammerHead','Weapons','WeaponsComponents',1,1,140,0,0,0,0,0,0,'Metal|Stone',NULL,'Crate',NULL,0,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('WarhammerHead','WarhammerHead','Weapons','WeaponsComponents',1,1,140,0,0,0,0,0,0,'Metal|Stone',NULL,'Crate',NULL,0,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Hammer','Hammer','Weapons','WeaponsMetal',1,1,150,0,0,0,0,0,0,NULL,NULL,'Crate',NULL,10,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Warhammer','Warhammer','Weapons','WeaponsMetal',1,1,150,0,0,0,0,0,0,NULL,NULL,'Crate',NULL,15,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ClaymoreBlade','ClaymoreBlade','Weapons','WeaponsComponents',1,1,180,0,0,0,0,0,0,'Metal|Stone',NULL,'Crate',NULL,NULL,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HandAxeHead','HandAxeHead','Weapons','WeaponsComponents',1,1,100,0,0,0,0,0,0,'Metal',NULL,'Crate',NULL,NULL,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BattleAxeHead','BattleAxeHead','Weapons','WeaponsComponents',1,1,149,0,0,0,0,0,0,'Metal',NULL,'Crate',NULL,NULL,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('WallTorch','WallTorch','Utility','Lights',1,0,4,0,0,0,0,21,0,'Wood',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Chest','Chest','Containers','Immovable',1,1,100,0,0,1,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Bookshelf','Bookshelf','Furniture','Cabinets',1,1,20,0,0,0,0,0,0,'Wood',NULL,NULL,NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('BigTorch','BigTorch','Utility','Lights',1,0,10,0,0,0,0,30,0,'Metal',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Brazier','Brazier','Utility','Lights',1,0,20,0,0,0,0,25,0,'Metal',NULL,'Crate',NULL,0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Backpack','Backpack','Armor','Leather',1,0,30,0,0,0,0,0,0,'Leather',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GlassIngot','GlassIngot','Materials','Gem',1,0,20,0,0,0,0,0,0,'Glass',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('RoughGlassGem','RoughGlassGem','Materials','Gem',1,0,20,0,0,0,0,0,0,'Glass',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('MosaicTile','MosaicTile','Materials','Gem',1,0,20,0,0,0,0,0,0,'Glass',NULL,'Crate','Wheelbarrow',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Cider','Cider','Drinks','Alcoholic',1,1,2,0,50,0,0,0,0,'Fruit',NULL,'Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Vinegar','Vinegar','Food','Other',1,0,1,0,0,0,0,0,0,'Fruit',NULL,'Barrel','Bucket',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Sugar','Sugar','Food','Other',1,0,5,5,0,0,0,0,0,NULL,'Sugarbeet','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('DropCandy','DropCandy','Food','Cooked',1,1,10,10,0,0,0,0,0,NULL,'Sugarbeet','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('ShepherdsPie','ShepherdsPie','Food','Cooked',1,1,50,50,0,0,0,0,0,'Vegetable',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('Biscuit','Biscuit','Food','Cooked',1,1,10,25,0,0,0,0,0,'Grain',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PickledFruit','PickledFruit','Food','Cooked',1,1,40,20,0,0,0,0,0,'Fruit',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FruitPreserve','FruitPreserve','Food','Cooked',1,1,50,25,0,0,0,0,0,'Fruit',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SmokedMeat','SmokedMeat','Food','Cooked',1,1,10,25,0,0,0,0,0,'Animal',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SmokedSausage','SmokedSausage','Food','Cooked',1,1,10,25,0,0,0,0,0,'Animal',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FruitBread','FruitBread','Food','Cooked',1,1,20,30,0,0,0,0,0,'Fruit',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FreshCheese','FreshCheese','Food','Cooked',1,1,10,20,0,0,0,0,0,NULL,'Cow|Yak','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('HardCheese','HardCheese','Food','Cooked',1,1,10,20,0,0,0,0,0,NULL,'Cow|Yak','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('MeatPie','MeatPie','Food','Cooked',1,1,20,25,0,0,0,0,0,'Animal',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PickledVegetable','PickledVegetable','Food','Cooked',1,1,40,20,0,0,0,0,0,'Vegetable',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('PickledEgg','PickledEgg','Food','Cooked',1,1,40,20,0,0,0,0,0,NULL,'Chicken|Duck|Goose|Emu','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('VegetablePreserve','VegetablePreserve','Food','Cooked',1,1,50,25,0,0,0,0,0,'Vegetable',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SmokedBird','SmokedBird','Food','Cooked',1,1,10,25,0,0,0,0,0,NULL,'Chicken|Duck|Goose|Emu','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('SmokedFish','SmokedFish','Food','Cooked',1,1,10,25,0,0,0,0,0,NULL,'GreenFish|GreyFish','Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FlatBread','FlatBread','Food','Cooked',1,1,10,20,0,0,0,0,0,'Grain',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FruitPie','FruitPie','Food','Cooked',1,1,20,30,0,0,0,0,0,'Fruit',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('VeggiePie','VeggiePie','Food','Cooked',1,1,20,30,0,0,0,0,0,'Vegetable',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('FineMeatPie','FineMeatPie','Food','Cooked',1,1,20,50,0,0,0,0,0,'Animal',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GlassJar','GlassJar','Workshop','Materials',1,0,10,0,0,0,0,0,0,'Glass',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"Items\" (\"ID\",\"SpriteID\",\"Category\",\"ItemGroup\",\"StackSize\",\"HasQuality\",\"Value\",\"EatValue\",\"DrinkValue\",\"IsContainer\",\"IsTool\",\"LightIntensity\",\"HasComponents\",\"AllowedMaterialTypes\",\"AllowedMaterials\",\"AllowedContainers\",\"CarryContainer\",\"AttackValue\",\"BurnValue\") VALUES ('GlassBottle','GlassBottle','Workshop','Materials',1,0,10,0,0,0,0,0,0,'Glass',NULL,'Crate','Bag',0,0);\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Materials','Gem','Gem');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Materials','Soil','RawSoil');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Materials','Metal','RawOre');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Materials','Stone','Block');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Materials','Wood','RawWood');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Grown','Plant','Straw');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Workshop','Tools','Knife');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Workshop','Workplaces','Workbench');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Food','Other','Leaves');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Food','Raw','Fruit');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Food','Cooked','Sausage');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Drinks','Alcoholic','Wine');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Drinks','NonAlcoholic','Milk');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Containers','Immovable','Crate');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Containers','Movable','Wheelbarrow');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Furniture','Chairs','WoodChair');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Furniture','Tables','Table');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Furniture','Beds','WoodBed');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','Doors','Door');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Furniture','Misc','Painting');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Furniture','FarmUtils','Shed');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Cloth','Unprocessed','RawCloth');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Cloth','ClothProducts','Bolt');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Leather','LeatherProducts','LeatherStrap');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Jewelry','JewelryProducts','Ring');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Butchery','Corpses','Skull');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Butchery','Bones','Bone');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Butchery','Meats','Meat');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Butchery','Hides','Hide');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Armor','Leather','LeatherArmorChest');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Armor','Chainmail','ChainArmorChest');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Armor','Plate','PlateArmorChest');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Armor','HeavyPlate','HeavyPlateArmorChest');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Weapons','WeaponsMetal','Sword');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Weapons','WeaponsComponents','SwordBlade');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Furniture','Parts','FancyBedFrame');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','Lights','Torch');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Armor','BoneArmor','BoneArmorChest');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Food','Meat','Meat');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Workshop','Materials','Dye');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','Mechanism','Gear');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','Hydraulics','Pipe');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','Automaton','Automaton');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','Farm','BeeHiveFull');\r\nINSERT INTO \"ItemGrouping_Groups\" (\"ID\",\"GroupID\",\"SpriteID\") VALUES ('Utility','AlarmBell','AlarmBell');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Materials','160 160 160 255','RawOre');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Grown','160 255 160 255','Sapling');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Workshop','220 220 160 255','Gear');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Food','160 160 225 255','Fruit');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Drinks','160 160 225 255','Milk');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Containers','255 160 160 255','Crate');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Furniture','160 160 160 255','Cabinet');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Cloth','225 225 255 255','DyedCloth');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Armor','225 225 255 255','LeatherArmorChest');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Jewelry','225 225 255 255','Gem');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Butchery','160 160 160 255','Meat');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Weapons','255 255 255 255','Sword');\r\nINSERT INTO \"ItemGrouping\" (\"ID\",\"Color\",\"SpriteID\") VALUES ('Utility','255 255 255 255','Torch');\r\nINSERT INTO \"Hydraulics\" (\"ID\",\"Buildable\",\"Item\",\"Sprite\") VALUES ('Pipe',1,NULL,'Pipe');\r\nINSERT INTO \"Hydraulics\" (\"ID\",\"Buildable\",\"Item\",\"Sprite\") VALUES ('PipeExit',1,NULL,NULL);\r\nINSERT INTO \"Hydraulics\" (\"ID\",\"Buildable\",\"Item\",\"Sprite\") VALUES ('Pump',1,NULL,NULL);\r\nINSERT INTO \"HairColors\" (\"ID\",\"Color\") VALUES ('Green','0 255 0 255');\r\nINSERT INTO \"HairColors\" (\"ID\",\"Color\") VALUES ('Red','255 0 0 255');\r\nINSERT INTO \"HairColors\" (\"ID\",\"Color\") VALUES ('Blue','0 0 255 255');\r\nINSERT INTO \"HairColors\" (\"ID\",\"Color\") VALUES ('Cyan','0 255 255 255');\r\nINSERT INTO \"HairColors\" (\"ID\",\"Color\") VALUES ('Purple','255 0 255 255');\r\nINSERT INTO \"HairColors\" (\"ID\",\"Color\") VALUES ('Yellow','255 255 0 255');\r\nINSERT INTO \"FormationPerks\" (\"ID\") VALUES ('EyesOpen');\r\nINSERT INTO \"FormationPerks\" (\"ID\") VALUES ('ShieldWall');\r\nINSERT INTO \"FormationPerks\" (\"ID\") VALUES ('MeleeOffense');\r\nINSERT INTO \"FormationPerks\" (\"ID\") VALUES ('FiringSquad');\r\nINSERT INTO \"FarmUtils\" (\"ID\",\"Buildable\",\"Item\") VALUES ('Shed',1,NULL);\r\nINSERT INTO \"FarmUtils\" (\"ID\",\"Buildable\",\"Item\") VALUES ('Trough',1,NULL);\r\nINSERT INTO \"FarmUtils\" (\"ID\",\"Buildable\",\"Item\") VALUES ('BeeHive',1,NULL);\r\nINSERT INTO \"Events_OnSuccess\" (\"ID\",\"Action\",\"CenterCamera\",\"Count\",\"Message\",\"Pause\",\"Title\") VALUES ('EventTrader','SpawnTraderGnome',0,'$Num','A trader has arrived!',0,'Trader!');\r\nINSERT INTO \"Events_OnSuccess\" (\"ID\",\"Action\",\"CenterCamera\",\"Count\",\"Message\",\"Pause\",\"Title\") VALUES ('EventMigration','SpawnGnome',1,'$Num',NULL,0,NULL);\r\nINSERT INTO \"Events_OnSuccess\" (\"ID\",\"Action\",\"CenterCamera\",\"Count\",\"Message\",\"Pause\",\"Title\") VALUES ('EventInvasion','SpawnGoblin',1,'$Num','A force of $Num goblin has arrived.',0,'Invasion');\r\nINSERT INTO \"Events_OnFailure\" (\"ID\",\"Message\",\"Title\") VALUES ('EventMigration','Unfortunately those gnomes didn''t find an entry to your base.','Gnomes got lost.');\r\nINSERT INTO \"Events_OnFailure\" (\"ID\",\"Message\",\"Title\") VALUES ('EventInvasion','Luckily for you those goblins didn''t find a way to your base.','Goblins got lost.');\r\nINSERT INTO \"Events_Init\" (\"ID\",\"Title\",\"Message\",\"Min\",\"Max\",\"Pause\",\"Require\",\"Location\") VALUES ('EventTrader','none','none',1.0,1.0,1,'FreeMarketStall','RandomBorderTile');\r\nINSERT INTO \"Events_Init\" (\"ID\",\"Title\",\"Message\",\"Min\",\"Max\",\"Pause\",\"Require\",\"Location\") VALUES ('EventMigration','New Gnomes','$Num new gnomes have arrived. Do you accept them into your base?',1.0,5.0,1,'Query','RandomBorderTile');\r\nINSERT INTO \"Events_Init\" (\"ID\",\"Title\",\"Message\",\"Min\",\"Max\",\"Pause\",\"Require\",\"Location\") VALUES ('EventInvasion','none','none',1.0,5.0,0,'None','RandomBorderTile');\r\nINSERT INTO \"Events_Expires\" (\"ID\",\"After\",\"Unit\",\"Title\",\"Message\") VALUES ('EventMigration',1.0,'Day','You waited too long','Unfortunately your decision took too long and they are looking elsewhere.');\r\nINSERT INTO \"Events\" (\"ID\",\"Trigger_\",\"TriggerCount\",\"TriggerUnit\",\"NotBeforeDay\",\"NotInPeaceful\") VALUES ('EventTrader','Kingdom',0.0,'none',0,'false');\r\nINSERT INTO \"Events\" (\"ID\",\"Trigger_\",\"TriggerCount\",\"TriggerUnit\",\"NotBeforeDay\",\"NotInPeaceful\") VALUES ('EventMigration','OnSeasonChange',0.0,'none',0,'false');\r\nINSERT INTO \"Events\" (\"ID\",\"Trigger_\",\"TriggerCount\",\"TriggerUnit\",\"NotBeforeDay\",\"NotInPeaceful\") VALUES ('EventInvasion','Kingdom',0.0,'none',60,'true');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Coal',-6.0,-1000.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Tin',-7.0,-25.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Copper',-15.0,-30.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Malachite',-30.0,-50.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Lead',-20.0,-40.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Iron',-40.0,-80.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Silver',-50.0,-80.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Gold',-75.0,-95.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Platinum',-90.0,-100.0,'Ore','EmbeddedOre');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('FlintStone',-3.0,-6.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Amber',-3.0,-15.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Beryll',-10.0,-40.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Topaz',-15.0,-60.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Amethyst',-30.0,-80.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Ruby',-30.0,-80.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Sapphire',-30.0,-80.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Emerald',-20.0,-70.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"EmbeddedMaterials\" (\"ID\",\"Highest\",\"Lowest\",\"Type\",\"WallSprite\") VALUES ('Diamond',-50.0,-1000.0,'Gem','EmbeddedGem');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','LeftArm','GoblinArmLeft',1,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','Torso','GoblinTorso',2,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','RightArm','GoblinArmRight',4,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','Head','GoblinHead',5,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','Feet','GoblinFootLeft',6,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','Hair','#GoblinHair1|GoblinHair2|GoblinHair3|GoblinHair4',7,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','Facial','#GoblinBeard1|GoblinBeard2|GoblinBeard3|GoblinBeard4|GoblinBeard5',8,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Goblin','Clothing','#GoblinClothing1|GoblinClothing2|GoblinClothing3|GoblinClothing4|GoblinClothing5',3,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','Head','GoblinHead',1,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','Torso','GoblinTorso',2,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','LeftArm','GoblinArmLeft',4,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','RightArm','GoblinArmRight',5,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','Feet','GoblinFootLeft',6,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','Hair','#GoblinHair1|GoblinHair2|GoblinHair3|GoblinHair4|GoblinHair5',7,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GoblinBack','Clothing','#GoblinClothing1|GoblinClothing2|GoblinClothing3|GoblinClothing4|GoblinClothing5',3,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','RightArm','GnomeArmRight',6,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','RightArmArmor',NULL,7,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','RightHandArmor',NULL,8,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','Torso','GnomeTorso',4,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','Clothing','Shirt',5,'ShirtColor',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','ChestArmor',NULL,9,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','LeftArm','GnomeArmLeft',1,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','LeftArmArmor',NULL,2,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','LeftHandArmor',NULL,3,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','LeftFootArmor',NULL,'B','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','RightFootArmor',NULL,'C','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','Boots','GnomeBoots','A',NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','Head','GnomeHead','D',NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','Facial','FacialHair','E','HairColor',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','Hair','Hair','G','HairColor',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','HeadArmor',NULL,'F','Material','Hair');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','RightHandHeld',NULL,'H','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Gnome','LeftHandHeld',NULL,'I','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','RightArm','GnomeArmRightBack','A',NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','RightArmArmor',NULL,'B','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','RightHandArmor',NULL,'C','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','Torso','GnomeTorsoBack',8,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','Clothing','Shirt',9,'$ShirtColor',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','ChestArmor',NULL,'D','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','LeftArm','GnomeArmLeftBack',2,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','LeftArmArmor',NULL,3,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','LeftHandArmor',NULL,4,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','LeftFootArmor',NULL,6,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','RightFootArmor',NULL,7,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','Boots','GnomeBootsBack',5,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','Head','GnomeHeadBack',1,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','Hair','Hair','F','HairColor',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','HeadArmor',NULL,'E','Material','Hair');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','RightHandHeld',NULL,'G','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','LeftHandHeld',NULL,'H','Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorker','Torso','MantWorkerBodyFR',1,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorker','Head','MantWorkerHeadFR',2,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorker','LeftArm','MantWorkerArmLeftFR',3,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorker','RightArm','MantWorkerArmRightFR',4,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorker','LeftLeg','MantWorkerLegLeftFR',5,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorker','RightLeg','MantWorkerLegRightFR',6,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorkerBack','Torso','MantWorkerBodyBR',4,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorkerBack','Head','MantWorkerHeadBR',5,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorkerBack','LeftArm','MantWorkerArmLeftBR',3,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorkerBack','RightArm','MantWorkerArmRightBR',6,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorkerBack','LeftLeg','MantWorkerLegLeftBR',1,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantWorkerBack','RightLeg','MantWorkerLegRightBR',2,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldier','Torso','MantSoldierBodyFR',3,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldier','Head','MantSoldierHeadFR',5,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldier','LeftArm','MantSoldierArmLeftFR',1,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldier','RightArm','MantSoldierArmRightFR',4,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldier','LeftLeg','MantSoldierLegLeftFR',6,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldier','RightLeg','MantSoldierLegRightFR',2,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldierBack','Torso','MantSoldierBodyBR',4,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldierBack','Head','MantSoldierHeadBR',6,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldierBack','LeftArm','MantSoldierArmLeftBR',5,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldierBack','RightArm','MantSoldierArmRightBR',3,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldierBack','LeftLeg','MantSoldierLegLeftBR',1,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantSoldierBack','RightLeg','MantSoldierLegRightBR',2,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueen','Torso','MantQueenBodyFR',3,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueen','Head','MantQueenHeadFR',5,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueen','LeftArm','MantQueenArmLeftFR',1,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueen','RightArm','MantQueenArmRightFR',4,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueen','LeftLeg','MantQueenLegLeftFR',6,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueen','RightLeg','MantQueenLegRightFR',2,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueenBack','Torso','MantQueenBodyBR',4,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueenBack','Head','MantQueenHeadBR',6,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueenBack','LeftArm','MantQueenArmLeftBR',5,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueenBack','RightArm','MantQueenArmRightBR',3,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueenBack','LeftLeg','MantQueenLegLeftBR',1,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('MantQueenBack','RightLeg','MantQueenLegRightBR',2,'','');\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','ArmLeft','AutomatonLeftArmFR',1,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','Torso','AutomatonTorsoFR',2,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','ArmRight','AutomatonRightArmFR',3,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','Head','AutomatonHeadFR',4,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','LegLeft','AutomatonLeftFootFR',5,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','LegRight','AutomatonRightFootFR',6,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','Head','AutomatonHeadBR',1,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','ArmLeft','AutomatonLeftArmBR',4,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','Torso','AutomatonTorsoBR',5,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','ArmRight','AutomatonRightArmBR',6,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','LegLeft','AutomatonLeftFootBR',2,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','LegRight','AutomatonRightFootBR',3,'Material',NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('AutomatonBack','Flame','AutomatonFurnaceFlameBR',7,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('Automaton','Eye','AutomatonEyeFR',7,NULL,NULL);\r\nINSERT INTO \"Creature_Parts\" (\"ID\",\"Part\",\"BaseSprite\",\"Order\",\"Tint\",\"Conceales\") VALUES ('GnomeBack','Back',NULL,'I',NULL,NULL);\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 0 0','Mammoth000');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 1 0','Mammoth010');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 2 0','Mammoth020');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 0 0','Mammoth100');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 1 0','Mammoth110');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 2 0','Mammoth120');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 0 1','Mammoth001');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 1 1','Mammoth011');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 2 1','Mammoth021');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 0 1','Mammoth101');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 1 1','Mammoth111');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 2 1','Mammoth121');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 0 2','Mammoth002');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 1 2','Mammoth012');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','0 2 2','Mammoth022');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 0 2','Mammoth102');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 1 2','Mammoth112');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFL','1 2 2','Mammoth122');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothFL','0 0 0','Sabretooth1FL');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothFL','0 -1 0','Sabretooth2FL');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothFR','0 0 0','Sabretooth1FR');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothFR','-1 0 0','Sabretooth2FR');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothBR','0 0 0','Sabretooth1BR');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothBR','0 1 0','Sabretooth2BR');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothBL','0 0 0','Sabretooth1BL');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('SabretoothBL','1 0 0','Sabretooth2BL');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 0 0','Mammoth000');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 1 0','Mammoth010');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 2 0','Mammoth020');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 0 0','Mammoth100');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 1 0','Mammoth110');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 2 0','Mammoth120');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 0 1','Mammoth001');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 1 1','Mammoth011');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 2 1','Mammoth021');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 0 1','Mammoth101');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 1 1','Mammoth111');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 2 1','Mammoth121');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 0 2','Mammoth002');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 1 2','Mammoth012');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','0 2 2','Mammoth022');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 0 2','Mammoth102');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 1 2','Mammoth112');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothFR','1 2 2','Mammoth122');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 0 0','Mammoth000');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 1 0','Mammoth010');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 2 0','Mammoth020');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 0 0','Mammoth100');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 1 0','Mammoth110');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 2 0','Mammoth120');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 0 1','Mammoth001');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 1 1','Mammoth011');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 2 1','Mammoth021');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 0 1','Mammoth101');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 1 1','Mammoth111');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 2 1','Mammoth121');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 0 2','Mammoth002');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 1 2','Mammoth012');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','0 2 2','Mammoth022');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 0 2','Mammoth102');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 1 2','Mammoth112');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBL','1 2 2','Mammoth122');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 0 0','Mammoth000');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 1 0','Mammoth010');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 2 0','Mammoth020');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 0 0','Mammoth100');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 1 0','Mammoth110');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 2 0','Mammoth120');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 0 1','Mammoth001');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 1 1','Mammoth011');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 2 1','Mammoth021');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 0 1','Mammoth101');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 1 1','Mammoth111');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 2 1','Mammoth121');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 0 2','Mammoth002');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 1 2','Mammoth012');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','0 2 2','Mammoth022');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 0 2','Mammoth102');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 1 2','Mammoth112');\r\nINSERT INTO \"Creature_Layouts\" (\"ID\",\"Offset\",\"Sprite\") VALUES ('MammothBR','1 2 2','Mammoth122');\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Plank','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Stick','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Haft','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Hilt','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Knife','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneChair','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WoodTable','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WoodChair','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneTable','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Workbench','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Crate','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Barrel','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Chisel','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneSawblade','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('KnifeBlade','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Block','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bread','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Beer','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Wine','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('FruitWine','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HoneyWine','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bar','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BronzeBar','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('SteelBar','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('RoseGoldBar','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Anvil','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('SliverBar','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Gem','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bolt','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('RawCoal','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Brick','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Tile','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ClayStatuette','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Tea','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneDoor','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Hearth','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Mold','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Furnace','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Trough','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneSword','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneHandAxe','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneHammer','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneCrossbowBolt','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneMusketRound','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneStatue','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StonePillar','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('StoneStatuette','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PetRock','TechStone',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BedFrame','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('FancyBedFrame','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bed','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('FancyBed','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WoodDoor','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Dresser','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Cabinet','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Torch','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Loom','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bellows','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('TrainingDummy','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Wheelbarrow','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bucket','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WoodenShield','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('CrossbowStock','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BlunderbussStock','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PistolStock','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WoodStatue','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WoodStatuette','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PuzzleBox','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('FellingAxeHead','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('FellingAxe','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('CuttingWheel','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('File','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BallPeenHammer','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('AlarmBell','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MetalStatue','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MetalStatuette','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Coin','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Wrench','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Rod','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Gear','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Spring','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Spike','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MetalCrossbowBolt','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('CrossbowBow','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MetalMusketRound','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BlunderbussBarrel','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PistolBarrel','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Screw','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Ring','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('GemmedRing','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Necklace','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('GemmedNecklace','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bag','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Sack','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Bandage','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('String','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Padding','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Mattress','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('AmmoPouch','TechCloth',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherStrap','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherArmorPanel','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherHelm','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherCuirass','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherBracer','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherGreave','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherGlove','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('LeatherBoot','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Quiver','TechLeather',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Sausage','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Sandwich','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Cheese','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('CheeseOmelette','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('SausageOmelette','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MushroomOmelette','TechFood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('SwordBlade','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Sword','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HandAxeHead','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HandAxe','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HammerHead','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Hammer','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ClaymoreBlade','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Claymore','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BattleAxeHead','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BattleAxe','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WarhammerHead','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Warhammer','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ShieldBoss','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ShieldBacking','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Shield','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('TowerShieldBacking','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('TowerShield','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ArmorPlate','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Helmet','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Breastplate','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Pauldron','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Greave','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Gauntlet','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Boot','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Axle','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MechanismBase','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Gearbox','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Handcrank','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('TrapBase','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('SpikeTrap','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BladeTrap','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Crossbow','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Lever','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MechanicalWall','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('WindmillBlade','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PressurePlate','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Hatch','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Blunderbuss','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Pistol','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Cylinder','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ArtificialArm','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ArtificialHand','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ArtificialLeg','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ArtificialFoot','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Automaton','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('MetalNeedle','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BoneStatuette','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('SkullHelmet','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BoneShirt','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ChainBoots','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ChainPants','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ChainGloves','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ChainBracers','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ChainShirt','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('ChainHelm','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PlateBoots','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PlatePauldrons','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PlateGloves','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PlateHelm','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PlateGreaves','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('PlateChest','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HeavyPlateBoots','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HeavyPlateChest','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HeavyPlateGloves','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HeavyPlateGreaves','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HeavyPlateHelm','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('HeavyPlatePauldrons','TechMetal',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('BeeHive','TechWood',1.0);\r\nINSERT INTO \"Crafts_TechGain\" (\"ID\",\"TechID\",\"Value\") VALUES ('Chest','TechCloth',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Plank',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Stick',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Haft',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Hilt',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Knife',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneChair',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WoodTable',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WoodChair',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneTable',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Workbench',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Crate',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Barrel',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Chisel',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneSawblade',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('KnifeBlade',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Block',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bread',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Beer',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Wine',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('FruitWine',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HoneyWine',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bar',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BronzeBar',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('SteelBar',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('RoseGoldBar',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Anvil',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('SliverBar',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Gem',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bolt',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('RawCoal',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Brick',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Tile',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ClayStatuette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Tea',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneDoor',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Hearth',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Mold',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Furnace',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneSword',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneHandAxe',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneHammer',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneCrossbowBolt',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneMusketRound',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneStatue',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StonePillar',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('StoneStatuette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PetRock',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BedFrame',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('FancyBedFrame',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bed',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('FancyBed',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WoodDoor',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Dresser',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Cabinet',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Torch',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Loom',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bellows',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('TrainingDummy',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Wheelbarrow',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bucket',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WoodenShield',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('CrossbowStock',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BlunderbussStock',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PistolStock',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WoodStatue',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WoodStatuette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PuzzleBox',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('FellingAxeHead',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('FellingAxe',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('CuttingWheel',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('File',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BallPeenHammer',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('AlarmBell',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MetalStatue',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MetalStatuette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Coin',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Wrench',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Rod',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Gear',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Spring',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Spike',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MetalCrossbowBolt',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('CrossbowBow',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MetalMusketRound',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BlunderbussBarrel',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PistolBarrel',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Screw',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Ring',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('GemmedRing',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Necklace',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('GemmedNecklace',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bag',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Sack',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Bandage',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('String',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Padding',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Mattress',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('AmmoPouch',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherStrap',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherArmorPanel',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherHelm',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherCuirass',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherBracer',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherGreave',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherGlove',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('LeatherBoot',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Quiver',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Sausage',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Sandwich',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Cheese',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('CheeseOmelette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('SausageOmelette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MushroomOmelette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('SwordBlade',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Sword',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HandAxeHead',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HandAxe',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HammerHead',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Hammer',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ClaymoreBlade',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Claymore',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BattleAxeHead',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BattleAxe',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WarhammerHead',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Warhammer',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ShieldBoss',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ShieldBacking',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Shield',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('TowerShieldBacking',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('TowerShield',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ArmorPlate',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Helmet',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Breastplate',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Pauldron',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Greave',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Gauntlet',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Boot',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Axle',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MechanismBase',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Gearbox',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Handcrank',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('TrapBase',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('SpikeTrap',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BladeTrap',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Crossbow',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Lever',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MechanicalWall',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('WindmillBlade',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PressurePlate',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Hatch',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Blunderbuss',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Pistol',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Cylinder',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ArtificialArm',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ArtificialHand',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ArtificialLeg',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ArtificialFoot',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Automaton',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Needle',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('MetalNeedle',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BoneStatuette',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('SkullHelmet',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BoneShirt',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ChainBoots',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ChainPants',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ChainGloves',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ChainBracers',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ChainShirt',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('ChainHelm',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PlateBoots',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PlatePauldrons',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PlateGloves',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PlateHelm',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PlateGreaves',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('PlateChest',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HeavyPlateBoots',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HeavyPlateChest',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HeavyPlateGloves',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HeavyPlateGreaves',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HeavyPlateHelm',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('HeavyPlatePauldrons',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('BeeHive',1.0);\r\nINSERT INTO \"Crafts_SkillGain\" (\"ID\",\"Value\") VALUES ('Chest',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Crate','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Barrel','tech','TechWood',10.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bar','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BronzeBar','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('SteelBar','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('RoseGoldBar','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Anvil','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('SliverBar','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Gem','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bolt','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('RawCoal','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Brick','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Tile','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ClayStatuette','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Tea','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneDoor','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Hearth','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Mold','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Furnace','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Trough','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneSword','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneHandAxe','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneHammer','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneCrossbowBolt','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneMusketRound','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneStatue','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StonePillar','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('StoneStatuette','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PetRock','tech','TechStone',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BedFrame','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('FancyBedFrame','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bed','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('FancyBed','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('WoodDoor','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Dresser','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Cabinet','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Torch','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Loom','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bellows','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('TrainingDummy','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Wheelbarrow','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bucket','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('WoodenShield','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('CrossbowStock','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BlunderbussStock','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PistolStock','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('WoodStatue','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('WoodStatuette','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PuzzleBox','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('FellingAxeHead','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('FellingAxe','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('CuttingWheel','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('File','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BallPeenHammer','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('AlarmBell','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MetalStatue','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MetalStatuette','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Coin','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Wrench','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Rod','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Gear','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Spring','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Spike','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MetalCrossbowBolt','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('CrossbowBow','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MetalMusketRound','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BlunderbussBarrel','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PistolBarrel','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Screw','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Ring','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('GemmedRing','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Necklace','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('GemmedNecklace','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bag','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Sack','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Bandage','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('String','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Padding','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Mattress','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('AmmoPouch','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherStrap','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherArmorPanel','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherHelm','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherCuirass','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherBracer','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherGreave','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherGlove','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('LeatherBoot','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Quiver','tech','TechLeather',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Sausage','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Sandwich','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Cheese','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('CheeseOmelette','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('SausageOmelette','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MushroomOmelette','tech','TechFood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('SwordBlade','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Sword','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HandAxeHead','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HandAxe','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HammerHead','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Hammer','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ClaymoreBlade','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Claymore','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BattleAxeHead','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BattleAxe','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('WarhammerHead','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Warhammer','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ShieldBoss','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ShieldBacking','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Shield','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('TowerShieldBacking','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('TowerShield','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ArmorPlate','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Helmet','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Breastplate','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Pauldron','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Greave','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Gauntlet','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Boot','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Axle','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MechanismBase','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Gearbox','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Handcrank','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('TrapBase','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('SpikeTrap','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BladeTrap','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Crossbow','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Lever','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MechanicalWall','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('WindmillBlade','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PressurePlate','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Hatch','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Blunderbuss','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Pistol','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Cylinder','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ArtificialArm','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ArtificialHand','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ArtificialLeg','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ArtificialFoot','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Automaton','tech','TechEngineer',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Needle','tech','TechCloth',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('MetalNeedle','tech','TechMetal',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BoneStatuette','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('SkullHelmet','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BoneShirt','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PickaxeHeadFlintStone','tech','TechWood',1.0);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ChainBoots',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ChainPants',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ChainGloves',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ChainBracers',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ChainShirt',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('ChainHelm',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PlateBoots',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PlatePauldrons',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PlateGloves',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PlateHelm',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PlateGreaves',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('PlateChest',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HeavyPlateBoots',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HeavyPlateChest',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HeavyPlateGloves',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HeavyPlateGreaves',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HeavyPlateHelm',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('HeavyPlatePauldrons',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('BeeHive',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Prereqs\" (\"ID\",\"Category\",\"TechGroup\",\"Value\") VALUES ('Chest',NULL,NULL,NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Cider','Apple',NULL,1,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Vinegar',NULL,NULL,1,'Wine',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sugar','Sugarbeet',NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DropCandy',NULL,NULL,2,'Sugar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DropCandy',NULL,NULL,1,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ShepherdsPie',NULL,NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ShepherdsPie',NULL,NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ShepherdsPie','Potato',NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ShepherdsPie',NULL,NULL,1,'Meat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Biscuit',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Biscuit',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledFruit',NULL,NULL,1,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledFruit',NULL,NULL,1,'Sugar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledFruit',NULL,NULL,1,'GlassJar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitPreserve',NULL,NULL,2,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedMeat',NULL,NULL,1,'Meat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedMeat',NULL,'Wood',1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedSausage',NULL,NULL,1,'Sausage',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedSausage',NULL,'Wood',1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitBread',NULL,NULL,1,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitBread',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FreshCheese',NULL,NULL,2,'Milk',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HardCheese',NULL,NULL,2,'Milk',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MeatPie',NULL,NULL,1,'Meat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MeatPie',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MeatPie',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledVegetable',NULL,NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledVegetable',NULL,NULL,1,'Vinegar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledVegetable',NULL,NULL,1,'GlassJar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledEgg',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledEgg',NULL,NULL,1,'Vinegar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickledEgg',NULL,NULL,1,'GlassJar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('VegetablePreserve',NULL,NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedBird','Chicken|Duck|Emu',NULL,1,'Meat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedBird',NULL,'Wood',1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedFish',NULL,NULL,1,'FishMeat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SmokedFish',NULL,'Wood',1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FlatBread',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitPie',NULL,NULL,1,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitPie',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitPie',NULL,NULL,1,'Sugar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitPie',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('VeggiePie',NULL,NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('VeggiePie',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('VeggiePie',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FineMeatPie',NULL,NULL,3,'Meat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FineMeatPie',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FineMeatPie',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Plank',NULL,NULL,1,'RawWood',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Stick',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Haft',NULL,NULL,1,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Hilt',NULL,NULL,1,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Knife',NULL,NULL,1,'KnifeBlade',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Knife',NULL,NULL,1,'Hilt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneChair',NULL,NULL,4,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodTable',NULL,NULL,2,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodTable',NULL,NULL,4,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodChair',NULL,NULL,2,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodChair',NULL,NULL,4,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneTable',NULL,NULL,5,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Workbench',NULL,NULL,6,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Crate',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Barrel',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Chisel',NULL,NULL,2,'RawStone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneSawblade',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('KnifeBlade',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Block',NULL,NULL,1,'RawStone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bread',NULL,NULL,1,'Flour',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Beer',NULL,NULL,1,'Grain',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Wine',NULL,NULL,1,'Berries',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FruitWine',NULL,NULL,1,'Fruit',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HoneyWine',NULL,NULL,1,'Honey',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyedTable',NULL,'Wood',1,'Table',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyedTable',NULL,NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyedPlank',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyedPlank',NULL,NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RedDye','BeetRoot',NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RedDye','BeetRoot',NULL,1,'Vegetable',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GreenDye','Woad',NULL,1,'Leaves',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GreenDye','DyersWeed',NULL,1,'Leaves',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BlueDye','Woad',NULL,1,'Leaves',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BlueDye','Woad',NULL,1,'Leaves',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('YellowDye','DyersWeed',NULL,1,'Leaves',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('YellowDye','DyersWeed',NULL,1,'Leaves',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PurpleDye','Red',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PurpleDye','Blue',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CyanDye','Green',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CyanDye','Blue',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyeHair',NULL,NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bar',NULL,NULL,2,'RawOre','true');\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bar',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BronzeBar','Tin',NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BronzeBar','Copper',NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BronzeBar',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SteelBar','Iron',NULL,2,'Bar','true');\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SteelBar',NULL,NULL,2,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RoseGoldBar','Gold',NULL,3,'Bar','true');\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RoseGoldBar','Copper',NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RoseGoldBar',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Anvil',NULL,NULL,8,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SliverBar',NULL,NULL,10,'Sliver',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SliverBar',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Gem',NULL,NULL,1,'RawGem',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bolt',NULL,NULL,1,'RawCloth',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RawCoal',NULL,NULL,1,'RawWood',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Brick','Clay|Sand',NULL,1,'RawSoil',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Brick',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ClayStatuette','Clay',NULL,1,'RawSoil',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Tea',NULL,NULL,1,'Mushroom',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneDoor',NULL,NULL,4,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Hearth',NULL,NULL,6,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Mold',NULL,NULL,4,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Furnace',NULL,NULL,10,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Trough',NULL,NULL,4,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneSword',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneSword',NULL,NULL,1,'Hilt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneHandAxe',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneHandAxe',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneHammer',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneHammer',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneCrossbowBolt',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneMusketRound',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneStatue',NULL,NULL,4,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StonePillar',NULL,NULL,4,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('StoneStatuette',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PetRock',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BedFrame',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FancyBedFrame',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bed',NULL,NULL,1,'WoodBedFrame',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bed',NULL,NULL,1,'Mattress',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FancyBed',NULL,NULL,1,'FancyBedFrame',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FancyBed',NULL,NULL,1,'Mattress',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodDoor',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Dresser',NULL,NULL,6,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Cabinet',NULL,NULL,6,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Torch',NULL,NULL,1,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Torch',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Loom',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Loom',NULL,NULL,4,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bellows',NULL,NULL,2,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TrainingDummy',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TrainingDummy',NULL,NULL,2,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Wheelbarrow',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Wheelbarrow',NULL,NULL,2,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bucket',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodenShield',NULL,NULL,3,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CrossbowStock',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BlunderbussStock',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PistolStock',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodStatue',NULL,NULL,4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WoodStatuette',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PuzzleBox',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FellingAxeHead',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FellingAxe',NULL,NULL,1,'FellingAxeHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FellingAxe',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CuttingWheel',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('File',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BallPeenHammer',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AlarmBell',NULL,NULL,1,'AlarmBellBell',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AlarmBell',NULL,NULL,1,'AlarmBellBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MetalStatue',NULL,NULL,4,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MetalStatuette',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Coin',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Wrench',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Rod',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Gear',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Spring',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Spike',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MetalCrossbowBolt',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CrossbowBow',NULL,NULL,3,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MetalMusketRound',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BlunderbussBarrel',NULL,NULL,5,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PistolBarrel',NULL,NULL,3,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Screw',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Ring',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GemmedRing',NULL,NULL,1,'Gem',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GemmedRing',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Necklace',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GemmedNecklace',NULL,NULL,1,'Gem',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GemmedNecklace',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bag',NULL,NULL,2,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bag',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sack',NULL,NULL,2,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sack',NULL,NULL,2,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bandage',NULL,NULL,1,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('String',NULL,NULL,1,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Padding',NULL,NULL,1,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Padding',NULL,NULL,1,'RawCloth',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Padding',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Mattress',NULL,NULL,4,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Mattress',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Mattress',NULL,NULL,2,'Straw',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AmmoPouch',NULL,NULL,1,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AmmoPouch',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherStrap',NULL,NULL,1,'RawHide',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherArmorPanel',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherHelm',NULL,NULL,3,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherHelm',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherHelm',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherCuirass',NULL,NULL,4,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherCuirass',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherCuirass',NULL,NULL,2,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherBracer',NULL,NULL,2,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherBracer',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherBracer',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherPants',NULL,NULL,2,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherPants',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherPants',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherGlove',NULL,NULL,1,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherGlove',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherGlove',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherBoot',NULL,NULL,1,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherBoot',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('LeatherBoot',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Quiver',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Quiver',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sausage',NULL,NULL,1,'Meat',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sandwich',NULL,NULL,1,'Sausage',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sandwich',NULL,NULL,1,'Bread',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Cheese',NULL,NULL,1,'Milk',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CheeseOmelette',NULL,NULL,1,'Cheese',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('CheeseOmelette',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SausageOmelette',NULL,NULL,1,'Sausage',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SausageOmelette',NULL,NULL,1,'Cheese',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SausageOmelette',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MushroomOmelette',NULL,NULL,1,'Mushroom',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MushroomOmelette',NULL,NULL,1,'Cheese',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MushroomOmelette',NULL,NULL,1,'Egg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SwordBlade',NULL,NULL,5,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sword',NULL,NULL,1,'SwordBlade',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Sword',NULL,NULL,1,'Hilt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HandAxeHead',NULL,NULL,5,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HandAxe',NULL,NULL,1,'HandAxeHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HandAxe',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HammerHead',NULL,NULL,5,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Hammer',NULL,NULL,1,'HammerHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Hammer',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ClaymoreBlade',NULL,NULL,8,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Claymore',NULL,NULL,1,'ClaymoreBlade',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Claymore',NULL,NULL,1,'Hilt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BattleAxeHead',NULL,NULL,8,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BattleAxe',NULL,NULL,1,'BattleAxeHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BattleAxe',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WarhammerHead',NULL,NULL,8,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Warhammer',NULL,NULL,1,'WarhammerHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Warhammer',NULL,NULL,1,'Haft',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ShieldBoss',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ShieldBacking',NULL,NULL,3,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Shield',NULL,NULL,1,'ShieldBoss',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Shield',NULL,NULL,1,'ShieldBacking',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TowerShieldBacking',NULL,NULL,6,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TowerShield',NULL,NULL,1,'ShieldBoss',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TowerShield',NULL,NULL,1,'TowerShieldBacking',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Helmet',NULL,NULL,3,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Helmet',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Helmet',NULL,NULL,1,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Breastplate',NULL,NULL,4,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Breastplate',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Breastplate',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pauldron',NULL,NULL,2,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pauldron',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pauldron',NULL,NULL,1,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Greave',NULL,NULL,2,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Greave',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Greave',NULL,NULL,1,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Gauntlet',NULL,NULL,1,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Gauntlet',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Boot',NULL,NULL,1,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Boot',NULL,NULL,1,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Axle',NULL,NULL,1,'Rod',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MechanismBase',NULL,NULL,2,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MechanismBase',NULL,NULL,1,'Spring',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Gearbox',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Gearbox',NULL,NULL,4,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Handcrank',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Handcrank',NULL,NULL,1,'Rod',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TrapBase',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('TrapBase',NULL,NULL,1,'Spring',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SpikeTrap',NULL,NULL,1,'TrapBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SpikeTrap',NULL,NULL,3,'Spike',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BladeTrap',NULL,NULL,1,'TrapBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BladeTrap',NULL,NULL,1,'SwordBlade',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Crossbow',NULL,NULL,1,'CrossbowBow',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Crossbow',NULL,NULL,1,'CrossbowStock',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Crossbow',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Lever',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Lever',NULL,NULL,1,'Rod',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MechanicalWall',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MechanicalWall',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WindmillBlade',NULL,NULL,1,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('WindmillBlade',NULL,NULL,1,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PressurePlate',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PressurePlate',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Hatch',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Hatch',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Blunderbuss',NULL,NULL,1,'BlunderbussBarrel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Blunderbuss',NULL,NULL,1,'BlunderbussStock',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pistol',NULL,NULL,1,'PistolBarrel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pistol',NULL,NULL,1,'PistolStock',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Cylinder',NULL,NULL,4,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialArm',NULL,NULL,2,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialArm',NULL,NULL,1,'Rod',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialArm',NULL,NULL,1,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialArm',NULL,NULL,1,'ArtificialHand',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialHand',NULL,NULL,1,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialHand',NULL,NULL,1,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialLeg',NULL,NULL,2,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialLeg',NULL,NULL,1,'Rod',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialLeg',NULL,NULL,1,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialLeg',NULL,NULL,1,'ArtificialFoot',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialFoot',NULL,NULL,1,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArtificialFoot',NULL,NULL,1,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Needle',NULL,NULL,1,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MetalNeedle',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneStatuette',NULL,NULL,1,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SkullHelmet',NULL,NULL,1,'Skull',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneShirt',NULL,NULL,4,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneShirt',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickaxeHeadWood',NULL,NULL,1,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickaxeHeadFlintStone','FlintStone',NULL,1,'Gem',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickaxeHeadStone',NULL,NULL,1,'Block',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickaxeBaseWood',NULL,NULL,1,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pickaxe',NULL,NULL,1,'PickaxeHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Pickaxe',NULL,NULL,1,'PickaxeBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FishingRod',NULL,NULL,1,'Stick',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FishingRod',NULL,NULL,1,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SliverFromStone',NULL,NULL,1,'RawStone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SliverFromDirt',NULL,NULL,10,'RawSoil',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainBoots',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainBoots',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainBracers',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainBracers',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainGloves',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainGloves',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainHelm',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainHelm',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainHelm',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainPants',NULL,NULL,3,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainPants',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainPants',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainShirt',NULL,NULL,4,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainShirt',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ChainShirt',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('ArmorPlate',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateBoots',NULL,NULL,8,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateBoots',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateChest',NULL,NULL,16,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateChest',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateChest',NULL,NULL,4,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateGloves',NULL,NULL,8,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateGloves',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateGreaves',NULL,NULL,12,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateGreaves',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateGreaves',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateHelm',NULL,NULL,8,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateHelm',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlateHelm',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlatePauldrons',NULL,NULL,8,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('HeavyPlatePauldrons',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateBoots',NULL,NULL,4,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateBoots',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateChest',NULL,NULL,8,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateChest',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateChest',NULL,NULL,4,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateGloves',NULL,NULL,4,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateGloves',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateGreaves',NULL,NULL,6,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateGreaves',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateGreaves',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateHelm',NULL,NULL,4,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateHelm',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlateHelm',NULL,NULL,2,'Padding',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlatePauldrons',NULL,NULL,4,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PlatePauldrons',NULL,NULL,2,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyedBolt',NULL,NULL,1,'Bolt',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('DyedBolt',NULL,NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('PickaxeHeadMetal',NULL,NULL,1,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SteamEngine',NULL,NULL,1,'MechanismBase',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SteamEngine',NULL,NULL,1,'Cylinder',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SteamEngine',NULL,NULL,1,'Rod',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('SteamEngine',NULL,NULL,1,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Automaton',NULL,NULL,1,'AutomatonTorso',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Automaton',NULL,NULL,1,'AutomatonHead',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Automaton',NULL,NULL,2,'AutomatonLeg',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Automaton',NULL,NULL,2,'AutomatonArm',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonHead',NULL,NULL,3,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonTorso',NULL,NULL,5,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonArm',NULL,NULL,3,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonLeg',NULL,NULL,4,'ArmorPlate',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Flour',NULL,NULL,1,'Grain',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('FlourKitchen',NULL,NULL,1,'Grain',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneTable',NULL,NULL,8,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneChair',NULL,NULL,5,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneBedFrame',NULL,NULL,6,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneBed',NULL,NULL,1,'BoneBedFrame',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BoneBed',NULL,NULL,1,'Mattress',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonCoreMark1',NULL,NULL,2,'Screw',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonCoreMark1',NULL,NULL,2,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonCoreMark1',NULL,NULL,2,'Spring',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonCoreMark2',NULL,NULL,4,'Screw',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonCoreMark2',NULL,NULL,4,'Gear',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AutomatonCoreMark2',NULL,NULL,4,'Spring',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Shed',NULL,NULL,6,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BurnFishBone',NULL,NULL,1,'FishBone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BurnBone',NULL,NULL,1,'Bone',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BurnStraw',NULL,NULL,1,'Straw',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BurnSeeds',NULL,NULL,5,'Seed',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AlarmBellBell',NULL,NULL,2,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('AlarmBellBase',NULL,NULL,2,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BeeHive','','',4,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Chest',NULL,NULL,3,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Bookshelf',NULL,NULL,6,'Plank',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BigTorch',NULL,NULL,3,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('BigTorch',NULL,NULL,2,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Brazier',NULL,NULL,4,'Bar',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Brazier',NULL,NULL,4,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Backpack',NULL,NULL,4,'LeatherStrap',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Backpack',NULL,NULL,1,'LeatherArmorPanel',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('Backpack',NULL,NULL,2,'String',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GlassIngot','Sand',NULL,1,'RawSoil',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GlassIngot',NULL,NULL,2,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RoughGlassGem','Sand',NULL,1,'RawSoil',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('RoughGlassGem',NULL,NULL,2,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MosaicTile',NULL,NULL,1,'GlassIngot',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MosaicTile','Red',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MosaicTile','Green',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('MosaicTile','Blue',NULL,1,'Dye',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GlassJar',NULL,NULL,1,'GlassIngot',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GlassJar',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GlassBottle',NULL,NULL,1,'GlassIngot',NULL);\r\nINSERT INTO \"Crafts_Components\" (\"ID\",\"AllowedMaterial\",\"AllowedMaterialType\",\"Amount\",\"ItemID\",\"RequireSame\") VALUES ('GlassBottle',NULL,NULL,1,'RawCoal',NULL);\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Plank',1,NULL,'Plank',10.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Stick',1,NULL,'Stick',10.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Haft',1,NULL,'Haft',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Hilt',1,NULL,'Hilt',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Knife',1,NULL,'Knife',50.0,NULL,'Stone|Metal','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneChair',1,NULL,'Chair',50.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WoodTable',1,NULL,'Table',60.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WoodChair',1,NULL,'Chair',60.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneTable',1,NULL,'Table',60.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Workbench',1,NULL,'Workbench',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Crate',1,NULL,'Crate',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Barrel',1,NULL,'Barrel',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Chisel',1,NULL,'Chisel',50.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneSawblade',1,NULL,'Sawblade',50.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('KnifeBlade',1,NULL,'KnifeBlade',50.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Block',1,NULL,'Block',10.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bread',1,NULL,'Bread',20.0,NULL,'Grain','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Beer',1,NULL,'Beer',20.0,NULL,'Grain','Brewing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Wine',1,NULL,'Wine',20.0,NULL,'Berries','Brewing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HoneyWine',1,NULL,'Wine',20.0,NULL,'Honey','Brewing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FruitWine',1,NULL,'Wine',20.0,NULL,'Fruit','Brewing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('DyedTable',1,'$Dye','Table',20.0,NULL,'Wood','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('DyedPlank',1,'$Dye','Plank',20.0,NULL,'Wood','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('RedDye',1,'Red','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('GreenDye',1,'Green','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BlueDye',1,'Blue','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('YellowDye',1,'Yellow','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PurpleDye',1,'Purple','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('CyanDye',1,'Cyan','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('DyeHair',1,'$GnomeHair','Dye',20.0,NULL,'Dye','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bar',1,NULL,'Bar',30.0,NULL,'Metal','Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BronzeBar',2,'Bronze','Bar',30.0,'Bronze',NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SteelBar',1,'Steel','Bar',30.0,'Steel',NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('RoseGoldBar',4,'RoseGold','Bar',30.0,'RoseGold',NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Anvil',1,NULL,'Anvil',30.0,NULL,'Metal','Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SliverBar',1,NULL,'Bar',30.0,NULL,'Metal','Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Gem',1,NULL,'Gem',30.0,NULL,'Gem','Gemcutting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bolt',1,NULL,'Bolt',30.0,NULL,'Cloth','Weaving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('RawCoal',1,'Coal','RawCoal',30.0,NULL,'Coal','Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Brick',1,NULL,'Brick',30.0,NULL,NULL,'Pottery');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ClayStatuette',1,'Clay','Statuette',30.0,NULL,'Clay','Pottery');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Tea',1,NULL,'Tea',30.0,NULL,'Plant','Brewing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneDoor',1,NULL,'Door',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Hearth',1,NULL,'Hearth',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Mold',1,NULL,'Mold',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Furnace',1,NULL,'Furnace',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Trough',1,NULL,'Trough',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneSword',1,NULL,'StoneSword',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneHandAxe',1,NULL,'StoneHandAxe',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneHammer',1,NULL,'StoneHammer',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneCrossbowBolt',16,NULL,'CrossbowBolt',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneMusketRound',32,NULL,'MusketRound',30.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneStatue',1,NULL,'Statue',30.0,NULL,'Stone','Stonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StonePillar',1,NULL,'Pillar',30.0,NULL,'Stone','Stonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('StoneStatuette',1,NULL,'Statuette',30.0,NULL,'Stone','Stonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PetRock',1,NULL,'PetRock',30.0,NULL,'Stone','Stonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BedFrame',1,NULL,'WoodBedFrame',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FancyBedFrame',1,NULL,'FancyBedFrame',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bed',1,NULL,'Bed',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FancyBed',1,NULL,'FancyBed',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WoodDoor',1,NULL,'Door',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Dresser',1,NULL,'Dresser',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Cabinet',1,NULL,'Cabinet',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Torch',1,NULL,'Torch',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Loom',1,NULL,'Loom',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bellows',1,NULL,'Bellows',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('TrainingDummy',1,NULL,'TrainingDummy',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Wheelbarrow',1,NULL,'Wheelbarrow',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bucket',1,NULL,'Bucket',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WoodenShield',1,NULL,'WoodenShield',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('CrossbowStock',1,NULL,'CrossbowStock',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BlunderbussStock',1,NULL,'BlunderbussStock',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PistolStock',1,NULL,'PistolStock',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WoodStatue',1,NULL,'Statue',30.0,NULL,'Wood','Woodcarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WoodStatuette',1,NULL,'Statuette',30.0,NULL,'Wood','Woodcarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PuzzleBox',1,NULL,'PuzzleBox',30.0,NULL,'Wood','Woodcarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FellingAxeHead',1,NULL,'FellingAxeHead',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FellingAxe',1,NULL,'FellingAxe',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('CuttingWheel',1,NULL,'CuttingWheel',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('File',1,NULL,'File',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BallPeenHammer',1,NULL,'BallPeenHammer',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AlarmBell',1,NULL,'AlarmBell',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MetalStatue',1,NULL,'Statue',30.0,NULL,'Metal','Metalworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MetalStatuette',1,NULL,'Statuette',30.0,NULL,NULL,'Metalworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Coin',1,NULL,'Coin',30.0,NULL,'Metal','Metalworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Wrench',1,NULL,'Wrench',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Rod',2,NULL,'Rod',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Gear',1,NULL,'Gear',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Spring',1,NULL,'Spring',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Spike',1,NULL,'Spike',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MetalCrossbowBolt',16,NULL,'CrossbowBolt',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('CrossbowBow',1,NULL,'CrossbowBow',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MetalMusketRound',32,NULL,'MusketRound',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BlunderbussBarrel',1,NULL,'BlunderbussBarrel',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PistolBarrel',1,NULL,'PistolBarrel',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Screw',1,NULL,'Screw',30.0,NULL,'Metal','Machining');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Ring',1,NULL,'Ring',30.0,NULL,'Metal','JewelryMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('GemmedRing',1,NULL,'GemmedRing',30.0,NULL,'Gem','JewelryMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Necklace',1,NULL,'Necklace',30.0,NULL,'Metal','JewelryMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('GemmedNecklace',1,NULL,'GemmedNecklace',30.0,NULL,'Gem','JewelryMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bag',1,NULL,'Bag',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Sack',1,NULL,'Sack',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bandage',1,NULL,'Bandage',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('String',1,NULL,'String',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Padding',1,NULL,'Padding',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Mattress',1,NULL,'Mattress',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AmmoPouch',1,NULL,'AmmoPouch',30.0,NULL,'Cloth','Tailoring');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherStrap',2,'$Leather','LeatherStrap',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherArmorPanel',1,NULL,'LeatherArmorPanel',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherHelm',1,NULL,'LeatherHelm',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherCuirass',1,NULL,'LeatherCuirass',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherBracer',1,NULL,'LeatherBracer',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherPants',1,NULL,'LeatherPants',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherGlove',1,NULL,'LeatherGlove',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('LeatherBoot',1,NULL,'LeatherBoot',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Quiver',1,NULL,'Quiver',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Sausage',1,NULL,'Sausage',30.0,NULL,'Meat','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Sandwich',1,NULL,'Sandwich',30.0,NULL,'Meat','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Cheese',1,NULL,'Cheese',30.0,NULL,'Animal','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('CheeseOmelette',1,NULL,'CheeseOmelette',30.0,NULL,'Animal','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SausageOmelette',1,NULL,'SausageOmelette',30.0,NULL,'Meat','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MushroomOmelette',1,NULL,'MushroomOmelette',30.0,NULL,'Plant','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SwordBlade',1,NULL,'SwordBlade',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Sword',1,NULL,'Sword',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HandAxeHead',1,NULL,'HandAxeHead',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HandAxe',1,NULL,'HandAxe',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HammerHead',1,NULL,'HammerHead',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Hammer',1,NULL,'Hammer',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ClaymoreBlade',1,NULL,'ClaymoreBlade',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Claymore',1,NULL,'Claymore',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BattleAxeHead',1,NULL,'BattleAxeHead',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BattleAxe',1,NULL,'BattleAxe',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WarhammerHead',1,NULL,'WarhammerHead',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Warhammer',1,NULL,'Warhammer',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ShieldBoss',1,NULL,'ShieldBoss',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ShieldBacking',1,NULL,'ShieldBacking',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Shield',1,NULL,'Shield',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('TowerShieldBacking',1,NULL,'TowerShieldBacking',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('TowerShield',1,NULL,'TowerShield',30.0,NULL,'Metal','WeaponCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ArmorPlate',1,'','ArmorPlate',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Helmet',1,NULL,'Helmet',30.0,NULL,'Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Breastplate',1,NULL,'Breastplate',30.0,NULL,'Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Pauldron',1,NULL,'Pauldron',30.0,NULL,'Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Greave',1,NULL,'Greave',30.0,NULL,'Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Gauntlet',1,NULL,'Gauntlet',30.0,NULL,'Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Boot',1,NULL,'Boot',30.0,NULL,'Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Axle',1,NULL,'Axle',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MechanismBase',1,NULL,'MechanismBase',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Gearbox',1,NULL,'Gearbox',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Handcrank',1,NULL,'Handcrank',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('TrapBase',1,NULL,'TrapBase',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SpikeTrap',1,NULL,'SpikeTrap',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BladeTrap',1,NULL,'BladeTrap',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Crossbow',1,NULL,'Crossbow',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Lever',1,NULL,'Lever',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MechanicalWall',1,NULL,'MechanicalWall',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('WindmillBlade',1,NULL,'WindmillBlade',30.0,NULL,'Wood','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PressurePlate',1,NULL,'PressurePlate',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Hatch',1,NULL,'Hatch',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Blunderbuss',1,NULL,'Blunderbuss',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Pistol',1,NULL,'Pistol',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Cylinder',1,NULL,'Cylinder',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ArtificialArm',1,NULL,'ArtificialArm',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ArtificialHand',1,NULL,'ArtificialHand',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ArtificialLeg',1,NULL,'ArtificialLeg',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ArtificialFoot',1,NULL,'ArtificialFoot',30.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Needle',1,NULL,'Needle',30.0,NULL,'Bone|FishBone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MetalNeedle',1,NULL,'Needle',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BoneStatuette',1,NULL,'Statuette',30.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SkullHelmet',1,NULL,'SkullHelmet',30.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BoneShirt',1,NULL,'BoneShirt',30.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickaxeHeadWood',1,NULL,'PickaxeHead',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickaxeHeadFlintStone',1,NULL,'PickaxeHead',50.0,'FlintStone',NULL,'Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickaxeHeadStone',1,NULL,'PickaxeHead',50.0,NULL,'Stone','Masonry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickaxeBaseWood',1,NULL,'PickaxeBase',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Pickaxe',1,NULL,'Pickaxe',50.0,NULL,'Wood|Stone|Metal','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FishingRod',1,NULL,'FishingRod',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SliverFromStone',1,NULL,'Sliver',50.0,'RandomMetal',NULL,'Prospecting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SliverFromDirt',1,NULL,'Sliver',50.0,'RandomMetal',NULL,'Prospecting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ChainBoots',1,'','ChainBoot',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ChainPants',1,'','ChainPants',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ChainGloves',1,'','ChainGlove',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ChainBracers',1,'','ChainBracer',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ChainShirt',1,'','ChainShirt',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ChainHelm',1,'','ChainHelm',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PlateBoots',1,'','PlateBoot',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PlatePauldrons',1,'','PlatePauldron',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PlateGloves',1,'','PlateGlove',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PlateHelm',1,'','PlateHelm',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PlateGreaves',1,'','PlateGreaves',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PlateChest',1,'','PlateChest',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HeavyPlateBoots',1,'','HeavyPlateBoot',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HeavyPlateChest',1,'','HeavyPlateChest',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HeavyPlateGloves',1,'','HeavyPlateGlove',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HeavyPlateGreaves',1,'','HeavyPlateGreaves',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HeavyPlateHelm',1,'','HeavyPlateHelm',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HeavyPlatePauldrons',1,'','HeavyPlatePauldron',30.0,'','Metal','ArmorCrafting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickaxeHeadMetal',1,NULL,'PickaxeHead',50.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('DyedBolt',1,'$Dye','Bolt',50.0,NULL,'Cloth','Dyeing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SteamEngine',1,NULL,'SteamEngine',100.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Automaton',1,NULL,'Automaton',500.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AutomatonHead',1,NULL,'AutomatonHead',100.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AutomatonTorso',1,NULL,'AutomatonTorso',100.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AutomatonLeg',1,NULL,'AutomatonLeg',50.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AutomatonArm',1,NULL,'AutomatonArm',50.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AutomatonCoreMark1',1,NULL,'AutomatonCoreMark1',200.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AutomatonCoreMark2',1,NULL,'AutomatonCoreMark2',200.0,NULL,'Metal','Engineering');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Flour',1,NULL,'Flour',20.0,NULL,'Grain','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FlourKitchen',1,NULL,'Flour',100.0,NULL,'Grain','Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BoneTable',1,NULL,'Table',60.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BoneChair',1,NULL,'Chair',50.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BoneBedFrame',1,NULL,'BoneBedFrame',50.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BoneBed',1,NULL,'Bed',50.0,NULL,'Bone','Bonecarving');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Shed',1,NULL,'Shed',50.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BurnFishBone',0,NULL,NULL,1.0,NULL,NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BurnBone',0,NULL,NULL,1.0,NULL,NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BurnStraw',0,NULL,NULL,1.0,NULL,NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BurnSeeds',0,NULL,NULL,1.0,NULL,NULL,'Smelting');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AlarmBellBase',1,'','AlarmBellBase',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('AlarmBellBell',1,'','AlarmBellBell',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BeeHive',1,'','BeeHive',20.0,NULL,NULL,'Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Chest',1,'','Chest',10.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Bookshelf',1,NULL,'Bookshelf',30.0,NULL,'Wood','Carpentry');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('BigTorch',1,NULL,'BigTorch',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Brazier',1,NULL,'Brazier',30.0,NULL,'Metal','Blacksmithing');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Backpack',1,NULL,'Backpack',30.0,NULL,'Leather','Leatherworking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('GlassIngot',1,'Glass','GlassIngot',10.0,NULL,NULL,'GlassMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('RoughGlassGem',1,'Glass','RoughGlassGem',10.0,NULL,NULL,'GlassMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MosaicTile',1,NULL,'MosaicTile',10.0,NULL,NULL,'GlassMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Cider',1,NULL,'Cider',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Vinegar',1,NULL,'Vinegar',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Sugar',1,NULL,'Sugar',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('DropCandy',1,NULL,'DropCandy',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('ShepherdsPie',1,NULL,'ShepherdsPie',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('Biscuit',1,NULL,'Biscuit',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickledFruit',1,NULL,'PickledFruit',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FruitPreserve',1,NULL,'FruitPreserve',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SmokedMeat',1,NULL,'SmokedMeat',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SmokedSausage',1,NULL,'SmokedSausage',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FruitBread',1,NULL,'FruitBread',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FreshCheese',1,NULL,'FreshCheese',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('HardCheese',1,NULL,'HardCheese',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('MeatPie',1,NULL,'MeatPie',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickledVegetable',1,NULL,'PickledVegetable',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('PickledEgg',1,NULL,'PickledEgg',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('VegetablePreserve',1,NULL,'VegetablePreserve',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SmokedBird',1,NULL,'SmokedBird',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('SmokedFish',1,NULL,'SmokedFish',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FlatBread',1,NULL,'FlatBread',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FruitPie',1,NULL,'FruitPie',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('VeggiePie',1,NULL,'VeggiePie',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('FineMeatPie',1,NULL,'FineMeatPie',20.0,NULL,NULL,'Cooking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('GlassJar',1,NULL,'GlassJar',50.0,NULL,NULL,'GlassMaking');\r\nINSERT INTO \"Crafts\" (\"ID\",\"Amount\",\"ConversionMaterial\",\"ItemID\",\"ProductionTime\",\"ResultMaterial\",\"ResultMaterialTypes\",\"SkillID\") VALUES ('GlassBottle',1,NULL,'GlassBottle',50.0,NULL,NULL,'GlassMaking');\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Crate',0,0,'0 0 0','Crate',1);\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Barrel',0,0,'0 0 0','Barrel',1);\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Bucket',0,0,'0 0 0','Bucket',0);\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Bag',0,0,'0 0 0','Bag',0);\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Sack',0,0,'0 0 0','Sack',1);\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Wheelbarrow',0,0,'0 0 0','Wheelbarrow',0);\r\nINSERT INTO \"Containers_Tiles\" (\"ID\",\"Construction\",\"Job\",\"Offset\",\"SpriteID\",\"Stockpile\") VALUES ('Chest',0,0,'0 0 0','Chest',1);\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Crate','Crate');\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Barrel','Barrel');\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Bucket','Bucket');\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Bag','Bag');\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Sack','Sack');\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Wheelbarrow','Wheelbarrow');\r\nINSERT INTO \"Containers_Components\" (\"ID\",\"ItemID\") VALUES ('Chest','Chest');\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Crate',1,50,0,NULL,NULL);\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Barrel',1,50,1,NULL,NULL);\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Bucket',0,10,1,NULL,NULL);\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Bag',0,20,1,NULL,NULL);\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Sack',1,65,1,NULL,NULL);\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Wheelbarrow',0,15,1,NULL,NULL);\r\nINSERT INTO \"Containers\" (\"ID\",\"Buildable\",\"Capacity\",\"RequireSame\",\"Type\",\"Item\") VALUES ('Chest',1,25,0,NULL,NULL);\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('Wall');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('FancyWall');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('Fence');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('Floor');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('FancyFloor');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('WallFloor');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('Stairs');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('Ramp');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('RampCorner');\r\nINSERT INTO \"ConstructionTypes\" (\"ID\") VALUES ('Scaffold');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilStairs','0 0 0','Stairs',NULL,'StairsBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilStairs','0 0 1','StairsTop',NULL,'StairsTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneStairs','0 0 0','Stairs',NULL,'StairsBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneStairs','0 0 1','StairsTop',NULL,'StairsTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilRamp','0 0 0','Ramp',NULL,'RampBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilRamp','0 0 1','RampTop',NULL,'RampTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneRamp','0 0 0','Ramp',NULL,'RampBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneRamp','0 0 1','RampTop',NULL,'RampTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('Scaffold','0 0 0','Scaffold',NULL,'StairsBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('Scaffold','0 0 1','ScaffoldFloor',NULL,'StairsTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('Palisade','0 0 0','Palisade',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('Palisade','0 0 1','PalisadeTop',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneWall','0 0 0','RoughWall','RoughStoneWall','Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilWallFloor','0 0 0','RoughWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilWallFloor','0 0 1','RoughFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneWallFloor','0 0 0','RoughStoneWall2',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneWallFloor','0 0 1','RoughStoneFloor2',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PlankWallFloor','0 0 0','PlankWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PlankWallFloor','0 0 1','PlankFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BlockWall','0 0 0','BlockWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BrickWall','0 0 0','CeramicWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PlankWall','0 0 0','PlankWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PlankFloor','0 0 0','PlankFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilWall','0 0 0','RoughWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('LogWall','0 0 0','LogWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('ThatchWall','0 0 0','ThatchWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('ThatchFloor','0 0 0','ThatchFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('ThatchRamp','0 0 0','ThatchRamp',NULL,'RampBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('ThatchRamp','0 0 1','ThatchRampTop',NULL,'RampTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('Roof','0 0 0','CombinedRoof',NULL,'RampBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilCornerRamp','0 0 0','SoilOuterCornerRamp',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneCornerRamp','0 0 0','StoneOuterCornerRamp',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('ThatchCornerRamp','0 0 0','ThatchOuterCornerRamp',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BlockFloor','0 0 0','BlockFloor100',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('StoneFloor','0 0 0','RoughStoneFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BrickFloor','0 0 0','CeramicFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SoilFloor','0 0 0','RoughFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('LogFloor','0 0 0','LogFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyWall1','0 0 0','StarEngravedBlockWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyWall2','0 0 0','SpiralEngravedBlockWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyWall3','0 0 0','MoonEngravedBlockWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyWall4','0 0 0','WaterEngravedBlockWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyWall5','0 0 0','EngravedBlockWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyWall6','0 0 0','CarvedStoneWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyFloor1','0 0 0','StarEngravedBlockFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyFloor2','0 0 0','SpiralEngravedBlockFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyFloor3','0 0 0','MoonEngravedBlockFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyFloor4','0 0 0','WaterEngravedBlockFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyFloor5','0 0 0','EngravedBlockFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('FancyFloor6','0 0 0','CarvedStoneFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BlockFence','0 0 0','BlockFence',NULL,'WallSeeThrough');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('CobbleStoneFence','0 0 0','CobbleStoneFence',NULL,'WallSeeThrough');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('WoodFence','0 0 0','WoodFence',NULL,'WallSeeThrough');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('Pipe','0 0 0','Pipe',NULL,'WallSeeThrough');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PipeExit','0 0 0','PipeExit',NULL,'WallSeeThrough');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BoneWall','0 0 0','BoneWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('SkullWall','0 0 0','SkullWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BoneFloor','0 0 0','BoneFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('WallTorch','0 0 0','WallTorch',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PlankStairs','0 0 0','PlankStairs',NULL,'StairsBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('PlankStairs','0 0 1','PlankStairsTop',NULL,'StairsTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BlockStairs','0 0 0','StoneStairs',NULL,'StairsBottom');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('BlockStairs','0 0 1','StoneStairsTop',NULL,'StairsTop');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('MosaicWall','0 0 0','MosaicWall',NULL,'Wall');\r\nINSERT INTO \"Constructions_Sprites\" (\"ID\",\"Offset\",\"SpriteID\",\"SpriteIDOverride\",\"Type\") VALUES ('MosaicFloor','0 0 0','MosaicFloor',NULL,'Floor');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockWall','0 0 0',98.0,'BlockWall100','Wall');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockWall','0 0 0',75.0,'BlockWall75','Wall');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockWall','0 0 0',50.0,'BlockWall50','Wall');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockWall','0 0 0',25.0,'BlockWall25','Wall');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockFloor','0 0 0',75.0,'BlockFloor75','Floor');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockFloor','0 0 0',50.0,'BlockFloor50','Floor');\r\nINSERT INTO \"Constructions_IntermediateSprites\" (\"ID\",\"Offset\",\"Percent\",\"SpriteID\",\"Type\") VALUES ('BlockFloor','0 0 0',25.0,'BlockFloor25','Floor');\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SoilStairs',1,'RawSoil',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('StoneStairs',1,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SoilRamp',1,'RawSoil',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('StoneRamp',1,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('Scaffold',2,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('Palisade',4,'RawWood',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('StoneWall',1,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SoilWallFloor',2,'RawSoil',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('StoneWallFloor',2,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('PlankWallFloor',2,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BlockWall',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BrickWall',1,'Brick',NULL,'Clay|Sand');\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('PlankWall',1,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('PlankFloor',1,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SoilWall',1,'RawSoil',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('LogWall',1,'RawWood',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('ThatchWall',4,'Straw',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('ThatchFloor',4,'Straw',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('ThatchRamp',4,'Straw',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('Roof',1,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('Roof',2,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SoilCornerRamp',1,'RawSoil',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('StoneCornerRamp',1,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('ThatchCornerRamp',4,'Straw',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BlockFloor',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('StoneFloor',1,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BrickFloor',1,'Brick',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SoilFloor',1,'RawSoil',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('LogFloor',1,'RawWood',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyWall1',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyWall2',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyWall3',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyWall4',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyWall5',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyWall6',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyFloor1',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyFloor2',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyFloor3',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyFloor4',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyFloor5',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('FancyFloor6',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BlockFence',1,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('CobbleStoneFence',1,'RawStone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('WoodFence',1,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('VerticalAxle',1,'Axle',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BoneWall',5,'Bone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('SkullWall',5,'Skull',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BoneFloor',4,'Bone',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('WallTorch',1,'Torch',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('PlankStairs',4,'Plank',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('BlockStairs',2,'Block',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('MosaicWall',2,'MosaicTile',NULL,NULL);\r\nINSERT INTO \"Constructions_Components\" (\"ID\",\"Amount\",\"ItemID\",\"MaterialTypes\",\"Materials\") VALUES ('MosaicFloor',2,'MosaicTile',NULL,NULL);\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SoilStairs',0,1,'Stairs','Soil');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('StoneStairs',0,1,'Stairs','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SoilRamp',0,1,'Ramp','Soil');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('StoneRamp',0,1,'Ramp','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('Scaffold',0,0,'Stairs','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('Palisade',0,0,'Wall','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('StoneWall',1,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SoilWallFloor',1,0,'WallFloor','Soil');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('StoneWallFloor',1,0,'WallFloor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('PlankWallFloor',0,0,'WallFloor','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BlockWall',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BrickWall',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('PlankWall',0,0,'Wall','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('PlankFloor',0,0,'Floor','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SoilWall',1,0,'Wall','Soil');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('LogWall',0,0,'Wall','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('ThatchWall',0,0,'Wall','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('ThatchFloor',0,0,'Floor','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('ThatchRamp',0,0,'Ramp','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('Roof',0,0,'Ramp','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SoilCornerRamp',0,0,'RampCorner','Soil');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('StoneCornerRamp',0,0,'RampCorner','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('ThatchCornerRamp',0,0,'RampCorner','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BlockFloor',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('StoneFloor',1,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BrickFloor',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SoilFloor',1,0,'Floor','Soil');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('LogFloor',0,0,'Floor','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyWall1',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyWall2',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyWall3',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyWall4',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyWall5',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyWall6',0,0,'Wall','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyFloor1',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyFloor2',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyFloor3',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyFloor4',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyFloor5',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('FancyFloor6',0,0,'Floor','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BlockFence',0,0,'Fence','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('CobbleStoneFence',0,0,'Fence','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('WoodFence',0,0,'Fence','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('VerticalAxle',0,0,'Item',NULL);\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('Pipe',0,0,'Hydraulics',NULL);\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('PipeExit',0,0,'Hydraulics',NULL);\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BoneWall',0,0,'Wall','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('SkullWall',0,0,'Wall','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BoneFloor',0,0,'Floor','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('WallTorch',0,1,'Item',NULL);\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('PlankStairs',0,1,'Stairs','Wood');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('BlockStairs',0,1,'Stairs','Stone');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('MosaicWall',0,0,'Wall','Other');\r\nINSERT INTO \"Constructions\" (\"ID\",\"NoConstruction\",\"Rotation\",\"Type\",\"Category\") VALUES ('MosaicFloor',0,0,'Floor','Other');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmptyFloor','320 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmptyWall','320 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SelectionFloor','0 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SelectionWall','0 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SolidSelectionFloor','32 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SolidSelectionWall','32 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MiningJobWall','0 648 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughSoilFloor','0 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughSoilWall','0 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughClayFloor','256 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughClayWall','256 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughStoneFloor','32 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughStoneWall','32 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogFloor','64 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogWall','64 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockStoneFloor','128 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockStoneWall','128 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyBlockFloor','160 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyBlockWall','160 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankFloor','224 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankWall','224 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MetalFloor','96 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MetalWall','96 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmbeddedOre','0 540 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmbeddedGem','32 540 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterFloor','128 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LavaFloor','160 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterRightWall_','128 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterLeftWall_','160 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree','0 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTreeNoLeaves','32 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTree','64 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeNoLeaves','96 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree','128 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTreeNoLeaves','160 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sapling','256 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TilledSoil','288 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlantedSoil','288 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StairsTopFR','32 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StairsTopBL','96 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StairsFR','32 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StairsBL','96 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockStairsTopFR','160 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockStairsTopBL','224 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockStairsFR','160 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockStairsBL','224 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodBedFrameFR','32 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodBedFrameBL','0 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MattressFR','96 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MattressBL','64 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyWoodBedFrameFR','160 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyWoodBedFrameBL','128 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyWoodBedSheetsFR','224 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyWoodBedSheetsBL','192 432 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MetalBarPile','96 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneStatueFR','960 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneStatueBL','928 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoorLeft','896 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoorRight','992 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoorLeft','704 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoorRight','800 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodTable','96 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodChairFR','832 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodChairBL','800 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Well','256 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WellTop','288 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GearBoxBaseItem','288 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GearBoxFrameItem','352 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GearBoxBase','256 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GearBoxFrame','320 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverBaseFL','320 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverBaseFR','352 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverBaseBR','288 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverBaseBL','256 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOnFL','576 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOnFR','608 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOnBR','544 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOnBL','512 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOffFL','448 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOffFR','480 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOffBR','416 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeverOffBL','384 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PressurePlate','96 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PressurePlateItem','96 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HatchOpen','736 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HatchClosed','608 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HatchItem','704 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpikeTrap','128 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BladeTrap','224 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BladeTrapItem','96 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HandcrankFL','544 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HandcrankFR','576 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HandcrankBR','512 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HandcrankBL','480 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Windmill1','416 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Windmill2','448 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Windmill3','480 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Windmill4','512 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawSoil','96 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawStone','128 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawWood','160 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawCoal','992 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawOre','64 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawGem','0 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RawHide','32 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Block','384 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Plank','544 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bar','832 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Gem','384 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bolt','800 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bandage','800 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Wheat','320 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeSwordRight','64 324 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeSwordLeft','288 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeAxeRight','576 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeAxeLeft','544 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHammerRight','320 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHammerLeft','288 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePickaxeRight','864 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePickaxeRightBack','832 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinTorso','64 0 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHead','32 0 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinArmRight','96 0 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinArmLeft','128 0 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHandRight','160 0 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHandLeft','160 0 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinFootRight','0 72 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinFootLeft','0 72 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothTorso1','672 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothTorso2','704 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GolemTorso','96 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketStallBase','256 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarpenterStandToolsFR','384 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarpenterStandFR','320 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarpenterStandBR','352 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TableSaw','128 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTable','288 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WorkbenchFR','256 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WorkbenchBR','288 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Workmat','192 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AxeBenchFR','192 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AxeBenchBL','192 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KegFR','128 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KegBL','128 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WorkshopWaterTub','256 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinTunnel','928 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Distill','160 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TanningRackFR','192 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TanningRackBL','224 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodPile','64 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GiantStoneBlock','288 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneBlockPileFL','320 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneBlockPileFR','320 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneBlockPileBR','352 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneBlockPileBL','352 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceFR','224 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceBL','256 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceFlameFR','288 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AnvilFR','288 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AnvilBL','320 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterTrough','160 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UprightWeaponStandFL','256 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UprightWeaponStandFR','256 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UprightWeaponStandBR','224 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UprightWeaponStandBL','224 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HammerTableTopFR','384 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HammerTableTopBL','352 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CoalPile','480 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BellowsFL','256 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BellowsBR','224 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Forge','224 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MoldFR','192 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MoldBL','160 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampFL','0 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampFR','32 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampBL','64 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampBR','96 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampFR','128 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampBL','224 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampFL','192 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampBR','160 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampBL','256 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampFL','288 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampTopFL','0 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampTopFR','32 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampTopBL','64 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilRampTopBR','96 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampTopFR','128 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampTopBR','160 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampTopFL','192 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilCornerRampTopBL','224 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampTopBL','256 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampTopFL','288 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampFL','320 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampFR','352 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampBL','384 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampBR','416 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampFR','448 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampBR','480 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampFL','512 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampBL','544 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayURampBL','576 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayURampFR','608 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampTopFL','320 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampTopFR','352 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampTopBL','384 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayRampTopBR','416 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampTopFR','448 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampTopBR','480 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampTopFL','512 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayCornerRampTopBL','544 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayURampTopBL','576 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayURampTopFR','608 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampFL','0 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampFR','32 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampBL','64 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampBR','96 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampFR','128 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampBR','160 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampFL','192 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampBL','224 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneURampBL','256 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneURampFR','288 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampTopFL','0 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampTopFR','32 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampTopBL','64 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRampTopBR','96 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampTopFR','128 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampTopBR','160 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampTopFL','192 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCornerRampTopBL','224 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneURampTopBL','256 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneURampTopFR','288 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThoughtBubble','224 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StatusTired','448 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StatusSleeping','384 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StatusThirsty','416 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StatusHungry','352 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StatusCombat','320 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LittleBlood1','640 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LittleBlood2','672 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigBlood1','160 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigBlood2','192 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Crate','576 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Barrel','864 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sack','768 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Egg','832 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Meat','352 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bread','960 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sausage','224 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sandwich','192 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Milk','0 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Wine','32 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Beer','64 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TeaCup','96 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cider','128 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Vinegar','160 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sugar','192 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DropCandy','224 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShepherdsPie','256 0 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Biscuit','0 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PickledFruit','32 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FruitPreserve','64 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmokedMeat','96 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmokedSausage','128 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FruitBread','160 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FreshCheese','192 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HardCheese','224 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MeatPie','256 36 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PickledVegetable','0 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PickledEgg','32 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('VegetablePreserve','64 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmokedBird','96 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmokedFish','128 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FlatBread','160 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FruitPie','192 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('VeggiePie','224 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FineMeatPie','256 72 32 36','food_drink_ingredients.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bone','864 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Skull','960 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LoomFR','352 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LoomBL','320 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LoomFaceFL','384 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LoomFaceFR','384 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LoomFaceBR','320 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LoomFaceBL','320 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GroundTorchBase','128 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GroundTorchFlame1','160 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GroundTorchFlame2','192 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GroundTorchFlame3','224 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GroundTorchFlame4','256 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PickaxeHead','160 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FellingAxeHead','32 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SwordBlade','64 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HandAxeHead','416 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HammerHead','288 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Shield','608 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFellingAxeRight','96 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFellingAxeRightBack','64 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShieldRight','192 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShieldLeft','160 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoor','864 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoor','672 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Coin','544 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Statuette','288 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SelectionFloorTop','64 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SelectionWallTop','64 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiseledBlockFloor','480 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiseledBlockWall','480 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PetRock','96 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Gear','224 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Spring','256 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorchRight','448 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorchLeft','416 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBattleAxe','608 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BattleAxeHead','896 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeWarhammer','544 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WarhammerHead','160 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HatchFrame','640 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HatchFrameItem','672 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpikeTrapSpike2','224 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpikeTrapItemSpike','160 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BladeTrapBlade3','320 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BladeTrapItemBlade','352 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeClaymore','832 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClaymoreBlade','352 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PuzzleBox','960 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Clipping','416 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpikeTrapSpike1','192 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BladeTrapBlade1','256 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BladeTrapBlade2','288 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PickaxeBase','128 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FellingAxeBase','0 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SwordBase','96 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HandAxeBase','448 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HammerBase','320 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShieldBase','640 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BattleAxeBase','928 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WarhammerBase','192 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClaymoreBase','384 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeSwordRightBase','64 360 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeSwordLeftBase','224 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeAxeRightBase','512 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeAxeLeftBase','480 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHammerRightBase','256 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHammerBaseLeft','224 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePickaxeRightBase','800 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePickaxeRightBackBase','768 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFellingAxeRightBase','32 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFellingAxeRightBackBase','0 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShieldRightBase','128 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShieldBaseLeft','96 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorchRightBase','384 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorchBaseLeft','352 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBattleAxeBase','640 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeWarhammerBase','576 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeClaymoreBase','864 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBlunderbussBase','704 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBlunderbussBarrel','672 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlunderbussBase','768 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlunderbussBarrel','736 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePistolRightBase','928 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePistolBaseLeft','896 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePistolRight','992 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePistolLeft','960 180 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PistolBase','512 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PistolBarrel','480 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeCrossbowBase','928 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeCrossbow','896 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrossbowBase','704 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Crossbow','672 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeAmmoPouch','448 144 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeQuiver','0 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TrainingDummy','288 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StonePillar','896 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreTorso','896 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreHead','864 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreArmRight','704 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreArmLeft','672 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreHandRight','832 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreHandLeft','800 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreFootRight','768 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OgreFootLeft','736 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreTorso','672 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreHeadRight','640 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreHeadLeft','608 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreArmRight','448 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreArmLeft','416 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreHandRight','576 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreHandLeft','544 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreFootRight','512 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueOgreFootLeft','480 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantTorso','224 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantHead','128 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantAntennaeRight','32 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantAntennaeLeft','0 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantArmRight','96 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantArmLeft','64 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantLegRight','192 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantLegLeft','160 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeetleTorso','0 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeetleHead','992 36 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cocoon','512 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieTorso','544 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieHead','512 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieArmRight','352 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieArmLeft','320 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieHandRight','480 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieHandLeft','448 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieFootRight','416 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZombieFootLeft','384 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonTorso','928 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonHead','896 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonArmRight','736 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonArmLeft','704 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonHandRight','864 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonHandLeft','832 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonFootRight','800 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkeletonFootLeft','768 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KnifeBlade','128 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KnifeHilt','160 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Hilt','800 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ForgeTop','256 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MoldTopFR','128 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('String','32 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillBlade','544 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cylinder','736 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Spike','96 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyWoodBedTopFR','992 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BellowsNozzleBL','288 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BellowsNozzleFR','320 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogFL','768 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogFR','800 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogBR','736 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogBL','704 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OldGrain','928 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Chisel','288 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Wrench','64 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StrawBed','0 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArmorPlate','128 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherPanel','192 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherStrip','224 288 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneNeedle','896 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneTable','992 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneChairFR','640 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneChairBL','608 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StarEngravedBlockFloor','352 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StarEngravedBlockWall','352 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpiralEngravedBlockFloor','384 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpiralEngravedBlockWall','384 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MoonEngravedBlockFloor','416 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MoonEngravedBlockWall','416 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterEngravedBlockFloor','448 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterEngravedBlockWall','448 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EngravedBlockFloor','192 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EngravedBlockWall','192 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneFloor','512 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneWall','512 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchFloor','544 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchWall','544 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchRampTopFR','480 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchRampTopBR','544 216 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchRampFR','480 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchRampBR','544 252 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsTopFR','256 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsTopFL','288 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsTopBL','320 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsTopBR','352 288 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsFR','256 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsFL','288 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsBL','320 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankStairsBR','352 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PostAndRailFencePost','704 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PostAndRailFenceFL','640 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PostAndRailFenceFR','672 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PostAndRailFenceBR','608 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PostAndRailFenceBL','576 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PicketFencePost','320 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PicketFenceFL','256 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PicketFenceFR','288 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PicketFenceBR','224 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PicketFenceBL','192 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CabinetFR','96 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CabinetBL','64 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneShirt','928 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpFloor','800 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpScrew1','832 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpScrew2','864 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpScrew3','896 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpScrew4','928 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Screw','512 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTableLeft','384 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTableLeft2','416 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTableRight','448 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTableRight2','480 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTableBladeFL','352 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawTableBladeBL','320 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrateLog','0 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CratePlank','256 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawHorse','224 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WorkshopTable','224 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiselTableTopFR','352 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiselTableTopBL','384 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShearsTableTopFR','128 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShearsTableTopBL','96 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClothRollTableTop','0 504 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ButcherTableTopFR','384 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ButcherTableTopBL','352 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KitchenTableTopFL','0 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KitchenTableTopFR','0 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KitchenTableTopBR','32 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KitchenTableTopBL','32 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ViseTableTop','352 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueprintTableTop','0 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperTableTopFL','32 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperTableTopFR','32 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperTableTopBR','32 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperTableTopBL','32 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('JewelryPile','832 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnFR','256 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnBL','224 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnFlameFR','288 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketStallTop','288 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoltRoundPile','832 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MusketRoundPile','640 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MetalSliver','416 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTree','192 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeNoLeaves','224 252 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Trough','352 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomPlant','608 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomItem','576 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cheese','224 108 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Omelette','960 324 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Wheelbarrow','352 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WheelbarrowBackHandle','384 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkullOnPikeFL','32 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkullOnPikeFR','64 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkullOnPikeBR','0 432 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkullOnPikeBL','992 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PikeFL','416 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PikeFR','448 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PikeBR','384 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PikeBL','352 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlarmBellBase','320 108 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlarmBellBell','352 108 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TowerShieldBase','288 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TowerShield','256 504 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ScaffoldFloor','608 72 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Scaffold','608 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GolemArmRight','992 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GolemArmLeft','960 216 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GolemLegRight','64 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GolemLegLeft','32 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodFloorFrame','352 396 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodCrossFrame','192 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodVFloorFrame','224 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodVFrame','224 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodPanelledFloorFrame','192 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodPanelledFrame','192 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmoothStoneFloor','256 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmoothStoneWall','256 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CeramicFloor','288 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CeramicWall','288 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarvedStoneFloor','352 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarvedStoneWall','352 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Silica','672 396 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightArm','256 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialLeftArm','160 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightHand','352 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialLeftHand','192 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightLeg','416 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialLeftLeg','224 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightArms','320 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightArmHands','288 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightHands','384 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtificialRightLegs','448 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonHeadFR','32 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GolemCore','0 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoorLeftOpenLeft','928 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoorLeftOpenRight','960 540 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoorRightOpenLeft','0 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodDoorRightOpenRight','32 576 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoorLeftOpenLeft','736 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoorLeftOpenRight','768 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoorRightOpenLeft','832 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneDoorRightOpenRight','864 468 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughSoilWallShort','0 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughClayWallShort','256 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughStoneWallShort','32 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LogWallShort','64 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockWallShort','128 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FancyBlockWallShort','160 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarvedStoneWallShort','352 684 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlankWallShort','224 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MetalWallShort','96 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MetalHighlightWallShort','96 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiseledBlockWallShort','480 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StarEngravedBlockWallShort','352 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpiralEngravedBlockWallShort','384 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MoonEngravedBlockWallShort','416 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WaterEngravedBlockWallShort','448 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EngravedBlockWallShort','192 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneWallShort','512 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchWallShort','544 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodWallShortFrame','192 684 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodVWallShortFrame','224 684 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodPanelledWallShortFrame','320 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SmoothStoneWallShort','256 684 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CeramicWallShort','288 684 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarvedWallShort','480 108 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ProspectorTableOreTop','736 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ProspectorTableSliverTop','768 360 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Panda','224 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Rabbit','192 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Chicken','192 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PigPink','96 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PigYellow','128 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sheep','160 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Woodlouse','480 360 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PandaBack','224 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RabbitBack','192 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChickenBack','192 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PigPinkBack','96 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PigYellowBack','128 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepBack','160 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodlouseBack','480 396 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Badger','0 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BadgerBack','0 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Lizzard','32 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LizzardBack','32 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlackBear','96 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlackBearBack','96 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Llama','32 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LlamaBack','32 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Yak','64 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YakBack','64 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Emu','288 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmuBack','288 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Spider','416 360 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpiderBack','416 396 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Beetle','448 360 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeetleBack','448 396 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RabbitYoung','192 288 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RabbitYoungBack','192 324 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChickenYoung','192 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChickenYoungBack','192 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PigYoung','96 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PigYoungBack','96 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepYoung','160 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepYoungBack','160 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LlamaYoung','32 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LlamaYoungBack','32 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YakYoung','64 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YakYoungBack','64 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmuYoung','288 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('EmuYoungBack','288 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Duck','224 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cow','0 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CowBack','0 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CowYoung','0 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CowYoungBack','0 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DuckBack','224 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DuckYoung','224 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DuckYoungBack','224 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Goose','256 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GooseBack','256 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GooseYoung','256 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GooseYoungBack','256 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Shepherd','320 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShepherdBack','320 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShepherdYoung','320 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShepherdYoungBack','320 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CatTabby','352 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CatTabbyBack','352 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CatBlack','384 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CatBlackBack','384 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Porcupine','64 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PorcupineBack','64 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Fox','128 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FoxBack','128 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Wolf','160 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WolfBack','160 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stag','256 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StagBack','256 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Roe','288 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoeBack','288 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Goat','320 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoatBack','320 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoatYoung','320 288 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoatYoungBack','320 324 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Squirrel','352 216 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SquirrelBack','352 252 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GreyFish','0 360 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GreyFishBack','0 396 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GreenFish','32 360 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GreenFishBack','32 396 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShedFR','96 144 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ShedBL','128 144 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Snake','128 360 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Carrot','32 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarrotPlant','32 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarrotPlantWithFruit','32 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Onion','64 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OnionPlant','64 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OnionPlantWithFruit','64 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Potato','96 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PotatoPlant','96 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PotatoPlantWithFruit','96 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cabbage','128 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CabbagePlant','128 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CabbagePlantWithFruit','128 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Asparagus','160 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AsparagusPlant','160 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AsparagusPlantWithFruit','160 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Broccoli','192 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BroccoliPlant','192 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BroccoliPlantWithFruit','192 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cauliflower','224 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CauliflowerPlant','224 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CauliflowerPlantWithFruit','224 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cucumber','256 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CucumberPlant','256 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CucumberPlantWithFruit','256 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RicePlant','288 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RicePlantWithFruit','288 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Garlic','0 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GarlicPlant','0 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GarlicPlantWithFruit','0 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Parsnip','32 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ParsnipPlant','32 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ParsnipPlantWithFruit','32 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Radish','64 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RadishPlant','64 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RadishPlantWithFruit','64 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Turnip','96 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TurnipPlant','96 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TurnipPlantWithFruit','96 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Lettuce','128 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LettucePlant','128 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LettucePlantWithFruit','128 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Melon','160 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MelonPlant','160 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MelonPlantWithFruit','160 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sugarbeet','192 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SugarbeetPlant','192 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SugarbeetPlantWithFruit','192 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pumpkin','224 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpkinPlant','224 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpkinPlantWithFruit','224 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Peas','256 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PeasPlant','256 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PeasPlantWithFruit','256 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeetRoot','288 108 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeetRootPlant','288 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeetRootWithFruit','288 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Tea','0 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TeaPlant','0 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TeaPlantWithFruit','0 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Tobacco','32 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TobaccoPlant','32 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TobaccoPlantWithFruit','32 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pineapple','64 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineapplePlant','64 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineapplePlantWithFruit','64 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Corn','96 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CornPlant','96 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CornPlantWithFruit','96 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Leek','128 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeekPlant','128 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeekPlantWithFruit','128 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Beans','160 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeansPlant','160 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeansPlantWithFruit','160 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Blackberry','192 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlackberryPlant','192 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlackberryPlantWithFruit','192 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Artichoke','224 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtichokePlant','224 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArtichokePlantWithFruit','224 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bottlegourd','256 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BottlegourdPlant','256 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BottlegourdPlantWithFruit','256 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grape','288 216 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrapePlant','288 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrapePlantWithFruit','288 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Tomato','0 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TomatoPlant','0 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TomatoPlantWithFruit','0 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Capsicum','32 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CapsicumPlant','32 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CapsicumPlantWithFruit','32 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Woad','64 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoadPlant','64 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoadPlantWithFruit','64 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyersWeed','96 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyersWeedPlant','96 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyersWeedPlantWithFruit','96 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlantGrowHelper1','160 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlantGrowHelper2','160 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlantGrowHelper3','160 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BarleyPlant','192 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BarleyPlantWithFruit','192 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OatPlant','224 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OatPlantWithFruit','224 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MilletPlant','256 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MilletPlantWithFruit','256 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WheatPlant','288 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WheatPlantWithFruit','288 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grain','192 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Strawberry','320 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StrawberryPlant','320 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StrawberryPlantWithFruit','320 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Fiber','352 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CottonPlant','352 36 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CottonPlantWithFruit','352 72 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Seed','256 576 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Apple','256 540 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Orange','288 540 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeeHiveEmpty','128 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BeeHiveFull','128 396 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineCone','320 540 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StrawMushroom','320 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodMushroom','352 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FibreMushroom','384 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrainMushroom','416 360 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Oak','352 540 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pigment','0 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Dye','96 0 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyedCloth','32 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodTub','288 144 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingRodsFR','0 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingRodsBL','32 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingRackFR','32 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingRackBL','32 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingVat','0 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingFishRack','32 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneChairFR','224 216 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneChairBL','256 216 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneTable','224 252 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting1','0 144 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting2','0 180 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting3','0 216 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting4','0 252 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting5','32 144 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting6','32 180 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting7','32 216 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Painting8','32 252 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockWall25','0 396 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockWall50','32 396 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockWall75','64 396 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockWall100','96 396 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFloor25','0 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFloor50','32 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFloor75','64 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFloor100','96 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrePile','288 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneOuterCornerRampFR','480 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneOuterCornerRampBR','480 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneOuterCornerRampFL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneOuterCornerRampBL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilOuterCornerRampFR','512 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilOuterCornerRampBR','512 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilOuterCornerRampFL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilOuterCornerRampBL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayOuterCornerRampFR','544 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayOuterCornerRampBR','544 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayOuterCornerRampFL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClayOuterCornerRampBL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchOuterCornerRampFR','608 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchOuterCornerRampBR','608 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchOuterCornerRampFL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThatchOuterCornerRampBL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Spring_FR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Spring_BR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Spring_FL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Summer_FR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Summer_BR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Summer_FL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Autumn_FR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Autumn_BR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Autumn_FL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Winter_FR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Winter_BR','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassOuterCornerRamp_Winter_FL','448 324 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Palisade','128 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PalisadeTop','128 396 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughSandFloor','384 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughSandWall','384 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughSandWallShort','384 684 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodFenceWest','0 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodFencePost','32 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodFenceEast','64 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFenceWest','96 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFencePost','128 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFenceEast','160 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CobbleStoneFenceWest','192 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CobbleStoneFencePost','224 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CobbleStoneFenceEast','256 432 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFenceNorth','96 468 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlockFenceSouth','128 468 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CobbleStoneFenceNorth','160 468 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CobbleStoneFenceSouth','192 468 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodFenceNorth','0 468 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodFenceSouth','32 468 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RafterFR','0 504 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoofingFR','32 504 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RafterBL','64 504 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoofingBL','96 504 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHead','32 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorso','64 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeArmRight','96 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeArmLeft','128 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFeet','0 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeArmor','160 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHelmet1','160 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeArmorBack','192 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHelmet1Back','192 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeadBack','32 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorsoBack','64 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeArmRightBack','128 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeArmLeftBack','96 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFeetBrown','0 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFeetBrownBack','0 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBoots','192 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBootsBack','192 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair1','0 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair2','32 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair3','64 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair4','96 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair5','128 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair6','160 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair7','192 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair8','224 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair9','256 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair10','288 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair11','320 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair12','352 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair13','384 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair14','416 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair15','448 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair1Back','0 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair2Back','32 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair3Back','64 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair4Back','96 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair5Back','128 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair6Back','160 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair7Back','192 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair8Back','224 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair9Back','256 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair10Back','288 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair11Back','320 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair12Back','352 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair13Back','384 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair14Back','416 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHair15Back','448 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt1','0 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt2','32 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt3','64 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt4','96 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt5','128 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt6','160 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt7','192 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt8','224 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt9','256 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt10','288 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt11','320 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt12','352 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt13','384 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt14','416 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt15','448 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt1Back','0 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt2Back','32 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt3Back','64 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt4Back','96 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt5Back','128 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt6Back','160 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt7Back','192 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt8Back','224 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt9Back','256 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt10Back','288 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt11Back','320 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt12Back','352 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt13Back','384 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt14Back','416 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeShirt15Back','448 288 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair1','0 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair2','32 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair3','64 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair4','96 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair5','128 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair6','160 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair7','192 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair8','224 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair9','256 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair10','288 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair11','320 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair12','352 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair13','384 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair14','416 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFacialHair15','448 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeWheelbarrowRight','224 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeWheelbarrowLeft','224 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeWheelbarrowRightBase','224 0 1 1','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeWheelbarrowBaseLeft','224 32 1 1','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bag','256 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bucket','288 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBagRight','256 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBagLeft','256 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBucketRight','288 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBucketLeft','288 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBagRightBase','256 0 1 1','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBagBaseLeft','256 32 1 1','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBucketRightBase','288 0 1 1','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBucketBaseLeft','288 32 1 1','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FishingRod','320 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFishingRodLeft','320 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeFishingRodRight','320 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopFL','0 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopFR','32 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopBL','64 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeMiddle','96 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopBR','128 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopCornerFront','160 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopCornerBack','512 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopCornerLeft','192 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTopCornerRight','224 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeBottomCornerLeft','256 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeBottomCornerFront','288 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeBottomCornerRight','320 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeBottom','352 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTrunkMiddle','384 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeTrunkBottom','416 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeApples','448 0 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeApple1','0 72 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeApple2','32 72 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AppleTreeApple3','64 72 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopFL','0 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopFR','32 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopBL','64 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeMiddle','96 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopBR','128 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopCornerFront','160 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopCornerBack','512 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopCornerLeft','192 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTopCornerRight','224 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeBottomCornerLeft','256 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeBottomCornerFront','288 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeBottomCornerRight','320 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeBottom','352 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTrunkMiddle','384 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeTrunkBottom','416 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeOranges','448 108 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeOrange1','96 72 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeOrange2','128 72 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeOrange3','160 72 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeMiddleCornerLeft','0 144 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeMiddleCornerRight','32 144 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeMiddleCornerFront','64 144 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeTreeMiddleCornerBack','96 144 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree1','0 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree2','32 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree3','64 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree4','96 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTreeTop','128 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTrunk2','160 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTrunk1','192 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree8','224 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree9','256 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree10','288 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree11','320 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree12','352 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree13','384 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree14','416 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree15','448 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree16','480 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PineTree17','512 36 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree1','0 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree2','32 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree3','64 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree4','96 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree5','128 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree6','160 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree7','192 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree8','224 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree9','256 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree10','288 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree11','320 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree12','352 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree13','384 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree14','416 180 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree21','0 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree22','32 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree23','64 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree24','96 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree25','128 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree26','160 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree27','192 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree28','224 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree29','256 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree210','288 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree211','320 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree212','352 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree213','384 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OakTree214','416 216 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree1','0 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree2','32 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree3','64 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree4','96 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree5','128 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree6','160 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree7','192 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree8','224 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree9','256 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree10','288 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree11','320 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree12','352 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree13','384 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree14','416 360 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree21','0 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree22','32 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree23','64 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree24','96 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree25','128 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree26','160 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree27','192 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree28','224 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree29','256 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree210','288 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree211','320 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree212','352 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree213','384 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WillowTree214','416 396 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_0','0 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_1','32 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_2','64 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_3','96 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_4','128 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_5','160 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_6','192 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_7','224 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_8','256 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_9','288 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_10','320 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_11','352 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_1_12','384 36 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_0','0 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_1','32 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_2','64 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_3','96 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_4','128 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_5','160 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_6','192 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_7','224 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_8','256 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_9','288 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_10','320 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_11','352 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_2_12','384 72 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_0','0 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_1','32 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_2','64 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_3','96 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_4','128 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_5','160 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_6','192 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_7','224 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_8','256 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_9','288 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_10','320 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_11','352 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_3_12','384 108 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_0','0 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_1','32 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_2','64 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_3','96 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_4','128 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_5','160 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_6','192 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_7','224 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_8','256 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_9','288 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_10','320 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_11','352 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_4_12','384 144 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_0','0 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_1','32 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_2','64 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_3','96 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_4','128 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_5','160 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_6','192 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_7','224 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_8','256 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_9','288 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_10','320 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_11','352 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_5_12','384 180 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_0','0 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_1','32 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_2','64 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_3','96 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_4','128 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_5','160 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_6','192 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_7','224 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_8','256 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_9','288 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_10','320 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_11','352 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_6_12','384 216 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_0','0 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_1','32 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_2','64 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_3','96 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_4','128 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_5','160 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_6','192 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_7','224 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_8','256 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_9','288 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_10','320 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_11','352 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_7_12','384 252 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_0','0 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_1','32 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_2','64 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_3','96 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_4','128 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_5','160 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_6','192 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_7','224 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_8','256 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_9','288 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_10','320 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_11','352 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_8_12','384 288 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_0','0 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_1','32 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_2','64 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_3','96 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_4','128 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_5','160 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_6','192 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_7','224 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_8','256 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_9','288 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_10','320 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_11','352 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_9_12','384 324 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_0','0 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_1','32 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_2','64 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_3','96 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_4','128 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_5','160 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_6','192 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_7','224 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_8','256 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_9','288 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_10','320 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_11','352 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_10_12','384 360 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_0','0 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_1','32 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_2','64 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_3','96 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_4','128 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_5','160 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_6','192 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_7','224 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_8','256 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_9','288 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_10','320 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_11','352 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_11_12','384 396 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_0','0 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_1','32 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_2','64 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_3','96 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_4','128 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_5','160 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_6','192 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_7','224 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_8','256 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_9','288 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_10','320 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_11','352 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_12_12','384 432 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_0','0 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_1','32 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_2','64 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_3','96 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_4','128 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_5','160 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_6','192 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_7','224 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_8','256 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_9','288 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_10','320 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_11','352 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_13_12','384 468 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_0','0 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_1','32 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_2','64 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_3','96 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_4','128 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_5','160 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_6','192 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_7','224 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_8','256 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_9','288 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_10','320 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_11','352 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_14_12','384 504 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_0','0 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_1','32 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_2','64 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_3','96 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_4','128 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_5','160 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_6','192 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_7','224 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_8','256 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_9','288 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_10','320 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_11','352 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_15_12','384 540 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_0','0 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_1','32 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_2','64 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_3','96 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_4','128 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_5','160 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_6','192 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_7','224 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_8','256 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_9','288 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_10','320 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_11','352 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_16_12','384 576 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_0','0 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_1','32 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_2','64 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_3','96 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_4','128 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_5','160 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_6','192 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_7','224 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_8','256 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_9','288 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_10','320 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_11','352 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_17_12','384 612 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_0','0 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_1','32 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_2','64 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_3','96 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_4','128 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_5','160 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_6','192 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_7','224 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_8','256 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_9','288 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_10','320 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_11','352 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_18_12','384 648 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_0','0 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_1','32 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_2','64 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_3','96 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_4','128 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_5','160 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_6','192 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_7','224 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_8','256 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_9','288 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_10','320 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_11','352 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_19_12','384 684 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_0','0 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_1','32 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_2','64 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_3','96 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_4','128 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_5','160 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_6','192 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_7','224 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_8','256 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_9','288 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_10','320 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_11','352 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_20_12','384 720 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_0','0 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_1','32 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_2','64 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_3','96 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_4','128 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_5','160 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_6','192 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_7','224 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_8','256 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_9','288 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_10','320 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_11','352 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_21_12','384 756 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_0','0 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_1','32 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_2','64 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_3','96 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_4','128 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_5','160 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_6','192 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_7','224 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_8','256 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_9','288 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_10','320 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_11','352 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_22_12','384 792 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_0','0 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_1','32 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_2','64 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_3','96 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_4','128 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_5','160 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_6','192 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_7','224 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_8','256 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_9','288 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_10','320 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_11','352 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_23_12','384 828 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_0','0 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_1','32 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_2','64 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_3','96 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_4','128 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_5','160 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_6','192 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_7','224 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_8','256 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_9','288 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_10','320 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_11','352 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_24_12','384 864 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_0','0 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_1','32 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_2','64 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_3','96 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_4','128 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_5','160 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_6','192 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_7','224 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_8','256 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_9','288 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_10','320 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_11','352 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_25_12','384 900 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_0','0 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_1','32 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_2','64 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_3','96 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_4','128 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_5','160 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_6','192 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_7','224 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_8','256 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_9','288 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_10','320 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_11','352 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_26_12','384 936 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_0','0 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_1','32 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_2','64 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_3','96 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_4','128 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_5','160 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_6','192 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_7','224 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_8','256 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_9','288 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_10','320 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_11','352 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_27_12','384 972 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_0','0 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_1','32 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_2','64 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_3','96 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_4','128 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_5','160 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_6','192 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_7','224 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_8','256 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_9','288 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_10','320 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_11','352 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_28_12','384 1008 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_0','0 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_1','32 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_2','64 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_3','96 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_4','128 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_5','160 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_6','192 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_7','224 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_8','256 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_9','288 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_10','320 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_11','352 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_29_12','384 1044 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_0','0 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_1','32 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_2','64 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_3','96 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_4','128 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_5','160 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_6','192 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_7','224 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_8','256 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_9','288 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_10','320 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_11','352 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Grass_30_12','384 1080 32 36','seasonalgrass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('empty','256 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_0','0 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_1','32 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_2','64 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_3','96 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_4','128 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_5','160 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_6','192 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_7','224 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RedFlower_8','256 0 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_0','0 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_1','32 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_2','64 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_3','96 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_4','128 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_5','160 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_6','192 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_7','224 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BlueFlower_8','256 36 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_0','0 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_1','32 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_2','64 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_3','96 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_4','128 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_5','160 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_6','192 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_7','224 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowFlower_8','256 72 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_0','0 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_1','32 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_2','64 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_3','96 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_4','128 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_5','160 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_6','192 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_7','224 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PurpleFlower_8','256 108 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_0','0 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_1','32 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_2','64 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_3','96 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_4','128 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_5','160 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_6','192 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_7','224 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeFlower_8','256 144 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_0','0 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_1','32 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_2','64 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_3','96 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_4','128 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_5','160 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_6','192 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_7','224 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_8','256 180 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_0','0 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_1','32 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_2','64 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_3','96 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_4','128 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_5','160 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_6','192 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_7','224 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_8','256 216 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_0','0 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_1','32 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_2','64 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_3','96 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_4','128 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_5','160 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_6','192 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_7','224 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_8','256 252 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_0','0 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_1','32 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_2','64 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_3','96 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_4','128 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_5','160 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_6','192 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_7','224 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WhiteMushroom_Snow_8','256 288 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_0','0 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_1','32 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_2','64 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_3','96 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_4','128 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_5','160 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_6','192 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_7','224 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('YellowMushroom_Snow_8','256 324 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_0','0 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_1','32 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_2','64 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_3','96 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_4','128 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_5','160 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_6','192 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_7','224 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OrangeMushroom_Snow_8','256 360 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_0','0 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_1','32 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_2','64 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_3','96 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_4','128 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_5','160 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_6','192 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_7','224 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_8','256 396 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_0','0 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_1','32 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_2','64 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_3','96 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_4','128 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_5','160 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_6','192 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_7','224 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Stone_Snow_8','256 432 32 36','seasonaldetails.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Spring_FL','0 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Spring_FL','0 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Spring_FR','32 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Spring_FR','32 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Spring_BL','64 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Spring_BL','64 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Spring_BR','96 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Spring_BR','96 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_April_FL','0 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_April_FL','0 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_April_FR','32 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_April_FR','32 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_April_BL','64 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_April_BL','64 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_April_BR','96 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_April_BR','96 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_May_FL','0 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_May_FL','0 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_May_FR','32 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_May_FR','32 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_May_BL','64 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_May_BL','64 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_May_BR','96 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_May_BR','96 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_June_FL','0 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_June_FL','0 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_June_FR','32 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_June_FR','32 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_June_BL','64 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_June_BL','64 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_June_BR','96 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_June_BR','96 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Summer_FL','0 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Summer_FL','0 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Summer_FR','32 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Summer_FR','32 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Summer_BL','64 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Summer_BL','64 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Summer_BR','96 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Summer_BR','96 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_August_FL','0 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_August_FL','0 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_August_FR','32 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_August_FR','32 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_August_BL','64 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_August_BL','64 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_August_BR','96 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_August_BR','96 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_September_FL','0 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_September_FL','0 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_September_FR','32 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_September_FR','32 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_September_BL','64 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_September_BL','64 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_September_BR','96 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_September_BR','96 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Autumn_FL','0 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Autumn_FL','0 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Autumn_FR','32 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Autumn_FR','32 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Autumn_BL','64 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Autumn_BL','64 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Autumn_BR','96 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Autumn_BR','96 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_November_FL','0 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_November_FL','0 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_November_FR','32 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_November_FR','32 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_November_BL','64 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_November_BL','64 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_November_BR','96 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_November_BR','96 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_December_FL','0 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_December_FL','0 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_December_FR','32 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_December_FR','32 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_December_BL','64 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_December_BL','64 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_December_BR','96 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_December_BR','96 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Winter_FL','0 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Winter_FL','0 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Winter_FR','32 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Winter_FR','32 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Winter_BL','64 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Winter_BL','64 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_Winter_BR','96 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_Winter_BR','96 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_February_FL','0 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_February_FL','0 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_February_FR','32 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_February_FR','32 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_February_BL','64 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_February_BL','64 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRampTop_February_BR','96 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassRamp_February_BR','96 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Spring_FL','128 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Spring_FL','128 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Spring_FR','160 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Spring_FR','160 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Spring_BL','192 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Spring_BL','192 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Spring_BR','224 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Spring_BR','224 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_April_FL','128 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_April_FL','128 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_April_FR','160 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_April_FR','160 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_April_BL','192 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_April_BL','192 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_April_BR','224 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_April_BR','224 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_May_FL','128 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_May_FL','128 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_May_FR','160 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_May_FR','160 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_May_BL','192 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_May_BL','192 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_May_BR','224 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_May_BR','224 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_June_FL','128 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_June_FL','128 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_June_FR','160 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_June_FR','160 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_June_BL','192 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_June_BL','192 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_June_BR','224 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_June_BR','224 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Summer_FL','128 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Summer_FL','128 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Summer_FR','160 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Summer_FR','160 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Summer_BL','192 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Summer_BL','192 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Summer_BR','224 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Summer_BR','224 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_August_FL','128 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_August_FL','128 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_August_FR','160 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_August_FR','160 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_August_BL','192 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_August_BL','192 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_August_BR','224 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_August_BR','224 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_September_FL','128 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_September_FL','128 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_September_FR','160 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_September_FR','160 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_September_BL','192 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_September_BL','192 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_September_BR','224 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_September_BR','224 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Autumn_FL','128 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Autumn_FL','128 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Autumn_FR','160 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Autumn_FR','160 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Autumn_BL','192 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Autumn_BL','192 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Autumn_BR','224 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Autumn_BR','224 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_November_FL','128 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_November_FL','128 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_November_FR','160 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_November_FR','160 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_November_BL','192 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_November_BL','192 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_November_BR','224 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_November_BR','224 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_December_FL','128 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_December_FL','128 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_December_FR','160 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_December_FR','160 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_December_BL','192 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_December_BL','192 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_December_BR','224 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_December_BR','224 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Winter_FL','128 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Winter_FL','128 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Winter_FR','160 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Winter_FR','160 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Winter_BL','192 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Winter_BL','192 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_Winter_BR','224 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_Winter_BR','224 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_February_FL','128 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_February_FL','128 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_February_FR','160 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_February_FR','160 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_February_BL','192 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_February_BL','192 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRampTop_February_BR','224 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassCornerRamp_February_BR','224 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Spring_FR','256 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Spring_FR','256 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Spring_FL','288 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Spring_FL','288 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Spring_BL','256 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Spring_BL','256 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Spring_BR','288 0 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Spring_BR','288 36 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_April_FL','256 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_April_FL','256 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_April_FR','288 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_April_FR','288 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_April_BR','256 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_April_BR','256 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_April_BL','288 72 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_April_BL','288 108 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_May_FL','256 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_May_FL','256 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_May_FR','288 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_May_FR','288 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_May_BR','256 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_May_BR','256 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_May_BL','288 144 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_May_BL','288 180 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_June_FL','256 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_June_FL','256 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_June_FR','288 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_June_FR','288 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_June_BR','256 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_June_BR','256 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_June_BL','288 216 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_June_BL','288 252 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Summer_FR','256 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Summer_FR','256 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Summer_FL','288 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Summer_FL','288 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Summer_BL','256 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Summer_BL','256 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Summer_BR','288 288 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Summer_BR','288 324 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_August_FL','256 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_August_FL','256 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_August_FR','288 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_August_FR','288 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_August_BR','256 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_August_BR','256 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_August_BL','288 360 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_August_BL','288 396 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_September_FL','256 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_September_FL','256 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_September_FR','288 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_September_FR','288 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_September_BR','256 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_September_BR','256 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_September_BL','288 432 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_September_BL','288 468 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Autumn_FR','256 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Autumn_FR','256 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Autumn_FL','288 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Autumn_FL','288 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Autumn_BL','256 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Autumn_BL','256 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Autumn_BR','288 504 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Autumn_BR','288 540 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_November_FL','256 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_November_FL','256 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_November_FR','288 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_November_FR','288 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_November_BR','256 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_November_BR','256 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_November_BL','288 576 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_November_BL','288 612 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_December_FL','256 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_December_FL','256 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_December_FR','288 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_December_FR','288 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_December_BR','256 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_December_BR','256 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_December_BL','288 648 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_December_BL','288 684 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Winter_FR','256 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Winter_FR','256 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Winter_FL','288 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Winter_FL','288 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Winter_BL','256 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Winter_BL','256 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_Winter_BR','288 720 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_Winter_BR','288 756 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_February_FL','256 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_February_FL','256 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_February_FR','288 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_February_FR','288 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_February_BR','256 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_February_BR','256 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURampTop_February_BL','288 792 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrassURamp_February_BL','288 828 32 36','seasonalslopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pentagram1','0 0 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pentagram2','32 0 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pentagram3','0 0 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Pentagram4','32 0 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SparkleFrame1','96 40 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SparkleFrame2','128 40 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SparkleFrame3','160 40 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SparkleFrame4','192 40 32 36','magic.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrass1','0 0 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrass2','32 0 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrass3','64 0 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrass4','96 0 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrass5','128 0 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassDetail1','0 32 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassDetail2','32 32 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassDetail3','64 32 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassDetail4','96 32 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassDetail5','128 32 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrystalPole','64 180 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrystalShroom','96 180 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrystalSnakeFR','0 180 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrystalSnakeBL','32 180 32 36','mushroom_biome_grass.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_1_FL','0 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_1_FL','0 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_1_FR','32 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_1_FR','32 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_1_BL','64 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_1_BL','64 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_1_BR','96 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_1_BR','96 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_1_FL','128 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_1_FL','128 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_1_FR','160 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_1_FR','160 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_1_BL','192 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_1_BL','192 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_1_BR','224 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_1_BR','224 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_1_FR','256 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_1_FR','256 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_1_FL','288 0 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_1_FL','288 36 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_2_FL','0 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_2_FL','0 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_2_FR','32 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_2_FR','32 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_2_BL','64 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_2_BL','64 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_2_BR','96 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_2_BR','96 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_2_FL','128 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_2_FL','128 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_2_FR','160 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_2_FR','160 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_2_BL','192 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_2_BL','192 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_2_BR','224 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_2_BR','224 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_2_FR','256 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_2_FR','256 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_2_FL','288 72 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_2_FL','288 72 32 32','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_3_FL','0 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_3_FL','0 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_3_FR','32 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_3_FR','32 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_3_BL','64 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_3_BL','64 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_3_BR','96 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_3_BR','96 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_3_FL','128 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_3_FL','128 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_3_FR','160 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_3_FR','160 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_3_BL','192 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_3_BL','192 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_3_BR','224 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_3_BR','224 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_3_FR','256 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_3_FR','256 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_3_FL','288 144 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_3_FL','288 180 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_4_FL','0 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_4_FL','0 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_4_FR','32 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_4_FR','32 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_4_BL','64 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_4_BL','64 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_4_BR','96 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_4_BR','96 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_4_FL','128 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_4_FL','128 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_4_FR','160 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_4_FR','160 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_4_BL','192 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_4_BL','192 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_4_BR','224 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_4_BR','224 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_4_FR','256 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_4_FR','256 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_4_FL','288 216 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_4_FL','288 252 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_5_FL','0 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_5_FL','0 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_5_FR','32 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_5_FR','32 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_5_BL','64 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_5_BL','64 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRampTop_5_BR','96 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassRamp_5_BR','96 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_5_FL','128 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_5_FL','128 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_5_FR','160 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_5_FR','160 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_5_BL','192 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_5_BL','192 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRampTop_5_BR','224 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassCornerRamp_5_BR','224 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_5_FR','256 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_5_FR','256 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURampTop_5_FL','288 288 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MushroomGrassURamp_5_FL','288 324 32 36','mushroom_biome_slopes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom1_1','0 72 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom1_2','32 72 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom1_3','64 72 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom1_4','96 72 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_1','0 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_2','32 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_3','64 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_4','96 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_5','128 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_6','160 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_7','192 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_8','224 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_9','256 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_10','288 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_11','320 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_12','352 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_13','384 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_14','416 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_15','448 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_16','480 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_17','512 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_18','544 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_19','576 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_20','608 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_21','640 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_22','672 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_23','704 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_24','736 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_25','768 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_26','800 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_27','832 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_28','864 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_29','896 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_30','928 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_31','960 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_32','992 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_33','1024 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Mushroom2_34','1056 36 32 36','mushrooms.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYoungBlueFR','0 0 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYoungBlueBL','0 36 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYoungRedFR','0 72 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYoungRedBL','0 108 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYouthBlueFR','0 144 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYouthBlueBL','0 180 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYouthRedFR','0 216 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygYouthRedBL','0 252 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygAdultBlueFR','0 288 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygAdultBlueBL','0 324 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygAdultRedFR','0 360 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygAdultRedBL','0 396 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygSeniorBlueFR','0 432 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygSeniorBlueBL','0 468 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygSeniorRedFR','0 504 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ZygSeniorRedBL','0 540 32 36','mushroom_biome_zygs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Breastplate','992 72 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Helmet','768 252 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherHeadArmor','480 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateRightFootArmorBack','736 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateLeftFootArmorBack','704 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateRightHandArmorBack','672 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateRightArmArmorBack','640 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateLeftHandArmorBack','608 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateLeftArmArmorBack','576 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateChestArmorBack','544 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateHeadArmorBack','480 252 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateRightFootArmor','736 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateLeftFootArmor','704 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateRightHandArmor','608 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateRightArmArmor','576 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateLeftHandArmor','672 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateLeftArmArmor','640 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateChestArmor','544 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeHeavyPlateHeadArmor','480 216 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateRightFootArmorBack','736 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateLeftFootArmorBack','704 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateRightHandArmorBack','672 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateRightArmArmorBack','640 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateLeftHandArmorBack','608 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateLeftArmArmorBack','576 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateChestArmorBack','544 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateHeadArmorBack','480 180 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateRightFootArmor','736 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateLeftFootArmor','704 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateRightHandArmor','608 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateRightArmArmor','576 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateLeftHandArmor','672 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateLeftArmArmor','640 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateChestArmor','544 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomePlateHeadArmor','480 144 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailRightFootArmorBack','736 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailLeftFootArmorBack','704 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailRightHandArmorBack','672 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailRightArmArmorBack','640 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailLeftHandArmorBack','608 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailLeftArmArmorBack','576 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailChestArmorBack','544 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailHeadArmorBack','480 108 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailRightFootArmor','736 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailLeftFootArmor','704 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailRightHandArmor','608 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailRightArmArmor','576 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailLeftHandArmor','672 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailLeftArmArmor','640 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailChestArmor','544 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeChainmailHeadArmor','480 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherRightFootArmorBack','736 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherLeftFootArmorBack','704 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherRightHandArmorBack','672 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherRightArmArmorBack','640 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherLeftHandArmorBack','608 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherLeftArmArmorBack','576 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherChestArmorBack','544 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherHeadArmorBack','480 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherRightFootArmor','736 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherLeftFootArmor','704 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherRightHandArmor','608 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherRightArmArmor','576 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherLeftHandArmor','672 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherLeftArmArmor','640 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeLeatherChestArmor','544 0 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TerrainDummy','0 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlantDummy','288 0 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FlaxPlant','0 468 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FlaxPlantWithFruit','0 504 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherArmorHead','0 0 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherArmorChest','32 0 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherArmorArms','64 0 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherArmorHands','96 0 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherArmorLegs','128 0 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherArmorFeet','160 0 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChainArmorHead','0 36 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChainArmorChest','32 36 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChainArmorArms','64 36 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChainArmorHands','96 36 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChainArmorLegs','128 36 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChainArmorFeet','160 36 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlateArmorHead','0 72 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlateArmorChest','32 72 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlateArmorArms','64 72 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlateArmorHands','96 72 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlateArmorLegs','128 72 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlateArmorFeet','160 72 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HeavyPlateArmorHead','0 108 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HeavyPlateArmorChest','32 108 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HeavyPlateArmorArms','64 108 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HeavyPlateArmorHands','96 108 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HeavyPlateArmorLegs','128 108 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HeavyPlateArmorFeet','160 108 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneArmorHead','0 144 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneArmorChest','32 144 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneArmorArms','64 144 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneArmorLegs','128 144 32 36','weapons_armour.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeSwordRightBackBase','256 360 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeSwordRightBack','256 324 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair1','0 144 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair2','32 108 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair3','64 108 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair4','96 108 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinBeard1','0 180 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinBeard2','32 180 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinBeard3','64 180 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinBeard4','96 180 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinBeard5','128 180 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing1','0 216 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing2','32 216 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing3','64 216 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing4','96 216 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing5','128 216 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinArmLeftBack','128 36 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinArmRightBack','96 36 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinTorsoBack','64 36 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHeadBack','32 36 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinFootLeftBack','96 72 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair1Back','0 144 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair2Back','32 144 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair3Back','64 144 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair4Back','96 144 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing1Back','0 252 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing2Back','32 252 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing3Back','64 252 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing4Back','96 252 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinClothing5Back','128 252 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair5','128 108 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GoblinHair5Back','128 144 32 36','goblin.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampFR','256 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampBR','288 180 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampTopFR','256 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SoilURampTopBR','288 144 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorchLeftBase','384 396 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeTorchLeft','416 396 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WorkshopInputIndicator','512 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepRed','0 432 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepRedBack','0 468 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepGreen','32 432 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepGreenBack','32 468 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepBlue','64 432 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepBlueBack','64 468 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepYellow','96 432 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepYellowBack','96 468 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepPurple','128 432 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepCyan','160 432 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepCyanBack','160 468 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SheepPurpleBack','128 468 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEngineBoilerFR','512 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston1FR','512 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston2FR','512 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston3FR','512 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston4FR','512 144 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEngineBoilerBL','544 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston1BL','544 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston2BL','544 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston3BL','544 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SteamEnginePiston4BL','544 144 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeItem','416 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingItem','288 216 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeWest','320 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipePost','320 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeEast','288 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeNorth','352 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeSouth','384 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeNS','448 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeEW','416 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingNW','352 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingSW','384 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingES','416 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingNE','448 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingNEW','288 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingNSW','320 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingESW','352 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeFittingNES','384 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpBase','480 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpTop1','480 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpTop2','480 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpTop3','480 108 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PumpPipeConnectors','192 252 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree1','0 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree2','32 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree3','64 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree4','96 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree5','128 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree6','160 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree7','192 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree8','224 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree9','256 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree10','288 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree11','320 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree12','352 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree13','384 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree14','416 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree15','448 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree16','480 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree17','512 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree18','544 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree19','576 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BirchTree20','608 288 32 36','multitrees.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpikeTrapItem','0 180 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MechanicalWallOpen','224 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MechanicalWallClosed','256 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonTorsoFR','64 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonRightArmFR','96 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonLeftArmFR','128 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonRightFootFR','160 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonLeftFootFR','192 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonTorsoBR','64 36 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonRightArmBR','128 36 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonLeftArmBR','96 36 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonLeftFootBR','160 36 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonRightFootBR','192 36 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillBaseFL','0 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillBaseBR','32 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillRoofFL','128 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillRoofBR','160 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_1FR','0 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_2FR','64 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_3FR','128 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_1FR','32 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_2FR','96 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_3FR','160 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_1FR','0 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_2FR','64 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_3FR','128 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_1FR','32 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_2FR','96 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_3FR','160 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_1BL','0 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_2BL','64 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_3BL','128 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_1BL','32 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_2BL','96 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_3BL','160 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_1BL','0 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_2BL','64 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_3BL','128 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_1BL','32 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_2BL','96 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_3BL','160 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SlidingWallMechanism','0 360 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SlidingWallWall','32 360 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SlidingWallOpen','0 396 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MechanicalStairRaisedFL','128 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MechanicalStairRaisedBL','160 0 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MechanicalStairLoweredFL','128 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MechanicalStairLoweredBL','160 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PipeUP','448 72 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Valve','416 180 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkullWall','160 360 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SkullWallShort','512 720 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneBedFrameFR','224 324 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneBedFrameBL','224 288 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BoneBedSheetsFR','288 324 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Axle1FR','96 288 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Axle2FR','128 288 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Axle3FR','160 288 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Axle','64 36 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Axle4FR','192 288 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AxleUD1','96 324 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AxleUD2','160 324 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AxleUD3','128 324 32 36','traps_mechanism.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillBase2FL','64 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillBase2BR','96 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_4BL','192 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail1_4FR','192 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_4FR','224 36 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_4FR','192 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_4FR','224 72 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail2_4BL','224 180 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail3_4BL','192 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSail4_4BL','224 216 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_1FR','0 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_2FR','64 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_3FR','128 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_1FR','32 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_2FR','96 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_3FR','160 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_1FR','0 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_2FR','64 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_3FR','128 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_1FR','32 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_2FR','96 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_3FR','160 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_1BL','0 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_2BL','64 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_3BL','128 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_1BL','32 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_2BL','96 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_3BL','160 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_1BL','0 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_2BL','64 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_3BL','128 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_1BL','32 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_2BL','96 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_3BL','160 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_4BL','192 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth1_4FR','192 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_4FR','224 108 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_4FR','192 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_4FR','224 144 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth2_4BL','224 252 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth3_4BL','192 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WindmillSailCloth4_4BL','224 288 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FlourSack','192 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FlourSackPile','224 0 32 36','windmill.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Donkey','416 0 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DonkeyBack','416 36 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DonkeyYoung','416 72 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DonkeyYoungBack','416 108 32 36','animals.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerBodyFR','160 216 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerBodyBR','160 252 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerHeadFR','192 216 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerHeadBR','192 252 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerArmRightFR','224 216 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerArmRightBR','224 252 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerArmLeftFR','256 216 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerArmLeftBR','256 252 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerLegRightFR','288 216 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerLegRightBR','288 252 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerLegLeftFR','320 216 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantWorkerLegLeftBR','320 252 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierBodyFR','224 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierBodyBR','224 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierHeadFR','256 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierHeadBR','256 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierArmRightFR','288 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierArmRightBR','320 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierArmLeftFR','320 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierArmLeftBR','288 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierLegRightFR','384 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierLegRightBR','384 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierLegLeftFR','352 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantSoldierLegLeftBR','352 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenBodyFR','224 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenBodyBR','224 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenHeadFR','256 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenHeadBR','256 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenArmRightFR','288 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenArmRightBR','320 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenArmLeftFR','320 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenArmLeftBR','288 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenLegRightFR','384 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenLegRightBR','384 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenLegLeftFR','352 288 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MantQueenLegLeftBR','352 324 32 36','mobs.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonHeadBR','32 36 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonFurnaceFlameBR','64 72 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonEyeFR','224 0 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL1','0 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL2','32 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL3','64 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL4','96 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL5','128 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL6','160 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL7','192 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL8','224 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL9','256 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL10','288 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL11','320 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL12','352 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL13','384 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL14','416 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL15','448 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL16','480 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL17','512 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR1','0 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR2','32 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR3','64 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR4','96 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR5','128 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR6','160 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR7','192 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR8','224 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR9','256 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR10','288 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR11','320 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR12','352 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR13','384 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR14','416 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR15','448 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR16','480 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR17','512 36 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothFL','512 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MammothBR','512 0 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AutomatonCore','0 72 32 36','automatons.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Straw','288 432 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Hay','256 432 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower1Young','320 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower1','320 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower2Young','352 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower2','352 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower3Young','384 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower3','384 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower4Young','416 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower4','416 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower5Young','448 144 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower5','448 180 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower6Young','320 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower6','320 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower7Young','352 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower7','352 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower8Young','384 252 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Flower8','384 288 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Honey','128 324 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HayBale','128 432 32 36','plants.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BasaltFloor','32 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GraniteFloor','64 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SerpentineFloor','96 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BauxiteFloor','128 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SandstoneFloor','160 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LapisFloor','192 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarbleFloor','224 576 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BasaltWall','32 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GraniteWall','64 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SerpentineWall','96 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BauxiteWall','128 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SandstoneWall','160 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LapisWall','192 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarbleWall','224 612 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchBaseBL','0 468 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchBaseFR','0 504 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame1BL','32 468 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame2BL','64 468 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame3BL','96 468 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame4BL','128 468 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame1FR','32 504 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame2FR','64 504 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame3FR','96 504 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WallTorchFlame4FR','128 504 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Chest','64 36 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BookshelfFR','64 252 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BookshelfBooksFR','64 288 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BookshelfBL','64 324 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BookshelfBooksBL','32 324 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bookshelf2FR','96 252 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bookshelf2BooksFR','96 288 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Bookshelf2BL','96 324 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cabinet2FR','128 252 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Cabinet2BL','128 288 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigTorchBase','224 144 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrazierBase','256 144 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigTorchFlame1','96 72 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigTorchFlame2','128 72 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigTorchFlame3','160 72 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BigTorchFlame4','192 72 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrazierFlame1','192 36 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrazierFlame2','224 36 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrazierFlame3','256 36 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrazierFlame4','288 36 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DresserFR','0 396 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DresserBL','32 396 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth1FL','0 216 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth2FL','32 216 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth1BR','96 216 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth2BR','64 216 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth1FR','0 288 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth2FR','32 288 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth1BL','96 288 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Sabretooth2BL','64 288 32 36','multicreatures.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlarmBellBellItem','384 108 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PlaceHolder','0 0 32 36','default.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('Backpack','352 72 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GnomeBackpackBack','352 36 32 36','gnomes.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SandContainer','96 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassFurnaceFR','128 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassFurnaceBL','160 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassFurnaceFlame1','128 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassFurnaceFlame2','160 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassFurnaceFlame3','192 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassFurnaceFlame4','224 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassIngot','384 0 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassBlock','480 0 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MosaicTile','416 0 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('RoughGlassGem','448 0 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MosaicFloor','448 0 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MosaicWall','448 36 32 36','terrain.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BowsRackFR','64 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BowsRackB','96 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassWorkPipeB','128 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassWorkPipeFR','160 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassIngotStack','192 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TargetBR','96 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TargetFL','64 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('IngotMouldBL','224 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('IngotMouldFR','192 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlchemyVialsFL','320 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodCarverStockBL','384 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('WoodCarverStockFR','352 36 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArrowBucket','64 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MortarAndPestle','288 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlchemyStill','256 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarpenterStock','352 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCarverTableTop','384 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OilMillFL','0 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OilMillBR','0 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('OilStack','32 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperPress','64 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperMakerTableTop','96 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassBottleStack','192 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassPanelStack','224 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlchemyStillFrame4','288 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlchemyStillFrame3','256 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlchemyStillFrame2','320 72 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AlchemyStillFrame1','320 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarpenterTableTopFF','352 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CarpenterTableTopBR','384 108 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PaperRack','64 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CharcoalKilnBL','128 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CharcoalKilnFR','96 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassBlowerStockBL','192 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassBlowerStockFR','160 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawMillTable','288 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SawMillBlade','320 144 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CoalPile','32 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CharcoalKilnFrame4','160 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CharcoalKilnFrame3','128 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CharcoalKilnFrame2','96 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CharcoalKilnFrame1','64 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherCrate','256 180 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyeTableTop','0 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyedClothStack','32 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketStallBR','96 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketStallFR','64 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CartBR','128 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CartFL','128 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('CrateSealed','160 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('HideStack','192 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherSuitFR','224 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherSuitBR','224 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('LeatherSheet','256 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneWorkTools','384 216 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('VatBL','32 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('VatFR','0 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketStallTopBR','96 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketStallTopFR','64 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AnimalStallBL','160 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('AnimalStallFR','160 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TanningVatBL','256 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TanningVatFR','256 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiselMasonFR','320 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ChiselMasonBR','288 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneRubble','352 252 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyeVatBL','32 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('DyeVatFR','0 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StovePanTop','64 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketSackFR','128 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MarketSackBL','96 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoolWood','288 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCarveBL','352 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoneCarveFR','320 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoveBL','96 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoveFR','64 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrewVat','160 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('BrewVatTop','192 324 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KitchenPot','0 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KitchenHearth','32 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('PotTop','64 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoveCookBL','128 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('StoveCookFR','96 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FruitPress','192 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceFlame4','384 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceFlame3','352 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceFlame2','320 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('FurnaceFlame1','288 360 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnFlame4','320 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnFlame3','288 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnFlame2','320 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('KilnFlame1','288 396 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('IngotMouldTop','384 0 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('TailorStand','384 288 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ClothStack','0 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpinningWheelBR','64 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpinningWheelFR','32 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpinningWheelTopBR','64 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SpinningWheelTopFR','32 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArmourSuitBR','128 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ArmourSuitFR','96 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrindStoneTop','160 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GrindStone','192 432 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('ThreadStack','0 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MeatStackFR','192 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SausageStackFR','160 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MeatStackBL','256 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('SausageStackBL','224 468 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MeatGrinderBR','64 504 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('MeatGrinderFL','32 504 32 36','workshops.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIChainmailArmorHead','0 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIChainmailArmorChest','32 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIChainmailArmorArms','64 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIChainmailArmorHands','96 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIChainmailArmorLegs','128 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIChainmailArmorFeet','160 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPlateArmorHead','0 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPlateArmorChest','32 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPlateArmorArms','64 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPlateArmorHands','96 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPlateArmorLegs','128 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPlateArmorFeet','160 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHeavyPlateArmorHead','0 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHeavyPlateArmorChest','32 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHeavyPlateArmorArms','64 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHeavyPlateArmorHands','96 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHeavyPlateArmorLegs','128 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHeavyPlateArmorFeet','160 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UILeatherArmorHead','0 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UILeatherArmorChest','32 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UILeatherArmorArms','64 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UILeatherArmorHands','96 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UILeatherArmorLegs','128 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UILeatherArmorFeet','160 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBoneArmorHead','0 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBoneArmorChest','32 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBoneArmorArms','64 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBoneArmorHands','96 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBoneArmorLegs','128 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBoneArmorFeet','160 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotHead','0 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotChest','32 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotArms','64 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotHands','96 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotLegs','128 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotFeet','160 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotShield','0 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotNeck','32 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotPotion','64 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotRing','96 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotWeapon','128 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIEmptySlotBack','160 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UITorch','160 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIWoodenSword','192 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIWoodenShield','224 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIStoneSwordBlade','256 0 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UISwordBlade','192 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIAxeBlade','224 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIStoneAxeBlade','256 36 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UISwordBase','192 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIAxeBase','224 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UI1','256 72 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIFellingAxeHead','192 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPickaxeHead','224 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UI2','256 108 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIFellingAxeBase','192 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIPickaxeBase','224 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UI3','256 144 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHammerHead','192 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIMetalShield','224 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIStoneHammerHead','256 180 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIHammerBase','192 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UIBow','224 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('UI4','256 216 32 36','weapons-armour-UI-large.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassJar','416 108 32 36','furniture.png');\r\nINSERT INTO \"BaseSprites\" (\"ID\",\"SourceRectangle\",\"Tilesheet\") VALUES ('GlassBottle','480 108 32 36','furniture.png');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawSoil');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawStone');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawWood');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawCoal');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawOre');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawGem');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Bone');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Meat');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Grain');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Milk');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Fruit');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Vegetable');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Leaves');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawCloth');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('RawHide');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Straw');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Berries');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Egg');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Mushroom');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Skull');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('Fish');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('FishMeat');\r\nINSERT INTO \"BaseItems\" (\"ID\") VALUES ('FishBone');\r\nINSERT INTO \"Automaton_Cores_Skills\" (\"ID\",\"SkillID\",\"SkillValue\") VALUES ('AutomatonCoreMark1','Hauling',2000);\r\nINSERT INTO \"Automaton_Cores_Skills\" (\"ID\",\"SkillID\",\"SkillValue\") VALUES ('AutomatonCoreMark2','Hauling',2000);\r\nINSERT INTO \"Automaton_Cores_Skills\" (\"ID\",\"SkillID\",\"SkillValue\") VALUES ('AutomatonCoreMark2','Mining',2000);\r\nINSERT INTO \"Automaton_Cores_Skills\" (\"ID\",\"SkillID\",\"SkillValue\") VALUES ('AutomatonCoreMark2','Woodcutting',2000);\r\nINSERT INTO \"Automaton_Cores\" (\"ID\",\"BehaviorTree\") VALUES ('AutomatonCoreMark1','AutomatonMark1');\r\nINSERT INTO \"Automaton_Cores\" (\"ID\",\"BehaviorTree\") VALUES ('AutomatonCoreMark2','AutomatonMark2');\r\nINSERT INTO \"Attributes\" (\"ID\") VALUES ('Str');\r\nINSERT INTO \"Attributes\" (\"ID\") VALUES ('Dex');\r\nINSERT INTO \"Attributes\" (\"ID\") VALUES ('Con');\r\nINSERT INTO \"Attributes\" (\"ID\") VALUES ('Int');\r\nINSERT INTO \"Attributes\" (\"ID\") VALUES ('Wis');\r\nINSERT INTO \"Attributes\" (\"ID\") VALUES ('Cha');\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('PandaAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('ChickenAdult','EggLayer',NULL,1.0,NULL,1.0,0.0,'Chicken',0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('DuckAdult','EggLayer',NULL,1.0,NULL,1.0,0.0,'Duck',0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GooseAdult','EggLayer',NULL,1.0,NULL,1.0,0.0,'Goose',0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GoatYoung','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,8.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GoatAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,4.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GoatAdult','Producer','female',1.0,NULL,1.0,0.0,NULL,0.0,0.0,'Milk',0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('SheepYoung','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,8.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('SheepAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,4.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('SheepAdult','Producer',NULL,5.0,NULL,10.0,0.0,NULL,0.0,0.0,'RawCloth',0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('BadgerAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('LizzardAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('SquirrelAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('BlackBearAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('LlamaYoung','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,4.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('LlamaAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,2.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('LlamaAdult','Producer',NULL,5.0,NULL,10.0,0.0,NULL,0.0,0.0,'RawCloth',0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('YakYoung','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,2.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('YakAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,1.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('YakAdult','Producer','female',1.0,NULL,1.0,0.0,NULL,0.0,0.0,'Milk',0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('CowYoung','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,2.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('CowAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,1.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('CowAdult','Producer','female',1.0,NULL,1.0,0.0,NULL,0.0,0.0,'Milk',0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('EmuAdult','EggLayer',NULL,1.0,NULL,3.0,0.0,'Emu',0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('SpiderAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('SnakeAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('BeetleEggAdult','Morph',NULL,0.0,'Beetle',0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('BeetleAdult','EggLayer',NULL,3.0,NULL,10.0,0.0,'BeetleEgg',0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('WoodlouseAdult','TreeVermin',NULL,0.0,NULL,0.0,10.0,NULL,0.0,0.1,NULL,1.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GreyFishAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GreenFishAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('CrystalSnakeAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('ZygYoungAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('ZygYouthAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('ZygAdultAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('ZygSeniorAdult','NoneYet',NULL,0.0,NULL,0.0,0.0,NULL,0.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('ChickenAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,10.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('DuckAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,10.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('GooseAdult','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,10.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States_Behavior\" (\"ID\",\"ID2\",\"RequiredGender\",\"Amount\",\"CreatureID\",\"DaysBetween\",\"EatTime\",\"EggID\",\"FoodValue\",\"HungerPerTick\",\"ItemID\",\"Speed\") VALUES ('Rabbit','Grazing',NULL,0.0,NULL,0.0,0.0,NULL,10.0,0.0,NULL,0.0);\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Panda','Adult','Panda',0.0,0,'Animal','false',5,10,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Rabbit','Young','RabbitYoung',3.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Rabbit','Adult','Rabbit',0.0,0,'Animal','false',2,3,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Chicken','Egg','Egg',3.0,1,'Egg','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Chicken','Young','ChickenYoung',3.0,0,'Animal','false',1,1,'BirdSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Chicken','Adult','Chicken',0.0,0,'Animal','false',2,3,'Bird');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Duck','Egg','Egg',3.0,1,'Egg','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Duck','Young','DuckYoung',3.0,0,'Animal','false',1,1,'BirdSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Duck','Adult','Duck',0.0,0,'Animal','false',2,3,'Bird');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Goose','Egg','Egg',3.0,1,'Egg','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Goose','Young','GooseYoung',3.0,0,'Animal','false',1,1,'BirdSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Goose','Adult','Goose',0.0,0,'Animal','false',2,3,'Bird');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Pig','Young','PigYoung',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Pig','Adult','Pig',0.0,0,'Animal','false',4,3,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Shepherd','Young','ShepherdYoung',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Shepherd','Adult','Shepherd',0.0,0,'Animal','false',6,10,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('CatTabby','Young','CatTabby',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('CatTabby','Adult','CatTabby',0.0,0,'Animal','false',3,3,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('CatBlack','Young','CatBlack',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('CatBlack','Adult','CatBlack',0.0,0,'Animal','false',3,3,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Porcupine','Young','Porcupine',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Porcupine','Adult','Porcupine',0.0,0,'Animal','false',5,8,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Fox','Young','Fox',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Fox','Adult','Fox',0.0,0,'AnimalNightHunter','true',4,5,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Wolf','Young','Wolf',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Wolf','Adult','Wolf',0.0,0,'AnimalHunter','true',6,10,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Stag','Young','Stag',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Stag','Adult','Stag',0.0,0,'Animal','false',5,8,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Roe','Young','Roe',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Roe','Adult','Roe',0.0,0,'Animal','false',4,6,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Goat','Young','GoatYoung',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Goat','Adult','Goat',0.0,0,'Animal','false',3,5,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Sheep','Young','SheepYoung',7.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Sheep','Adult','Sheep',0.0,0,'Animal','false',3,4,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Badger','Adult','Badger',0.0,0,'Animal','false',5,10,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Lizzard','Adult','Lizzard',0.0,0,'Animal','false',3,5,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Squirrel','Adult','Squirrel',0.0,0,'Animal','false',2,2,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('BlackBear','Adult','BlackBear',0.0,0,'Animal','false',6,12,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Llama','Young','LlamaYoung',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Llama','Adult','Llama',0.0,0,'Animal','false',4,6,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Yak','Young','YakYoung',10.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Yak','Adult','Yak',0.0,0,'Animal','false',5,9,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Cow','Young','CowYoung',10.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Cow','Adult','Cow',0.0,0,'Animal','false',4,8,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Emu','Egg','Egg',5.0,1,'Egg','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Emu','Young','EmuYoung',5.0,0,'Animal','false',1,1,'Bird');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Emu','Adult','Emu',0.0,0,'Animal','false',5,6,'BirdBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Spider','Adult','Spider',0.0,0,'Animal','false',5,7,'Spider');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Snake','Adult','Snake',0.0,0,'Animal','false',6,7,'Snake');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('BeetleEgg','Egg','Cocoon',10.0,1,'Animal','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('BeetleEgg','Adult','Cocoon',0.0,0,'Animal','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Beetle','Adult','Beetle',0.0,0,'Animal','false',4,6,'Bug');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Woodlouse','Egg','Cocoon',2.0,1,'Animal','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Woodlouse','Adult','Woodlouse',0.0,0,'Animal','false',3,4,'Bug');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('GreyFish','Adult','GreyFish',0.0,0,'Animal','false',1,1,'Fish');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('GreenFish','Adult','GreyFish',0.0,0,'Animal','false',1,1,'Fish');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('CrystalSnake','Adult','CrystalSnake',0.0,0,'Animal','false',6,7,'Snake');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygYoung','Adult','ZygYoung',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygYouth','Adult','ZygYouth',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygAdult','Adult','ZygAdult',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygSenior','Adult','ZygSenior',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Mammoth','Adult','Mammoth',0.0,0,'AnimalBig','false',20,20,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Sabretooth','Adult','Sabretooth',0.0,0,'AnimalBig','true',15,15,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Goat','Adult','Goat',0.0,0,'Animal','false',3,5,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Sheep','Young','SheepYoung',7.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Sheep','Adult','Sheep',0.0,0,'Animal','false',3,4,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Badger','Adult','Badger',0.0,0,'Animal','false',5,10,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Lizzard','Adult','Lizzard',0.0,0,'Animal','false',3,5,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Squirrel','Adult','Squirrel',0.0,0,'Animal','false',2,2,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('BlackBear','Adult','BlackBear',0.0,0,'Animal','false',6,12,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Llama','Young','LlamaYoung',8.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Llama','Adult','Llama',0.0,0,'Animal','false',4,6,'Animal');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Yak','Young','YakYoung',10.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Yak','Adult','Yak',0.0,0,'Animal','false',5,9,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Cow','Young','CowYoung',10.0,0,'Animal','false',1,1,'AnimalSmall');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Cow','Adult','Cow',0.0,0,'Animal','false',4,8,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Emu','Egg','Egg',5.0,1,'Egg','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Emu','Young','EmuYoung',5.0,0,'Animal','false',1,1,'Bird');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Emu','Adult','Emu',0.0,0,'Animal','false',5,6,'BirdBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Spider','Adult','Spider',0.0,0,'Animal','false',5,7,'Spider');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Snake','Adult','Snake',0.0,0,'Animal','false',6,7,'Snake');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('BeetleEgg','Egg','Cocoon',10.0,1,'Animal','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('BeetleEgg','Adult','Cocoon',0.0,0,'Animal','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Beetle','Adult','Beetle',0.0,0,'Animal','false',4,6,'Bug');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Woodlouse','Egg','Cocoon',2.0,1,'Animal','false',0,0,'Egg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Woodlouse','Adult','Woodlouse',0.0,0,'Animal','false',3,4,'Bug');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('GreyFish','Adult','GreyFish',0.0,0,'Animal','false',1,1,'Fish');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('GreenFish','Adult','GreyFish',0.0,0,'Animal','false',1,1,'Fish');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('CrystalSnake','Adult','CrystalSnake',0.0,0,'Animal','false',6,7,'Snake');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygYoung','Adult','ZygYoung',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygYouth','Adult','ZygYouth',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygAdult','Adult','ZygAdult',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('ZygSenior','Adult','ZygSenior',0.0,0,'Animal','false',1,1,'Zyg');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Mammoth','Adult','Mammoth',0.0,0,'AnimalBig','false',20,20,'AnimalBig');\r\nINSERT INTO \"Animals_States\" (\"ID\",\"ID2\",\"SpriteID\",\"DaysToNextState\",\"Immobile\",\"BehaviorTree\",\"IsAggro\",\"Attack\",\"Damage\",\"Anatomy\") VALUES ('Sabretooth','Adult','Sabretooth',0.0,0,'AnimalBig','true',15,15,'AnimalBig');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Panda',4.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Panda',2.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Rabbit',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Chicken',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Duck',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Goose',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Pig',4.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Pig',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Shepherd',2.0,'Meat','Dog');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Shepherd',1.0,'Bone','Dog');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('CatTabby',2.0,'Meat','Cat');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('CatBlack',2.0,'Meat','Cat');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Porcupine',4.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Porcupine',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Fox',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Fox',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Wolf',3.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Wolf',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Stag',4.0,'Meat','Deer');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Stag',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Roe',4.0,'Meat','Deer');\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Roe',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Goat',4.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Goat',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Badger',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Badger',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Sheep',4.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Sheep',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Lizzard',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Squirrel',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('BlackBear',6.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('BlackBear',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Llama',6.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Llama',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Yak',8.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Yak',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Cow',8.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Cow',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Emu',4.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Emu',1.0,'Bone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Spider',3.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Snake',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Beetle',3.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Woodlouse',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('GreyFish',2.0,'FishMeat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('GreyFish',1.0,'FishBone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('GreenFish',2.0,'FishMeat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('GreenFish',1.0,'FishBone',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('CrystalSnake',2.0,'Meat',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Cow',1.0,'RawHide',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Stag',1.0,'RawHide',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Wolf',1.0,'RawHide',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Yak',1.0,'RawHide',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Bear',1.0,'RawHide',NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES (NULL,NULL,NULL,NULL);\r\nINSERT INTO \"Animals_OnButcher\" (\"ID\",\"Amount\",\"ItemID\",\"Type\") VALUES ('Emu',1.0,'RawHide',NULL);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Panda',1,0,'Animal',NULL,0,'Fruit',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Rabbit',1,0,'Animal',NULL,0,'Vegetable',3.0,1,1.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Chicken',0,0,'Animal',NULL,0,'Seed|Grain',0.0,1,1.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Duck',1,0,'Animal',NULL,0,'Seed|Grain',0.0,1,1.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Goose',0,0,'Animal',NULL,0,'Seed|Grain',0.0,1,1.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Pig',0,0,'Animal',NULL,0,'Vegetable|Grain',10.0,1,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Shepherd',0,0,'AnimalGuardDog',NULL,1,'Meat',10.0,0,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('CatTabby',0,0,'Animal',NULL,1,'Meat',10.0,0,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('CatBlack',0,0,'Animal',NULL,1,'Meat',10.0,0,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Porcupine',1,0,'Animal',NULL,0,'Fruit',10.0,0,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Fox',1,0,'AnimalNightHunter',NULL,0,'Meat',10.0,0,2.0,'Chicken|Goose',0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Wolf',1,0,'AnimalHunter',NULL,0,'Meat',10.0,0,2.0,'Rabbit',0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Stag',1,0,'Animal',NULL,0,'Hay|Grain',10.0,0,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Roe',1,0,'Animal',NULL,0,'Hay|Grain',10.0,0,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Goat',1,0,'Animal',NULL,0,'Hay|Grain',10.0,1,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Sheep',0,0,'Animal',NULL,0,'Hay|Grain',9.0,1,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Badger',1,0,'Animal',NULL,0,'Fruit',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Lizzard',1,0,'Animal',NULL,0,'Fruit|Vegetable',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Squirrel',1,0,'Animal',NULL,0,'Fruit',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('BlackBear',1,0,'Animal',NULL,0,'Meat|Fruit',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Llama',0,0,'Animal',NULL,0,'Hay|Grain',8.0,1,3.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Yak',0,0,'Animal',NULL,0,'Hay|Grain',12.0,1,4.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Cow',0,0,'Animal',NULL,0,'Hay|Grain',12.0,1,4.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Emu',0,0,'Animal',NULL,0,'Seed|Grain',0.0,1,2.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Spider',1,0,'Animal',NULL,0,'Meat',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Snake',1,0,'Animal',NULL,0,'Meat',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('BeetleEgg',1,0,'Animal',NULL,0,'none',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Beetle',1,0,'Animal',NULL,0,'Meat|Fruit|Vegetable',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('Woodlouse',1,0,'Animal',NULL,0,'RawWood|Plank',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('GreyFish',1,1,'Animal',NULL,0,'Seed|Grain',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('GreenFish',1,1,'Animal',NULL,0,'Seed|Grain',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('CrystalSnake',1,0,'Animal','Mushroom',0,'none',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('ZygYoung',1,0,'Animal','Mushroom',0,'none',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('ZygYouth',1,0,'Animal','Mushroom',0,'none',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('ZygAdult',1,0,'Animal','Mushroom',0,'none',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Animals\" (\"ID\",\"AllowInWild\",\"Aquatic\",\"BehaviorTree\",\"Biome\",\"Embark\",\"Food\",\"GestationDays\",\"Pasture\",\"PastureSize\",\"Prey\",\"IsMulti\") VALUES ('ZygSenior',1,0,'Animal','Mushroom',0,'none',0.0,0,0.0,NULL,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','Torso',NULL,'false','Middle','Center','Both',50,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','Head','Torso','false','High','Center','Both',50,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','LeftArm','Torso','false','Middle','Left','Both',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','LeftHand','LeftArm','false','Middle','Left','Both',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','RightArm','Torso','false','Middle','Right','Both',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','RightHand','RightArm','false','Middle','Right','Both',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','LeftLeg','Torso','false','Low','Left','Both',40,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','LeftFoot','LeftLeg','false','Low','Left','Both',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','RightLeg','Torso','false','Low','Right','Both',40,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','RightFoot','RightLeg','false','Low','Right','Both',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Humanoid','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','Torso',NULL,'false','Middle','Center','Both',50,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','Head','Torso','false','High','Center','Front',50,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','LeftFrontLeg','Torso','false','Low','Left','Front',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','LeftFrontFoot','LeftFrontLeg','false','Low','Left','Front',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','RightFrontLeg','Torso','false','Low','Right','Front',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','RightFrontFoot','RightFrontLeg','false','Low','Right','Front',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','LeftLeg','Torso','false','Low','Left','Back',40,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','LeftFoot','LeftLeg','false','Low','Left','Back',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','RightLeg','Torso','false','Low','Right','Back',40,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','RightFoot','RightLeg','false','Low','Right','Back',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Animal','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','Torso',NULL,'false','Middle','Center','Both',25,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','Head','Torso','false','High','Center','Front',25,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','LeftFrontLeg','Torso','false','Low','Left','Front',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','LeftFrontFoot','LeftFrontLeg','false','Low','Left','Front',7,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','RightFrontLeg','Torso','false','Low','Right','Front',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','RightFrontFoot','RightFrontLeg','false','Low','Right','Front',7,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','LeftLeg','Torso','false','Low','Left','Back',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','LeftFoot','LeftLeg','false','Low','Left','Back',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','RightLeg','Torso','false','Low','Right','Back',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','RightFoot','RightLeg','false','Low','Right','Back',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalSmall','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','Torso',NULL,'false','Middle','Center','Both',75,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','Head','Torso','false','High','Center','Front',75,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','LeftFrontLeg','Torso','false','Low','Left','Front',45,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','LeftFrontFoot','LeftFrontLeg','false','Low','Left','Front',22,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','RightFrontLeg','Torso','false','Low','Right','Front',45,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','RightFrontFoot','RightFrontLeg','false','Low','Right','Front',22,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','LeftLeg','Torso','false','Low','Left','Back',60,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','LeftFoot','LeftLeg','false','Low','Left','Back',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','RightLeg','Torso','false','Low','Right','Back',60,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','RightFoot','RightLeg','false','Low','Right','Back',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('AnimalBig','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','Torso',NULL,'false','Middle','Center','Both',20,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','Head','Torso','false','High','Center','Front',10,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','LeftWing','Torso','false','Middle','Left','Both',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','RightWing','Torso','false','Middle','Right','Both',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','LeftLeg','Torso','false','Low','Left','Back',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','LeftFoot','LeftLeg','false','Low','Left','Back',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','RightLeg','Torso','false','Low','Right','Back',15,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','RightFoot','RightLeg','false','Low','Right','Back',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Bird','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','Torso',NULL,'false','Middle','Center','Both',10,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','Head','Torso','false','High','Center','Front',5,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','LeftWing','Torso','false','Middle','Left','Both',5,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','RightWing','Torso','false','Middle','Right','Both',5,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','LeftLeg','Torso','false','Low','Left','Back',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','LeftFoot','LeftLeg','false','Low','Left','Back',5,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','RightLeg','Torso','false','Low','Right','Back',10,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','RightFoot','RightLeg','false','Low','Right','Back',5,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdSmall','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','Torso',NULL,'false','Middle','Center','Both',50,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','Head','Torso','false','High','Center','Front',20,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','Brain','Head','true','High','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','LeftEye','Head','false','High','Left','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','RightEye','Head','false','High','Right','Both',1,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','LeftWing','Torso','false','Middle','Left','Both',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','RightWing','Torso','false','Middle','Right','Both',30,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','LeftLeg','Torso','false','Low','Left','Back',40,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','LeftFoot','LeftLeg','false','Low','Left','Back',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','RightLeg','Torso','false','Low','Right','Back',40,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','RightFoot','RightLeg','false','Low','Right','Back',20,0);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','Heart','Torso','true','Middle','Center','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','LeftLung','Torso','true','Middle','Left','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('BirdBig','RightLung','Torso','true','Middle','Right','Both',1,1);\r\nINSERT INTO \"Anatomy_Parts\" (\"ID\",\"ID2\",\"Parent\",\"IsInside\",\"Height\",\"Side\",\"Facing\",\"HP\",\"IsVital\") VALUES ('Dummy','Torso',NULL,'false','Middle','Center','Both',50,1);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Humanoid',5000,'Torso','S|M|B');\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('AnimalSmall',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Animal',3000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('AnimalBig',6000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('BirdSmall',500,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Bird',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('BirdBig',2000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Snake',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Spider',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Bug',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Fish',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Zyg',1000,'Torso',NULL);\r\nINSERT INTO \"Anatomy\" (\"ID\",\"Blood\",\"Root\",\"LayerOrder\") VALUES ('Dummy',1000,'Torso',NULL);\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('Gnome','gnome_standard.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('GnomeTrader','gnome_trader.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('Animal','animal_standard.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AnimalHunter','animal_hunter.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AnimalNightHunter','animal_nighthunter.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AnimalSmallPasture','animal_small_pasture.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('Monster','monster_standard.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AnimalGuardDog','animal_guard_dog.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AutomatonMark1','automaton_mark1.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AutomatonMark2','automaton_mark2.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('MantWorker','monster_mant_worker.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('MantSoldier','monster_mant_soldier.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('MantQueen','monster_mant_queen.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('AnimalBig','animal_big.xml');\r\nINSERT INTO \"AI\" (\"ID\",\"BehaviorTree\") VALUES ('Egg','egg.xml');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('Mine','0 0 0','MiningJobWall',0,'Floor|MineableWall','Construction|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('DigHole','0 0 0','SolidSelectionFloor',0,'Floor','AnyWall|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('DigHole','0 0 -1','MiningJobWall',0,'Floor|Wall','Construction|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ExplorativeMine','0 0 0','MiningJobWall',0,'Floor|Wall','Construction|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('RemoveRamp','0 0 0','MiningJobWall',0,'Ramp',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('RemoveFloor','0 0 0','SolidSelectionFloor',0,'Floor','AnyWall|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('RemovePlant','0 0 0','SelectionWall',0,'Floor|Plant',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('MineStairsUp','0 0 0','Stairs',0,'Floor|Wall','Job|Construction|Plant|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('MineStairsUp','0 0 1','SelectionFloor',0,'Floor','Construction|Job|Designation|Mechanism|Tree');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('DigStairsDown','0 0 0','SelectionFloor',0,'Floor','Job|Construction|Plant|Tree|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('DigStairsDown','0 0 -1','Stairs',0,'Floor|Wall','Construction|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('DigRampDown','0 0 0','SelectionFloor',0,'Floor','AnyWall|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('DigRampDown','0 0 -1','Ramp',1,'Floor|Wall','Construction|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateRoom','0 0 0','SolidSelectionFloor',0,'Floor|Walkable','RampTop|Plant|Tree|Job|Ramp|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateDorm','0 0 0','SolidSelectionFloor',0,'Floor|Walkable','RampTop|Plant|Tree|Job|Ramp|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateDining','0 0 0','SolidSelectionFloor',0,'Floor|Walkable','RampTop|Plant|Tree|Job|Ramp|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateHospital','0 0 0','SolidSelectionFloor',0,'Floor|Walkable','RampTop|Plant|Tree|Job|Ramp|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateStockpile','0 0 0','SolidSelectionFloor',0,'Floor|Walkable','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateGrove','0 0 0','SolidSelectionFloor',0,'Floor|Soil','Wall|Construction|Designation|Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateFarm','0 0 0','SolidSelectionFloor',0,'Floor|Soil|Walkable','Wall|Tree|Construction|Designation|Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreatePasture','0 0 0','SolidSelectionFloor',0,'Floor|Soil|Walkable','Wall|Tree|Construction|Designation|Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CreateNoPass','0 0 0','SolidSelectionFloor',0,NULL,'Designation|Job|Room');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildWall','0 0 0','SolidSelectionWall',0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ReplaceWall','0 0 0','SolidSelectionWall',0,'Floor|Wall','Plant|Tree|Designation|Job|Stairs');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildWallFloor','0 0 0','SelectionWall',0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildWallFloor','0 0 1','SelectionFloor',0,NULL,'Floor|Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildFancyWall','0 0 0',NULL,0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildFloor','0 0 0',NULL,0,NULL,'AnyWall|Floor|RampTop');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildFloor','0 0 -1','none',0,NULL,'Stairs|Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ReplaceFloor','0 0 0','SolidSelectionFloor',0,'Floor','RampTop|Plant|Tree|Job|Ramp|Mechanism|Wall|Stairs');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ReplaceFloor','0 0 -1','none',0,NULL,'Stairs|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildFancyFloor','0 0 0',NULL,0,NULL,'AnyWall|Floor|RampTop');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildFancyFloor','0 0 -1','none',0,NULL,'Stairs|Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildScaffold','0 0 0','Scaffold',0,NULL,'AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildScaffold','0 0 1','none',0,NULL,'Floor|AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildFence','0 0 0','WoodFence',0,'Floor','AnyWall|Designation');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildWorkshop','0 0 0',NULL,0,NULL,NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildStairs','0 0 0','Stairs',0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildStairs','0 0 1','none',0,NULL,'Floor|AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildRamp','0 0 0',NULL,0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildRamp','-1 0 0',NULL,0,'Wall',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildRamp','0 0 1',NULL,0,NULL,'Floor|AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildRampCorner','0 0 0','ThatchOuterCornerRamp',0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CutClipping','0 0 0','SelectionWall',0,'Floor|TreeClip','Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildItem','0 0 0',NULL,0,'$ItemRequirements','$ItemRequirements');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('PlantTree','0 0 0','Sapling',0,'Floor','AnyWall|TreeInRange');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('FellTree','0 0 0','SelectionWall',0,'Floor|Tree','Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('Forage','0 0 0','SelectionWall',0,'PlantWithFruit','Job|Tree');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('HarvestTree','0 0 0','SelectionWall',0,'PlantWithFruit|Tree','Job');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('RemoveDesignation','0 0 0','SolidSelectionFloor',0,'Designation',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('Deconstruct','0 0 0','SelectionWall',0,'Construction',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('CancelJob','0 0 0','SolidSelectionWall',0,'Job',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('RaisePrio','0 0 0','SolidSelectionWall',0,'Job',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('LowerPrio','0 0 0','SolidSelectionWall',0,'Job',NULL);\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('MagicNatureSpeedGrowth','0 0 0','PentagramAnim',0,'Floor','Job|Tree|Wall|Construction');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('MagicGeomancyRevealOre','0 0 0','PentagramAnim',0,'Floor','Job|Tree|Wall|Construction');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildWallPalisade','0 0 0','SolidSelectionWall',0,'Floor','AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('BuildWallPalisade','0 0 1','SolidSelectionWall',0,NULL,'AnyWall|Floor');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ReplaceFancyWall','0 0 0','SolidSelectionWall',0,'Floor|Wall','Plant|Tree|Designation|Job|Stairs');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ReplaceFancyFloor','0 0 0','SolidSelectionFloor',0,'Floor','RampTop|Plant|Tree|Job|Ramp|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('ReplaceFancyFloor','0 0 -1','none',0,NULL,'Stairs|Job|Mechanism');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('FillHole','0 0 0','SelectionFloor',1,NULL,'Floor|AnyWall');\r\nINSERT INTO \"Actions_Tiles\" (\"ID\",\"Offset\",\"SpriteID\",\"IsFloor\",\"Required\",\"Forbidden\") VALUES ('FillHole','0 0 -1','SelectionWall',0,'Floor','AnyWall');\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('Mine','Mine',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('DigHole','DigHole',NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('ExplorativeMine','ExplorativeMine',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('RemoveRamp','RemoveRamp',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('RemoveFloor','RemoveFloor',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('RemovePlant','RemovePlant',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('MineStairsUp','MineStairsUp',NULL,0,0,0,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('DigStairsDown','DigStairsDown',NULL,0,0,0,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('DigRampDown','DigRampDown',NULL,0,0,1,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateRoom',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateDorm',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateDining',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateHospital',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateStockpile',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateGrove',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateFarm',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreatePasture',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CreateNoPass',NULL,NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildWall','BuildWall','Wall',1,0,1,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('ReplaceWall','BuildWall','Wall',1,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildWallFloor','BuildWallFloor','WallFloor',1,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildFancyWall','BuildWall','FancyWall',1,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildFloor','BuildFloor','Floor',1,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('ReplaceFloor','BuildFloor','Floor',1,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildFancyFloor','BuildFloor','FancyFloor',1,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildScaffold','BuildScaffold','Wall',1,0,1,1,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildFence','BuildFence','Wall',1,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildWorkshop','BuildWorkshop','Workshop',1,0,0,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildStairs','BuildStairs','Stairs',1,0,0,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildRamp','BuildRamp','Ramp',1,0,1,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildRampCorner','BuildRampCorner','RampCorner',1,0,1,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CutClipping','CutClipping',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('BuildItem','BuildItem','Item',0,0,0,0,1);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('PlantTree','PlantTree','Tree',0,0,0,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('FellTree','FellTree',NULL,0,0,1,1,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('Forage','Harvest',NULL,0,0,1,1,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('HarvestTree','HarvestTree',NULL,0,0,1,1,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('RemoveDesignation','none',NULL,0,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('Deconstruct','Deconstruct',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('CancelJob','CancelJob',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('RaisePrio','RaisePrio',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('LowerPrio','LowerPrio',NULL,0,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('MagicNatureSpeedGrowth','Magic_Nature_SpeedGrowth',NULL,0,1,0,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('MagicGeomancyRevealOre','Magic_Geomancy_RevealOre',NULL,0,1,0,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('ReplaceFancyWall','BuildWall','Wall',1,0,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('ReplaceFancyFloor','BuildFloor','Floor',1,1,1,0,0);\r\nINSERT INTO \"Actions\" (\"ID\",\"Job\",\"ConstructionType\",\"ConstructionSelect\",\"IsFloor\",\"Multi\",\"MultiZ\",\"Rotate\") VALUES ('FillHole','FillHole','Wall',1,0,1,0,0);\r\n\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('ButtonClick',NULL,'wood1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('actionDrink',NULL,'drink1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('actionEat',NULL,'eat1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('DigStairsDown',NULL,'pickaxe1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('BuildFloor',NULL,'hammering3.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('BuildItem',NULL,'hammering1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('BuildWorkshop',NULL,'hammering3.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('CraftAtWorkshop',NULL,'work1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('CraftAtWorkshop','Plank','saw1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('CraftAtWorkshop','Wine','pour1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('FellTree',NULL,'wood2.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('Harvest',NULL,'prassel1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('HarvestHay',NULL,'prassel1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('Mine',NULL,'pickaxe1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('ExplorativeMine',NULL,'pickaxe1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('PlantFarm',NULL,'sand1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('PlantFarm','Plant','sand1.wav');\r\nINSERT INTO \"Sounds\" (\"ID\",\"Material\",\"SoundFile\") VALUES ('Till',NULL,'sand2.wav');\r\n\r\n\r\nCOMMIT;\r\n"
  },
  {
    "path": "content/shaders/axle_f.glsl",
    "content": "#version 430 core\r\n\r\nlayout(location = 0) noperspective in vec2 vTexCoords;\r\n\r\nlayout(location = 0) out vec4 fColor;\r\n\r\nuniform int uWorldRotation;\r\nuniform int uTickNumber;\r\n\r\nuniform int uSpriteID;\r\nuniform int uRotation;\r\nuniform bool uAnim;\r\n\r\nuniform sampler2DArray uTexture[32];\r\n\r\nvec4 getTexel( uint spriteID, uint rot, uint animFrame )\r\n{\r\n\tuint absoluteId = ( spriteID + animFrame ) * 4;\r\n\tuint tex = absoluteId / 2048;\r\n\tuint localBaseId = absoluteId % 2048;\r\n\tuint localID = localBaseId + rot;\r\n\t\r\n\tivec3 samplePos = ivec3( vTexCoords.x * 32, vTexCoords.y * 64, localID);\r\n\r\n\t// Need to unroll each access to texelFetch with a different element from uTexture into a distinct instruction\r\n\t// Otherwise we are triggering a bug on AMD GPUs, where threads start sampling from the wrong texture\r\n\t#define B(X) case X: return texelFetch( uTexture[X], samplePos, 0);\r\n\t#define C(X) B(X) B(X+1) B(X+2) B(X+3)\r\n\t#define D(X) C(X) C(X+4) C(X+8) C(X+12)\r\n\tswitch(tex)\r\n\t{\r\n\t\tD(0)\r\n\t\tD(16)\r\n\t}\r\n\t#undef D\r\n\t#undef C\r\n\t#undef B\r\n}\r\n\r\nvoid main()\r\n{\r\n\tuint animFrame = 0;\r\n\tif( uAnim )\r\n\t{\r\n\t\tanimFrame = ( uTickNumber / 10 ) % 4;\r\n\t}\r\n\t\r\n\tint rot = ( uRotation + uWorldRotation ) % 4;\r\n\tvec4 texel = vec4(0.0);\r\n\t\r\n\ttexel = getTexel( uSpriteID, rot, animFrame ); // TODO add anim \r\n\t\r\n\tif( length( texel.rgba ) < 0.1 || texel.a < 0.1 ) \r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n\t\r\n\t\r\n\t\r\n\tfColor = texel;\r\n}"
  },
  {
    "path": "content/shaders/axle_v.glsl",
    "content": "#version 430 core\r\n\r\nlayout(location = 0) in vec3 aPos;\r\n\r\nlayout(location = 0) noperspective out vec2 vTexCoords;\r\n\r\nuniform uvec3 uWorldSize;\r\nuniform mat4 uTransform;\r\nuniform int uWorldRotation;\r\nuniform uvec3 uRenderMin;\r\nuniform uvec3 uRenderMax;\r\n\r\nuniform uvec3 tile;\r\n\r\nuvec3 rotate(uvec3 pos)\r\n{\r\n\tuvec3 ret = uvec3(0, 0, pos.z);\r\n\tswitch ( uWorldRotation )\r\n\t{\r\n\t\tdefault:\r\n\t\t\tret.xy = pos.xy;\r\n\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tret.x = uWorldSize.y - pos.y - 1;\r\n\t\t\tret.y = pos.x;\r\n\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tret.x = uWorldSize.x - pos.x - 1;\r\n\t\t\tret.y = uWorldSize.y - pos.y - 1;\r\n\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tret.x = pos.y;\r\n\t\t\tret.y = uWorldSize.x - pos.x - 1;\r\n\t\tbreak;\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\nuvec3 rotateOffset(uvec3 offset)\r\n{\r\n\tswitch ( uWorldRotation )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn offset;\r\n\t\tcase 1:\r\n\t\t\treturn uvec3( -offset.y, offset.x, offset.z );\r\n\t\tcase 2:\r\n\t\t\treturn uvec3( -offset.x, -offset.y, offset.z );\r\n\t\tcase 3:\r\n\t\t\treturn uvec3( offset.y, -offset.y, offset.z );\r\n\t}\r\n}\r\n\r\nvec3 project(uvec3 pos, vec2 offset, bool isWall)\r\n{\r\n\tfloat z = pos.z + pos.x + pos.y;\r\n\treturn vec3(\r\n\t\toffset.x * 32 + 16 * pos.x - 16 * pos.y,\r\n\t\toffset.y * 64 - ( 8 * pos.y + 8 * pos.x ) - ( uRenderMax.z - pos.z ) * 20 - 12,\r\n\t\tisWall ? z + 0.5 : z\r\n\t);\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvTexCoords = vec2( aPos.x, 1.0 - aPos.y );\r\n\r\n\tvec3 worldPos = project( rotate( tile ), aPos.xy, true);\r\n\r\n\tgl_Position = uTransform * vec4( worldPos, 1.0 );\r\n}\r\n"
  },
  {
    "path": "content/shaders/selection_f.glsl",
    "content": "#version 430 core\r\n\r\nlayout(location = 0) noperspective in vec2 vTexCoords;\r\n\r\nlayout(location = 0) out vec4 fColor;\r\n\r\nuniform int uWorldRotation;\r\n\r\nuniform int uSpriteID;\r\nuniform int uRotation;\r\nuniform bool uValid;\r\n\r\nuniform sampler2DArray uTexture[32];\r\n\r\n\r\nvec4 getTexel( uint spriteID, uint rot, uint animFrame )\r\n{\r\n\tuint absoluteId = ( spriteID + animFrame ) * 4;\r\n\tuint tex = absoluteId / 2048;\r\n\tuint localBaseId = absoluteId % 2048;\r\n\tuint localID = localBaseId + rot;\r\n\t\r\n\tivec3 samplePos = ivec3( vTexCoords.x * 32, vTexCoords.y * 64, localID);\r\n\r\n\t// Need to unroll each access to texelFetch with a different element from uTexture into a distinct instruction\r\n\t// Otherwise we are triggering a bug on AMD GPUs, where threads start sampling from the wrong texture\r\n\t#define B(X) case X: return texelFetch( uTexture[X], samplePos, 0);\r\n\t#define C(X) B(X) B(X+1) B(X+2) B(X+3)\r\n\t#define D(X) C(X) C(X+4) C(X+8) C(X+12)\r\n\tswitch(tex)\r\n\t{\r\n\t\tD(0)\r\n\t\tD(16)\r\n\t}\r\n\t#undef D\r\n\t#undef C\r\n\t#undef B\r\n}\r\n\r\nvoid main()\r\n{\r\n\tint rot = ( uRotation + uWorldRotation ) % 4;\r\n\t\r\n\tvec4 texel = vec4(0.0);\r\n\t\r\n\ttexel = getTexel( uSpriteID, rot, 0 );\r\n\t\r\n\t\r\n\t\t\t\r\n\tif( uValid )\r\n\t{\r\n\t\ttexel.r -= 0.6;\r\n\t\t//sTexel.g += 0.1;\r\n\t\ttexel.b -= 0.6;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//sTexel.r += 0.1;\r\n\t\ttexel.g -= 0.6;\r\n\t\ttexel.b -= 0.6;\r\n\t}\r\n\ttexel.a = max( 0.0, texel.a - 0.2 );\r\n\tif( length( texel.rgba ) < 0.1 || texel.a < 0.1 ) \r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n\t\r\n\t\r\n\t\r\n\tfColor = texel;\r\n}"
  },
  {
    "path": "content/shaders/selection_v.glsl",
    "content": "#version 430 core\r\n\r\nlayout(location = 0) in vec3 aPos;\r\n\r\nlayout(location = 0) noperspective out vec2 vTexCoords;\r\n\r\nuniform uvec3 uWorldSize;\r\nuniform mat4 uTransform;\r\nuniform int uWorldRotation;\r\nuniform uvec3 uRenderMin;\r\nuniform uvec3 uRenderMax;\r\n\r\nuniform uvec3 tile;\r\n\r\nuvec3 rotate(uvec3 pos)\r\n{\r\n\tuvec3 ret = uvec3(0, 0, pos.z);\r\n\tswitch ( uWorldRotation )\r\n\t{\r\n\t\tdefault:\r\n\t\t\tret.xy = pos.xy;\r\n\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tret.x = uWorldSize.y - pos.y - 1;\r\n\t\t\tret.y = pos.x;\r\n\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tret.x = uWorldSize.x - pos.x - 1;\r\n\t\t\tret.y = uWorldSize.y - pos.y - 1;\r\n\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tret.x = pos.y;\r\n\t\t\tret.y = uWorldSize.x - pos.x - 1;\r\n\t\tbreak;\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\nuvec3 rotateOffset(uvec3 offset)\r\n{\r\n\tswitch ( uWorldRotation )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn offset;\r\n\t\tcase 1:\r\n\t\t\treturn uvec3( -offset.y, offset.x, offset.z );\r\n\t\tcase 2:\r\n\t\t\treturn uvec3( -offset.x, -offset.y, offset.z );\r\n\t\tcase 3:\r\n\t\t\treturn uvec3( offset.y, -offset.y, offset.z );\r\n\t}\r\n}\r\n\r\nvec3 project(uvec3 pos, vec2 offset, bool isWall)\r\n{\r\n\tfloat z = pos.z + pos.x + pos.y;\r\n\treturn vec3(\r\n\t\toffset.x * 32 + 16 * pos.x - 16 * pos.y,\r\n\t\toffset.y * 64 - ( 8 * pos.y + 8 * pos.x ) - ( uRenderMax.z - pos.z ) * 20 - 12,\r\n\t\tisWall ? z + 0.5 : z\r\n\t);\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvTexCoords = vec2( aPos.x, 1.0 - aPos.y );\r\n\r\n\tvec3 worldPos = project( rotate( tile ), aPos.xy, true);\r\n\r\n\tgl_Position = uTransform * vec4( worldPos, 1.0 );\r\n}\r\n"
  },
  {
    "path": "content/shaders/thoughtbubble_f.glsl",
    "content": "#version 430 core\r\n\r\nlayout(location = 0) noperspective in vec2 vTexCoords;\r\n\r\nlayout(location = 0) out vec4 fColor;\r\n\r\nuniform sampler2DArray uTexture0;\r\n\r\nuniform int uType;\r\n\r\nvoid main()\r\n{\r\n\tvec4 texel = texture( uTexture0, vec3( vTexCoords, uType * 4 ) );\r\n\t\r\n\tif( length( texel.rgba ) < 0.1 || texel.a < 0.1 ) \r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n\tfColor = texel;\r\n}"
  },
  {
    "path": "content/shaders/thoughtbubble_v.glsl",
    "content": "#version 430 core\r\n\r\nlayout(location = 0) in vec3 aPos;\r\n\r\nlayout(location = 0) noperspective out vec2 vTexCoords;\r\n\r\nuniform uvec3 uWorldSize;\r\nuniform mat4 uTransform;\r\nuniform int uWorldRotation;\r\nuniform uvec3 uRenderMin;\r\nuniform uvec3 uRenderMax;\r\n\r\nuniform uvec3 tile;\r\n\r\nuvec3 rotate(uvec3 pos)\r\n{\r\n\tuvec3 ret = uvec3(0, 0, pos.z);\r\n\tswitch ( uWorldRotation )\r\n\t{\r\n\t\tdefault:\r\n\t\t\tret.xy = pos.xy;\r\n\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tret.x = uWorldSize.y - pos.y - 1;\r\n\t\t\tret.y = pos.x;\r\n\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tret.x = uWorldSize.x - pos.x - 1;\r\n\t\t\tret.y = uWorldSize.y - pos.y - 1;\r\n\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tret.x = pos.y;\r\n\t\t\tret.y = uWorldSize.x - pos.x - 1;\r\n\t\tbreak;\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\nuvec3 rotateOffset(uvec3 offset)\r\n{\r\n\tswitch ( uWorldRotation )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn offset;\r\n\t\tcase 1:\r\n\t\t\treturn uvec3( -offset.y, offset.x, offset.z );\r\n\t\tcase 2:\r\n\t\t\treturn uvec3( -offset.x, -offset.y, offset.z );\r\n\t\tcase 3:\r\n\t\t\treturn uvec3( offset.y, -offset.y, offset.z );\r\n\t}\r\n}\r\n\r\nvec3 project(uvec3 pos, vec2 offset, bool isWall)\r\n{\r\n\tfloat z = pos.z + pos.x + pos.y;\r\n\treturn vec3(\r\n\t\toffset.x * 32 + 16 * pos.x - 16 * pos.y,\r\n\t\toffset.y * 64 - ( 8 * pos.y + 8 * pos.x ) - ( uRenderMax.z - pos.z ) * 20 - 12,\r\n\t\tisWall ? z + 0.5 : z\r\n\t);\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvTexCoords = vec2( aPos.x, 1.0 - aPos.y );\r\n\r\n\tvec3 worldPos = project( rotate( tile ), aPos.xy, true);\r\n\r\n\t// Offset relative to owning creature\r\n\tworldPos.x += 8;\r\n\tworldPos.y += 16;\r\n\r\n\tgl_Position = uTransform * vec4( worldPos, 1.0 );\r\n}\r\n"
  },
  {
    "path": "content/shaders/world_f.glsl",
    "content": "#version 430 core\r\n\r\n#define TF_NONE                 0x00000000u\r\n#define TF_WALKABLE             0x00000001u\r\n#define TF_UNDISCOVERED         0x00000002u\r\n#define TF_SUNLIGHT             0x00000004u\r\n#define TF_WET                  0x00000008u\r\n#define TF_GRASS                0x00000010u\r\n#define TF_NOPASS               0x00000020u\r\n#define TF_BLOCKED              0x00000040u\r\n#define TF_DOOR                 0x00000080u\r\n#define TF_STOCKPILE            0x00000100u\r\n#define TF_GROVE                0x00000200u\r\n#define TF_FARM                 0x00000400u\r\n#define TF_TILLED               0x00000800u\r\n#define TF_WORKSHOP             0x00001000u\r\n#define TF_ROOM                 0x00002000u\r\n#define TF_LAVA                 0x00004000u\r\n#define TF_WATER                0x00008000u\r\n#define TF_JOB_FLOOR            0x00010000u\r\n#define TF_JOB_WALL             0x00020000u\r\n#define TF_JOB_BUSY_FLOOR       0x00040000u\r\n#define TF_JOB_BUSY_WALL        0x00080000u\r\n#define TF_MOUSEOVER            0x00100000u\r\n#define TF_WALKABLEANIMALS      0x00200000u\r\n#define TF_WALKABLEMONSTERS     0x00400000u\r\n#define TF_PASTURE              0x00800000u\r\n#define TF_INDIRECT_SUNLIGHT    0x01000000u\r\n#define TF_TRANSPARENT          0x40000000u\r\n#define TF_OVERSIZE             0x80000000u\r\n\r\n#define WATER_TOP               0x01u\r\n#define WATER_EDGE              0x02u\r\n#define WATER_WALL              0x10u\r\n#define WATER_FLOOR             0x20u\r\n#define WATER_ONFLOOR           0x40u\r\n\r\n#define CAT(x, y) CAT_(x, y)\r\n#define CAT_(x, y) x ## y\r\n#define UNPACKSPRITE(alias, src) const uint CAT(alias, ID) = src & 0xffff; const uint CAT(alias, Flags) = src >> 16;\r\nlayout(location = 0) noperspective in vec2 vTexCoords;\r\nlayout(location = 1) flat in uvec4  block1;\r\nlayout(location = 2) flat in uvec4  block2;\r\nlayout(location = 3) flat in uvec4  block3;\r\n\r\nlayout(location = 0) out vec4 fColor;\r\n\r\nuniform sampler2DArray uTexture[32];\r\n\r\nuniform int uTickNumber;\r\n\r\nuniform int uUndiscoveredTex;\r\nuniform int uWaterTex;\r\n\r\nuniform int uWorldRotation;\r\nuniform bool uOverlay;\r\nuniform bool uDebug;\r\nuniform bool uWallsLowered;\r\nuniform float uDaylight;\r\nuniform float uLightMin;\r\nuniform bool uPaintFrontToBack;\r\n\r\nuniform bool uShowJobs;\r\n\r\nconst float waterAlpha = 0.6;\r\nconst float flSize =  ( 1.0 / 32. );\r\nconst int rightWallOffset = 4;\r\nconst int leftWallOffset = 8;\r\n\r\nconst vec3 perceivedBrightness = vec3(0.299, 0.587, 0.114);\r\n\r\nvec4 getTexel( uint spriteID, uint rot, uint animFrame )\r\n{\r\n\tuint absoluteId = ( spriteID + animFrame ) * 4;\r\n\tuint tex = absoluteId / 2048;\r\n\tuint localBaseId = absoluteId % 2048;\r\n\tuint localID = localBaseId + rot;\r\n\t\r\n\tivec3 samplePos = ivec3( vTexCoords.x * 32, vTexCoords.y * 64, localID);\r\n\r\n\t// Need to unroll each access to texelFetch with a different element from uTexture into a distinct instruction\r\n\t// Otherwise we are triggering a bug on AMD GPUs, where threads start sampling from the wrong texture\r\n\t#define B(X) case X: return texelFetch( uTexture[X], samplePos, 0);\r\n\t#define C(X) B(X) B(X+1) B(X+2) B(X+3)\r\n\t#define D(X) C(X) C(X+4) C(X+8) C(X+12)\r\n\tswitch(tex)\r\n\t{\r\n\t\tD(0)\r\n\t\tD(16)\r\n\t}\r\n\t#undef D\r\n\t#undef C\r\n\t#undef B\r\n}\r\n\r\nvoid main()\r\n{\r\n\tvec4 texel = vec4( 0,  0,  0, 0 );\r\n\t\r\n\tuint rot = 0;\r\n\tuint spriteID = 0;\r\n\tuint animFrame = 0;\r\n\t\r\n\tUNPACKSPRITE(floorSprite, block1.x);\r\n\tUNPACKSPRITE(jobFloorSprite, block1.y);\r\n\tUNPACKSPRITE(wallSprite, block1.z);\r\n\tUNPACKSPRITE(jobWallSprite, block1.w);\r\n\tUNPACKSPRITE(itemSprite, block2.x);\r\n\tUNPACKSPRITE(creatureSprite, block2.y);\r\n\r\n\tconst uint vFluidLevelPacked1 = block2.z;\r\n\tconst bool uIsWall = ( block2.w != 0 );\r\n\r\n\tconst uint vFlags = block3.x;\r\n\tconst uint vFlags2 = block3.y;\r\n\r\n\tconst uint vLightLevel = block3.z;\r\n\tconst uint vVegetationLevel = block3.w;\r\n\r\n\tuint vFluidLevel = (vFluidLevelPacked1 >> 0) & 0xff;\r\n\tuint vFluidLevelLeft = (vFluidLevelPacked1 >> 8) & 0xff;\r\n\tuint vFluidLevelRight = (vFluidLevelPacked1 >> 16) & 0xff;\r\n\tuint vFluidFlags = (vFluidLevelPacked1 >> 24) & 0xff;\r\n\r\n\t\r\n\tif( !uIsWall )\r\n\t{\r\n\t\tif( ( vFlags & TF_UNDISCOVERED ) != 0 && !uDebug )\r\n\t\t{\r\n\t\t\tif( !uWallsLowered )\r\n\t\t\t{\r\n\t\t\t\tvec4 tmpTexel = getTexel( uUndiscoveredTex / 4 + 2, 0, 0 );\r\n\r\n\t\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, tmpTexel.a );\r\n\t\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tspriteID = floorSpriteID;\r\n\t\t\tif( spriteID != 0 )\r\n\t\t\t{\r\n\t\t\t\trot = floorSpriteFlags & 3;\r\n\t\t\t\trot = ( rot + uWorldRotation ) % 4;\r\n\t\t\t\t\r\n\t\t\t\tif( ( floorSpriteFlags & 4 ) == 4 )\r\n\t\t\t\t{\r\n\t\t\t\t\tanimFrame = ( uTickNumber / 10 ) % 4;\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\tvec4 tmpTexel = getTexel( spriteID, rot, animFrame );\r\n\t\t\t\t\r\n\t\t\t\tif( ( vFlags & TF_GRASS ) != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tvec4 roughFloor = getTexel( uUndiscoveredTex / 4 + 3, 0, 0 );\r\n\t\t\t\t\tfloat interpol = 1.0 - ( float( vVegetationLevel ) / 100. );\r\n\t\t\t\t\ttmpTexel.rgb = mix( tmpTexel.rgb, roughFloor.rgb, interpol * roughFloor.a );\r\n\t\t\t\t\ttexel.a = max(tmpTexel.a , roughFloor.a);\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, tmpTexel.a );\r\n\t\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tspriteID = jobFloorSpriteID;\r\n\t\t\tanimFrame = 0;\r\n\t\t\tif( uShowJobs && ( spriteID != 0 )  )\r\n\t\t\t{\r\n\t\t\t\trot = jobFloorSpriteFlags & 3;\r\n\t\t\t\trot = ( rot + uWorldRotation ) % 4;\r\n\t\t\t\t\r\n\t\t\t\tvec4 tmpTexel = getTexel( spriteID, rot, animFrame );\r\n\t\t\t\t\r\n\t\t\t\tif( ( vFlags & TF_JOB_BUSY_FLOOR ) != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\ttmpTexel.r *= 0.3;\r\n\t\t\t\t\ttmpTexel.g *= 0.7;\r\n\t\t\t\t\ttmpTexel.b *= 0.3;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttmpTexel.r *= 0.7;\r\n\t\t\t\t\ttmpTexel.g *= 0.7;\r\n\t\t\t\t\ttmpTexel.b *= 0.3;\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexel.rgba = tmpTexel.rgba;\r\n\t\t\t}\r\n\r\n\t\t\tif( uOverlay && 0 != ( vFlags & ( TF_STOCKPILE | TF_FARM | TF_GROVE | TF_PASTURE | TF_WORKSHOP | TF_ROOM | TF_NOPASS ) ) )\r\n\t\t\t{\r\n\t\t\t\tvec3 roomColor = vec3( 0.0 );\r\n\t\t\t\r\n\t\t\t\tif( ( vFlags & TF_STOCKPILE ) != 0 ) //stockpile\r\n\t\t\t\t{\r\n\t\t\t\t\troomColor = vec3(1, 1, 0);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\telse if( ( vFlags & TF_FARM ) != 0 ) //farm\r\n\t\t\t\t{\r\n\t\t\t\t\troomColor = vec3(0.5, 0, 1);\r\n\t\t\t\t}\r\n\t\t\t\telse if( ( vFlags & TF_GROVE ) != 0 ) //grove\r\n\t\t\t\t{\r\n\t\t\t\t\troomColor = vec3(0, 1, 0.5);\r\n\t\t\t\t}\r\n\t\t\t\telse if( ( vFlags & TF_PASTURE ) != 0 ) \r\n\t\t\t\t{\r\n\t\t\t\t\troomColor = vec3(0, 0.9, 0.9);\r\n\t\t\t\t}\r\n\t\t\t\telse if( ( vFlags & TF_WORKSHOP ) != 0 ) //workshop\r\n\t\t\t\t{\r\n\t\t\t\t\tif( ( vFlags & TF_BLOCKED ) != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\troomColor = vec3(1, 0, 0);\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\troomColor = vec3(1, 1, 0);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse if( ( vFlags & TF_ROOM ) != 0 ) //room\r\n\t\t\t\t{\r\n\t\t\t\t\troomColor = vec3(0, 0, 1);\r\n\t\t\t\t}\r\n\t\t\t\telse if( ( vFlags & TF_NOPASS ) != 0 ) //room\r\n\t\t\t\t{\r\n\t\t\t\t\troomColor = vec3(1, 0, 0);\r\n\t\t\t\t}\r\n\t\t\t\tif( texel.a != 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat brightness = dot(texel.rgb, perceivedBrightness.xyz);\r\n\t\t\t\t\t// Preserve perceived brightness of original pixel during tinting, but drop saturation partially\r\n\t\t\t\t\ttexel.rgb = mix( roomColor, mix( texel.rgb, vec3(1,1,1) * brightness, 0.7), 0.7);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t}\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// water related calculations\r\n\t\t//\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\tif( ( vFluidFlags & ( WATER_FLOOR | WATER_EDGE ) ) != 0 )\r\n\t\t{\r\n\t\t\tconst bool renderAboveFloor = ( vFluidFlags & WATER_ONFLOOR ) != 0;\r\n\t\t\tconst int startLevel =  renderAboveFloor ? 2 : int(min(vFluidLevel, 2));\r\n\t\t\tconst int referenceLevel = int(vTexCoords.x < 0.5 ? vFluidLevelLeft : vFluidLevelRight);\r\n\t\t\tconst int offset = vTexCoords.x < 0.5 ? leftWallOffset : rightWallOffset;\r\n\r\n\t\t\tconst float fl = float( startLevel - 2 ) * flSize;\r\n\r\n\t\t\tvec4 tmpTexel = vec4( 0, 0, 0, 0 );\r\n\r\n\t\t\tif( ( vFluidFlags & WATER_FLOOR ) != 0 )\r\n\t\t\t{\r\n\t\t\t\tfloat y = vTexCoords.y + fl;\r\n\t\t\t\ttmpTexel = texture( uTexture[0], vec3( vec2( vTexCoords.x, y ), uWaterTex ) );\r\n\t\t\t}\r\n\r\n\t\t\tif( ( vFluidFlags & WATER_EDGE ) != 0 )\r\n\t\t\t{\r\n\t\t\t\tfloat y = vTexCoords.y + fl;\r\n\t\t\t\tfor(int i = startLevel; i > referenceLevel; --i)\r\n\t\t\t\t{\r\n\t\t\t\t\ty -= flSize;\r\n\t\t\t\t\ttmpTexel += texture( uTexture[0], vec3( vec2( vTexCoords.x, y ), uWaterTex + offset ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Turn into slight tint instead\r\n\t\t\tif( renderAboveFloor && vFluidLevel == 1 )\r\n\t\t\t{\r\n\t\t\t\ttmpTexel.a *= 0.5;\r\n\t\t\t}\r\n\r\n\r\n\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, waterAlpha * tmpTexel.a );\r\n\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t}\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// end water related calculations\r\n\t\t//\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t\r\n\t\t\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( ( vFlags & TF_UNDISCOVERED ) != 0 && !uDebug )\r\n\t\t{\r\n\t\t\tif( !uWallsLowered )\r\n\t\t\t{\r\n\t\t\t\tvec4 tmpTexel = getTexel( uUndiscoveredTex / 4, 0, 0 );\r\n\r\n\t\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, tmpTexel.a );\r\n\t\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tspriteID = wallSpriteID;\r\n\t\t\tif( spriteID != 0 )\r\n\t\t\t{\r\n\t\t\t\trot = wallSpriteFlags & 3;\r\n\t\t\t\trot = ( rot + uWorldRotation ) % 4;\r\n\r\n\t\t\t\tif( ( wallSpriteFlags & 4 ) == 4 )\r\n\t\t\t\t{\r\n\t\t\t\t\tanimFrame = ( uTickNumber / 3 ) % 4;\r\n\t\t\t\t}\r\n\t\t\t\tif( uWallsLowered )\r\n\t\t\t\t{\r\n\t\t\t\t\tanimFrame = 0;\r\n\t\t\t\t\tif( ( wallSpriteFlags & 8 ) == 8 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tspriteID = spriteID + 1;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tvec4 tmpTexel = getTexel( spriteID, rot, animFrame );\r\n\t\t\t\t\r\n\t\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, tmpTexel.a );\r\n\t\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tspriteID = itemSpriteID;\r\n\t\t\tanimFrame = 0;\r\n\t\t\tif( spriteID != 0 )\r\n\t\t\t{\r\n\t\t\t\trot = itemSpriteID & 3;\r\n\t\t\t\trot = ( rot + uWorldRotation ) % 4;\r\n\t\t\t\t\r\n\t\t\t\tvec4 tmpTexel = getTexel( spriteID, rot, animFrame );\r\n\t\t\t\t\r\n\t\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, tmpTexel.a );\r\n\t\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t\t}\r\n\t\t}\r\n\t\r\n\t\tspriteID = jobWallSpriteID;\r\n\t\tanimFrame = 0;\r\n\t\tif( uShowJobs && spriteID != 0 )\r\n\t\t{\r\n\t\t\trot = jobWallSpriteFlags & 3;\r\n\t\t\trot = ( rot + uWorldRotation ) % 4;\r\n\t\t\t\r\n\t\t\tvec4 tmpTexel = getTexel( spriteID, rot, animFrame );\r\n\t\t\t\r\n\t\t\tif( ( vFlags & TF_JOB_BUSY_WALL ) != 0 )\r\n\t\t\t{\r\n\t\t\t\ttmpTexel.r *= 0.3;\r\n\t\t\t\ttmpTexel.g *= 0.7;\r\n\t\t\t\ttmpTexel.b *= 0.3;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttmpTexel.r *= 0.7;\r\n\t\t\t\ttmpTexel.g *= 0.7;\r\n\t\t\t\ttmpTexel.b *= 0.3;\r\n\t\t\t}\r\n\r\n\t\t\ttexel.rgba = tmpTexel.rgba;\r\n\t\t}\r\n\r\n\t\r\n\t\tspriteID = creatureSpriteID;\r\n\t\tanimFrame = 0;\r\n\t\tif( spriteID != 0 )\r\n\t\t{\r\n\t\t\trot = creatureSpriteFlags & 3;\r\n\t\t\trot = ( rot + uWorldRotation ) % 4;\r\n\t\t\t\r\n\t\t\tvec4 tmpTexel = getTexel( spriteID, rot, animFrame );\r\n\t\t\t\r\n\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, tmpTexel.a );\r\n\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t}\r\n\t\t\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// water related calculations\r\n\t\t//\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\tif( ( vFluidFlags & ( WATER_TOP | WATER_WALL ) ) != 0 && vFluidLevel > 2 )\r\n\t\t{\r\n\t\t\tconst int startLevel = int(vFluidLevel - 2);\r\n\t\t\tconst int referenceLevel = int( vTexCoords.x < 0.5 ? max(2, vFluidLevelLeft) : max(2, vFluidLevelRight) ) - 2;\r\n\t\t\tconst int offset = vTexCoords.x < 0.5 ? leftWallOffset : rightWallOffset;\r\n\r\n\t\t\tconst float fl = float( startLevel ) * flSize;\r\n\r\n\t\t\tvec4 tmpTexel = vec4( 0, 0, 0, 0 );\r\n\t\t\t\r\n\t\t\tif( ( vFluidFlags & WATER_TOP ) != 0 )\r\n\t\t\t{\r\n\t\t\t\tfloat y = vTexCoords.y + fl;\r\n\t\t\t\ttmpTexel = texture( uTexture[0], vec3( vec2( vTexCoords.x, y ), uWaterTex ) );\r\n\t\t\t}\r\n\r\n\t\t\tif( ( vFluidFlags & WATER_WALL ) != 0)\r\n\t\t\t{\r\n\t\t\t\tfloat y = vTexCoords.y + fl;\r\n\t\t\t\tfor(int i = startLevel; i > referenceLevel; --i)\r\n\t\t\t\t{\r\n\t\t\t\t\ty -= flSize;\r\n\t\t\t\t\ttmpTexel += texture( uTexture[0], vec3( vec2( vTexCoords.x, y ), uWaterTex + offset ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\ttexel.rgb = mix( texel.rgb, tmpTexel.rgb, waterAlpha * tmpTexel.a );\r\n\t\t\ttexel.a = max(texel.a , tmpTexel.a);\r\n\t\t}\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// end water related calculations\r\n\t\t//\r\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t}\r\n\r\n\tif( texel.a <= 0 )\r\n\t{\r\n\t\tdiscard;\r\n\t}\r\n\telse if(uPaintFrontToBack)\r\n\t{\r\n\t\t// Flush to 1 in case of front-to-back rendering\r\n\t\ttexel.a = 1;\r\n\t}\r\n\t\r\n\t\r\n\tif( !uDebug )\r\n\t{\r\n\t\tfloat light = float( vLightLevel ) / 20.;\r\n\t\tif( ( vFlags & ( TF_SUNLIGHT | TF_INDIRECT_SUNLIGHT ) ) != 0 )\r\n\t\t{\r\n\t\t\tlight = max( light , uDaylight );\r\n\t\t}\r\n\t\tfloat brightness = dot(texel.rgb, perceivedBrightness.xyz);\r\n\t\tfloat lightMult = ( 1 - uLightMin ) * light + uLightMin;\r\n\t\tconst float minSaturation = 0.1;\r\n\t\tfloat saturation = ( 1 - minSaturation ) * light + minSaturation;\r\n\t\t// Desaturate, then darken\r\n\t\ttexel.rgb = mix(brightness * vec3(1,1,1), texel.rgb, saturation) * lightMult;\r\n\t}\r\n\tfColor = texel;\r\n}\r\n"
  },
  {
    "path": "content/shaders/world_v.glsl",
    "content": "#version 430 core\r\n\r\n#define TF_NONE                 0x00000000u\r\n#define TF_WALKABLE             0x00000001u\r\n#define TF_UNDISCOVERED         0x00000002u\r\n#define TF_SUNLIGHT             0x00000004u\r\n#define TF_WET                  0x00000008u\r\n#define TF_GRASS                0x00000010u\r\n#define TF_NOPASS               0x00000020u\r\n#define TF_BLOCKED              0x00000040u\r\n#define TF_DOOR                 0x00000080u\r\n#define TF_STOCKPILE            0x00000100u\r\n#define TF_GROVE                0x00000200u\r\n#define TF_FARM                 0x00000400u\r\n#define TF_TILLED               0x00000800u\r\n#define TF_WORKSHOP             0x00001000u\r\n#define TF_ROOM                 0x00002000u\r\n#define TF_LAVA                 0x00004000u\r\n#define TF_WATER                0x00008000u\r\n#define TF_JOB_FLOOR            0x00010000u\r\n#define TF_JOB_WALL             0x00020000u\r\n#define TF_JOB_BUSY_FLOOR       0x00040000u\r\n#define TF_JOB_BUSY_WALL        0x00080000u\r\n#define TF_MOUSEOVER            0x00100000u\r\n#define TF_WALKABLEANIMALS      0x00200000u\r\n#define TF_WALKABLEMONSTERS     0x00400000u\r\n#define TF_PASTURE              0x00800000u\r\n#define TF_INDIRECT_SUNLIGHT    0x01000000u\r\n#define TF_TRANSPARENT          0x40000000u\r\n#define TF_OVERSIZE             0x80000000u\r\n\r\n#define WATER_TOP               0x01u\r\n#define WATER_EDGE              0x02u\r\n#define WATER_WALL              0x10u\r\n#define WATER_FLOOR             0x20u\r\n#define WATER_ONFLOOR           0x40u\r\n\r\nlayout(location = 0) in vec3 aPos;\r\n\r\nlayout(location = 0) noperspective out vec2 vTexCoords;\r\nlayout(location = 1) flat out uvec4  block1;\r\nlayout(location = 2) flat out uvec4  block2;\r\nlayout(location = 3) flat out uvec4  block3;\r\n\r\nuniform uvec3 uWorldSize;\r\nuniform mat4 uTransform;\r\nuniform int uWorldRotation;\r\nuniform uvec3 uRenderMin;\r\nuniform uvec3 uRenderMax;\r\n\r\n// DO NOT CHANGE, must match game internal layout\r\nstruct TileData {\r\n\t// TF_ flags 0:32\r\n\tuint flags;\r\n\t// TF_ flags 32:64\r\n\tuint flags2;\r\n\r\n\t// Sprites are all:\r\n\t// spriteID=0:16, spriteFlags=16:32\r\n\tuint floorSpriteUID ;\r\n\tuint wallSpriteUID;\r\n\t\r\n\tuint itemSpriteUID;\r\n\tuint creatureSpriteUID;\r\n\r\n\tuint jobSpriteFloorUID;\r\n\tuint jobSpriteWallUID;\r\n\r\n\t// fluidLevel=0:8, lightLevel=0:8, vegetationLevel=8:16\r\n\tuint packedLevels;\r\n};\r\n\r\nlayout(std430, binding = 0) readonly restrict buffer tileData1\r\n{\r\n\tTileData data[];\r\n} tileData;\r\n\r\nuniform bool uWallsLowered;\r\nuniform bool uPaintFrontToBack;\r\n\r\nuvec3 rotate(uvec3 pos)\r\n{\r\n\tuvec3 ret = uvec3(0, 0, pos.z);\r\n\tswitch ( uWorldRotation % 4 )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tret.xy = pos.xy;\r\n\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tret.x = uWorldSize.y - pos.y - 1;\r\n\t\t\tret.y = pos.x;\r\n\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tret.x = uWorldSize.x - pos.x - 1;\r\n\t\t\tret.y = uWorldSize.y - pos.y - 1;\r\n\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tret.x = pos.y;\r\n\t\t\tret.y = uWorldSize.x - pos.x - 1;\r\n\t\tbreak;\r\n\t}\r\n\treturn ret;\r\n}\r\n\r\nuvec3 rotateOffset(uvec3 offset)\r\n{\r\n\tswitch ( uWorldRotation % 4 )\r\n\t{\r\n\t\tdefault:\r\n\t\t\treturn offset;\r\n\t\tcase 1:\r\n\t\t\treturn uvec3( offset.y, -offset.x, offset.z );\r\n\t\tcase 2:\r\n\t\t\treturn uvec3( -offset.x, -offset.y, offset.z );\r\n\t\tcase 3:\r\n\t\t\treturn uvec3( -offset.y, offset.x, offset.z );\r\n\t}\r\n}\r\n\r\nvec3 project(uvec3 pos, vec2 offset, bool isWall)\r\n{\r\n\tfloat z = pos.z + pos.x + pos.y;\r\n\treturn vec3(\r\n\t\toffset.x * 32 + 16 * pos.x - 16 * pos.y,\r\n\t\toffset.y * 64 - ( 8 * pos.y + 8 * pos.x ) - ( uRenderMax.z - pos.z ) * 20 - 12,\r\n\t\tisWall ? z + 0.5 : z\r\n\t);\r\n}\r\n\r\nuint tileID(uvec3 pos)\r\n{\r\n\treturn pos.x + pos.y * uWorldSize.x + pos.z * uWorldSize.x * uWorldSize.y;\r\n}\r\n\r\nvoid main()\r\n{\r\n\tuint id = gl_InstanceID;\r\n\r\n\tconst bool uIsWall = aPos.z != 0;\r\n\r\n\t// Min and max are inclusive in volume\r\n\tconst uvec3 renderVolume = uRenderMax - uRenderMin + uvec3(1, 1, 1);\r\n\r\n\tuint pitchZ = renderVolume.x * renderVolume.y;\r\n\tuint pitchY = renderVolume.x;\r\n\r\n\tuvec3 localIndex;\r\n\tlocalIndex.z = id / pitchZ;\r\n\tid = id % pitchZ;\r\n\tlocalIndex.y = id / pitchY;\r\n\tid = id % pitchY;\r\n\tlocalIndex.x = id;\r\n\r\n\tbool reverseZ = uPaintFrontToBack;\r\n\tbool reverseY = (uWorldRotation == 1 || uWorldRotation == 2) ^^ uPaintFrontToBack;\r\n\tbool reverseX = (uWorldRotation == 2 || uWorldRotation == 3) ^^ uPaintFrontToBack;\r\n\r\n\tuvec3 tile;\r\n\ttile.z = reverseZ ? uRenderMax.z - localIndex.z : uRenderMin.z + localIndex.z;\r\n\ttile.y = reverseY ? uRenderMax.y - localIndex.y : uRenderMin.y + localIndex.y;\r\n\ttile.x = reverseX ? uRenderMax.x - localIndex.x: uRenderMin.x + localIndex.x;\r\n\r\n\tconst uint index = tileID(tile);\r\n\r\n\tuint vFlags = tileData.data[index].flags;\r\n\tuint vFlags2 = tileData.data[index].flags2;\r\n\tuint vLightLevel = ( tileData.data[index].packedLevels >> 8 ) & 0xff;\r\n\tuint vVegetationLevel = ( tileData.data[index].packedLevels >> 16 ) & 0xff;\r\n\r\n\tuint floorSprite = 0;\r\n\tuint wallSprite = 0;\r\n\tuint itemSprite = 0;\r\n\tuint jobFloorSprite = 0;\r\n\tuint jobWallSprite = 0;\r\n\tuint creatureSprite = 0;\r\n\t// Render in first pass if no transparency effects, and in second pass otherwise\r\n\tbool containsTransparency;\r\n\tif( uIsWall )\r\n\t{\r\n\t\tcontainsTransparency = ( vFlags & TF_TRANSPARENT ) != 0 || ( tileData.data[index].packedLevels & 0xff ) >= 3;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcontainsTransparency = ( vFlags & TF_TRANSPARENT ) != 0 || ( tileData.data[index].packedLevels & 0xff ) != 0;\r\n\t}\r\n\tconst bool renderingEnabled = uPaintFrontToBack ^^ containsTransparency;\r\n\tif( renderingEnabled )\r\n\t{\r\n\t\tfloorSprite = tileData.data[index].floorSpriteUID;\r\n\t\twallSprite = tileData.data[index].wallSpriteUID;\r\n\t\titemSprite = tileData.data[index].itemSpriteUID;\r\n\t\tjobFloorSprite = tileData.data[index].jobSpriteFloorUID;\r\n\t\tjobWallSprite = tileData.data[index].jobSpriteWallUID;\r\n\t\tcreatureSprite = tileData.data[index].creatureSpriteUID;\r\n\t}\r\n\t\r\n\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t//\r\n\t// water related calculations\r\n\t//\r\n\t////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\tuint vFluidLevelPacked1 = 0;\r\n\tuint vFluidFlags = 0;\r\n\r\n\tif( !uPaintFrontToBack )\r\n\t{\r\n\t\tconst uvec3 above = uvec3(tile.xy, tile.z + 1);\r\n\t\tconst uvec3 offsetLeft = rotateOffset( uvec3( 0, 1, 0 ) );\r\n\t\tconst uvec3 offsetRight = rotateOffset( uvec3( 1, 0, 0 ) );\r\n\r\n\t\tconst uint indexAbove = tileID( above );\t\t\r\n\t\tconst uint indexL = tileID( tile + offsetLeft );\r\n\t\tconst uint indexR = tileID( tile + offsetRight );\r\n\r\n\t\tconst uint vFluidLevel = tileData.data[index].packedLevels & 0xff;\r\n\r\n\t\tconst uint vFluidLevelAbove = tileData.data[indexAbove].packedLevels & 0xff;\r\n\t\tconst uint vFluidLevelLeft = tileData.data[indexL].packedLevels & 0xff;\r\n\t\tconst uint vFluidLevelRight = tileData.data[indexR].packedLevels & 0xff;\r\n\r\n\t\tif( vFluidLevel >= 3 )\r\n\t\t{\r\n\t\t\tif( vFluidLevel < 10 || tile.z == uRenderMax.z || vFluidLevelAbove == 0 )\r\n\t\t\t{\r\n\t\t\t\tvFluidFlags |= WATER_TOP;\r\n\t\t\t}\r\n\t\t\tif(vFluidLevelLeft < vFluidLevel)\r\n\t\t\t{\r\n\t\t\t\tvFluidFlags |= WATER_WALL;\r\n\t\t\t}\r\n\t\t\tif(vFluidLevelRight < vFluidLevel)\r\n\t\t\t{\r\n\t\t\t\tvFluidFlags |= WATER_WALL;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif( vFluidLevel >= 1 )\r\n\t\t{\r\n\t\t\tif(vFluidLevel <= 2)\r\n\t\t\t{\r\n\t\t\t\tvFluidFlags |= WATER_FLOOR;\r\n\t\t\t\tif(tileData.data[index].floorSpriteUID != 0)\r\n\t\t\t\t{\r\n\t\t\t\t\t// Edge case when water would render \"half height inside floor\"\r\n\t\t\t\t\tvFluidFlags |= WATER_ONFLOOR;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif(vFluidLevelLeft < 2 &&  vFluidLevelLeft < vFluidLevel)\r\n\t\t\t{\r\n\t\t\t\tvFluidFlags |= WATER_EDGE;\r\n\t\t\t}\r\n\t\t\tif(vFluidLevelRight < 2 && vFluidLevelRight < vFluidLevel)\r\n\t\t\t{\r\n\t\t\t\tvFluidFlags |= WATER_EDGE;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvFluidLevelPacked1 = (vFluidLevel << 0) | (vFluidLevelLeft << 8) | (vFluidLevelRight << 16) | (vFluidFlags << 24);\r\n\t}\r\n\r\n\t// Check if rendering is applicable at all for the current tile and rendering pass...\r\n\tif(\r\n\t\t((vFlags & TF_UNDISCOVERED) != 0 && uWallsLowered)\r\n\t\t|| (\r\n\t\t\t!uIsWall\r\n\t\t\t&& floorSprite == 0\r\n\t\t\t&& jobFloorSprite == 0\r\n\t\t\t&& (vFluidFlags & ( WATER_FLOOR | WATER_EDGE )) == 0\r\n\t\t)\r\n\t\t|| (\r\n\t\t\tuIsWall\r\n\t\t\t&& wallSprite == 0\r\n\t\t\t&& jobWallSprite == 0\r\n\t\t\t&& itemSprite == 0\r\n\t\t\t&& creatureSprite == 0\r\n\t\t\t&& ( vFluidFlags & ( WATER_TOP | WATER_WALL ) ) == 0\r\n\t\t)\r\n\t)\r\n\t{\r\n\t\t// ... if not, then skip projection and cull it\r\n\t\tconst float NaN = 1 / 0;\r\n\t\tgl_Position = vec4(NaN, NaN, NaN, NaN);\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvec2 vVertexCoords;\r\n\t\tif( ( vFlags & TF_OVERSIZE ) != 0 )\r\n\t\t{\r\n\t\t\t// Round to full sprite extent, for sprites which are not adhering to regular tile bounding boxes\r\n\t\t\tvVertexCoords.x = floor(aPos.x + 0.5);\r\n\t\t\tvVertexCoords.y = floor(aPos.y + 0.5);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tvVertexCoords = aPos.xy;\r\n\t\t}\r\n\r\n\t\tvTexCoords = vec2( vVertexCoords.x, 1.0 - vVertexCoords.y );\r\n\t\tblock1 = uvec4(floorSprite, jobFloorSprite, wallSprite, jobWallSprite);\r\n\t\tblock2 = uvec4(itemSprite, creatureSprite, vFluidLevelPacked1, uIsWall);\r\n\t\tblock3 = uvec4(vFlags, vFlags2, vLightLevel, vVegetationLevel);\r\n\r\n\t\tvec3 worldPos = project( rotate( tile ), vVertexCoords.xy, uIsWall );\r\n\t\tgl_Position = uTransform * vec4( worldPos, 1.0 );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "content/shaders/worldupdate_c.glsl",
    "content": "#version 430 core\n\n// DO NOT CHANGE, must match game internal layout\nstruct TileData {\n\t// TF_ flags 0:32\n\tuint flags;\n\t// TF_ flags 32:64\n\tuint flags2;\n\n\t// Sprites are all:\n\t// spriteID=0:16, spriteFlags=16:32\n\tuint floorSpriteUID ;\n\tuint wallSpriteUID;\n\t\n\tuint itemSpriteUID;\n\tuint creatureSpriteUID;\n\n\tuint jobSpriteFloorUID;\n\tuint jobSpriteWallUID;\n\n\t// fluidLevel=0:8, lightLevel=0:8, vegetationLevel=8:16\n\tuint packedLevels;\n};\n\nstruct TileDataUpdate {\n\tuint id;\n\tTileData tile;\n};\n\nlayout(std430, binding = 0) writeonly restrict buffer tileData1\n{\n\tTileData data[];\n} tileData;\n\nlayout(std430, binding = 1) readonly restrict buffer tileDataUpdate1\n{\n\tTileDataUpdate data[];\n} tileDataUpdate;\n\nuniform int uUpdateSize;\n\nlayout(local_size_x = 64) in;\n\nvoid main()\n{\n\tuint id = gl_GlobalInvocationID.x;\n\tif(id < uUpdateSize)\n\t{\n\t\tTileDataUpdate data = tileDataUpdate.data[id];\n\t\ttileData.data[data.id] = data.tile;\n\t}\n}\n"
  },
  {
    "path": "content/xaml/Agriculture.xaml",
    "content": "<UserControl\n\tx:Class=\"IngnomiaGUI.Agriculture\"\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\n\tx:Name=\"AgricultureControl\">\n\t<UserControl.DataContext>\n\t\t<local:AgricultureModel />\n\t</UserControl.DataContext>\n\n\t<UserControl.Resources>\n\t\t<ResourceDictionary>\n\t\t\t<ResourceDictionary.MergedDictionaries>\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\n\t\t\t</ResourceDictionary.MergedDictionaries>\n\t\t</ResourceDictionary>\n\t</UserControl.Resources>\n\n\t<Border x:Name=\"MainItemsBorder\" Style=\"{StaticResource Panel}\" MinWidth=\"500\" MinHeight=\"400\">\n\t\t<Grid>\n\t\t\t<StackPanel x:Name=\"TabFarm\" Visibility=\"{Binding ShowFarm}\">\n\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Title}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Height=\"80\" Command=\"{Binding ProductSelection}\" CommandParameter=\"Open\" Grid.Column=\"0\" Margin=\"3\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"{Binding Image}\" />\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<StackPanel Grid.Column=\"1\">\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_TilledPlots}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding Tilled}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_PlantsPlanted}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding Planted}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_CropsReady}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding HarvestReady}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t</StackPanel>\n\t\t\t\t</Grid>\n\n\t\t\t\t<ComboBox x:Name=\"PrioritySelector\" Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t<CheckBox x:Name=\"CBSuspend\" Content=\"{StaticResource Agriculture_Suspend}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\" FontSize=\"16\" />\n\t\t\t\t<CheckBox x:Name=\"CBHarvest\" Content=\"{StaticResource Agriculture_Harvest}\" IsChecked=\"{Binding Harvest, Mode=TwoWay}\" Margin=\"10,5,10,5\" FontSize=\"16\" />\n\t\t\t</StackPanel>\n\n\t\t\t<Grid x:Name=\"TabPlants\" Visibility=\"{Binding ShowPlantSelect}\">\n\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t<RowDefinition Height=\"3*\" />\n\t\t\t\t\t<RowDefinition Height=\"6*\" />\n\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource Agriculture_SelectCrop}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t<Grid Grid.Row=\"1\">\n\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t<Button x:Name=\"PCS\" Style=\"{StaticResource SquareButton}\" Height=\"80\" Command=\"{Binding ProductSelection}\" CommandParameter=\"Close\" Grid.Column=\"0\" Margin=\"3\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"{Binding Image}\" />\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<StackPanel Grid.Column=\"1\">\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_NumberOfSeeds}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumSeeds}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_NumberOfItems}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumItems}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_NumberOfPlants}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumPlants}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t</StackPanel>\n\t\t\t\t</Grid>\n\t\t\t\t<ScrollViewer x:Name=\"PlantSelectScroll\" VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"2\">\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding PlantRows}\" ItemTemplate=\"{StaticResource PlantRowTemplate}\">\n\t\t\t\t\t</ItemsControl>\n\t\t\t\t</ScrollViewer>\n\t\t\t</Grid>\n\n\t\t\t<StackPanel x:Name=\"TabPasture\" Visibility=\"{Binding ShowPasture}\">\n\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Title}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t<StackPanel Grid.Column=\"0\">\n\t\t\t\t\t\t<Button x:Name=\"ACS\" Style=\"{StaticResource SquareButton}\" Height=\"80\" Command=\"{Binding ProductSelection}\" CommandParameter=\"Open\" Margin=\"3\">\n\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t<Image Source=\"{Binding Image}\" />\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t<Button x:Name=\"BManageAnimals\" Width=\"80\" Content=\"{StaticResource Agriculture_Manage}\" Visibility=\"{Binding VisManageAnimals}\" Command=\"{Binding ManageAnimals}\" />\n\t\t\t\t\t</StackPanel>\n\t\t\t\t\t<StackPanel Grid.Column=\"1\">\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" FontSize=\"16\" Text=\"{StaticResource Agriculture_Animals}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock Grid.Column=\"1\" FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumAnimals}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" FontSize=\"16\" Text=\"{StaticResource Agriculture_Male}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock Grid.Column=\"1\" FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumMale}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBox   Grid.Column=\"2\" FontSize=\"16\"  Text=\"{Binding MaxMale}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" FontSize=\"16\" Text=\"{StaticResource Agriculture_Female}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock Grid.Column=\"1\" FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumFemale}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBox   Grid.Column=\"2\" FontSize=\"16\"  Text=\"{Binding MaxFemale}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t</StackPanel>\n\t\t\t\t</Grid>\n\n\t\t\t\t<ComboBox x:Name=\"PrioritySelectorA\" Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t<CheckBox x:Name=\"CBSuspendA\" Content=\"{StaticResource Agriculture_Suspend}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,4,10,4\" FontSize=\"16\" />\n\t\t\t\t<CheckBox x:Name=\"CBTameA\" Content=\"{StaticResource Agriculture_TameWildAnimals}\" IsChecked=\"{Binding Tame, Mode=TwoWay}\" Margin=\"10,4,10,4\" FontSize=\"16\" />\n\t\t\t\t<CheckBox x:Name=\"CBHarvestA\" Content=\"{StaticResource Agriculture_HarvestAnimals}\" IsChecked=\"{Binding Harvest, Mode=TwoWay}\" Margin=\"10,4,10,4\" FontSize=\"16\" />\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t\t\t<CheckBox x:Name=\"CBHarvestHayA\" Content=\"{StaticResource Agriculture_HarvestHay}\" IsChecked=\"{Binding HarvestHay, Mode=TwoWay}\" Margin=\"10,4,10,4\" FontSize=\"16\" MinWidth=\"200\" />\n\t\t\t\t\t<TextBlock Grid.Column=\"0\" FontSize=\"16\" Text=\"{Binding HayStatus}\" TextAlignment=\"Right\" MinWidth=\"100\" Margin=\"10,4,10,4\" />\n\t\t\t\t\t<TextBox  FontSize=\"16\"  Text=\"{Binding MaxHay}\" MinWidth=\"80\" Margin=\"10,4,10,4\" />\n\t\t\t\t</StackPanel>\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t\t\t<TextBlock Grid.Column=\"0\" FontSize=\"16\" Text=\"{StaticResource Agriculture_StoredFood}\" MinWidth=\"200\" Margin=\"10,4,10,4\" />\n\t\t\t\t\t<TextBlock Grid.Column=\"0\" FontSize=\"16\" Text=\"{Binding FoodStatus}\" MinWidth=\"100\" Margin=\"10,4,10,4\" />\n\t\t\t\t\t<Button Width=\"80\" Content=\"{StaticResource Agriculture_Settings}\" Command=\"{Binding CmdShowPastureFood}\" CommandParameter=\"Show\" Margin=\"10,4,10,0\" />\n\t\t\t\t</StackPanel>\n\t\t\t</StackPanel>\n\n\t\t\t<Grid x:Name=\"TabPastureFood\" Visibility=\"{Binding ShowPastureFoodSelect}\">\n\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t<RowDefinition Height=\"8*\" />\n\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"0\">\n\t\t\t\t\t<Button Width=\"80\" Content=\"{StaticResource Agriculture_Back}\" Command=\"{Binding CmdShowPastureFood}\" CommandParameter=\"Back\" />\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource Agriculture_SelectFoodForTroughs}\" Margin=\"10,5,10,5\" />\n\t\t\t\t</StackPanel>\n\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding FoodRows}\" ItemTemplate=\"{StaticResource FoodRowTemplate}\">\n\t\t\t\t\t</ItemsControl>\n\t\t\t\t</ScrollViewer>\n\t\t\t</Grid>\n\n\t\t\t<Grid x:Name=\"TabManageAnimals\" Visibility=\"{Binding ShowManageWindow}\">\n\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t<RowDefinition Height=\"8*\" />\n\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t\t\t<Button x:Name=\"BBackFromManageAnimals\" Width=\"60\" Content=\"{StaticResource Agriculture_Back}\" Command=\"{Binding ManageAnimalsBack}\" />\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource Agriculture_ManageAnimals}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t</StackPanel>\n\t\t\t\t<ScrollViewer x:Name=\"AnimalSelectScroll\" VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding PastureAnimals}\" ItemTemplate=\"{StaticResource PastureAnimalTemplate}\">\n\t\t\t\t\t</ItemsControl>\n\t\t\t\t</ScrollViewer>\n\t\t\t</Grid>\n\n\t\t\t<Grid x:Name=\"TabAnimals\" Visibility=\"{Binding ShowAnimalSelect}\">\n\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t<RowDefinition Height=\"3*\" />\n\t\t\t\t\t<RowDefinition Height=\"6*\" />\n\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource Agriculture_SelectAnimalType}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t<Grid Grid.Row=\"1\">\n\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t<Button x:Name=\"PCSA\" Style=\"{StaticResource SquareButton}\" Height=\"80\" Command=\"{Binding ProductSelection}\" CommandParameter=\"Close\" Grid.Column=\"0\" Margin=\"3\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"{Binding Image}\" />\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<StackPanel Grid.Column=\"1\">\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" Text=\"{StaticResource Agriculture_NumberOfAnimals}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumAnimals}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t</StackPanel>\n\t\t\t\t</Grid>\n\t\t\t\t<ScrollViewer x:Name=\"AnimalSelectScroll2\" VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"2\">\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding AnimalRows}\" ItemTemplate=\"{StaticResource AnimalRowTemplate}\">\n\t\t\t\t\t</ItemsControl>\n\t\t\t\t</ScrollViewer>\n\t\t\t</Grid>\n\n\t\t\t<StackPanel x:Name=\"TabGrove\" Visibility=\"{Binding ShowGrove}\">\n\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Title}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Height=\"80\" Command=\"{Binding ProductSelection}\" CommandParameter=\"Open\" Grid.Column=\"0\" Margin=\"3\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"{Binding Image}\" />\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<StackPanel Grid.Column=\"1\">\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumPlots}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t<TextBlock FontSize=\"16\" TextAlignment=\"Right\" Text=\"{Binding NumPlants}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t\t</Grid>\n\t\t\t\t\t</StackPanel>\n\t\t\t\t</Grid>\n\n\t\t\t\t<ComboBox x:Name=\"PrioritySelectorG\" Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t<CheckBox x:Name=\"CBSuspendT\" Content=\"{StaticResource Agriculture_Suspend}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\" FontSize=\"16\" />\n\t\t\t\t<CheckBox x:Name=\"CBPlantTree\" Content=\"{StaticResource Agriculture_PlantTrees}\" IsChecked=\"{Binding PlantTrees, Mode=TwoWay}\" Margin=\"10,5,10,5\" FontSize=\"16\" />\n\t\t\t\t<CheckBox x:Name=\"CBPickFruit\" Content=\"{StaticResource Agriculture_PickFruit}\" IsChecked=\"{Binding PickFruits, Mode=TwoWay}\" Margin=\"10,5,10,5\" FontSize=\"16\" />\n\t\t\t\t<CheckBox x:Name=\"CBFellTree\" Content=\"{StaticResource Agriculture_FellTrees}\" IsChecked=\"{Binding FellTrees, Mode=TwoWay}\" Margin=\"10,5,10,5\" FontSize=\"16\" />\n\t\t\t</StackPanel>\n\n\t\t\t<Grid x:Name=\"TabTrees\" Visibility=\"{Binding ShowTreeSelect}\">\n\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t<RowDefinition Height=\"3*\" />\n\t\t\t\t\t<RowDefinition Height=\"6*\" />\n\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource Agriculture_SelectTreeType}\" Grid.Row=\"0\" Margin=\"10,5,10,5\" />\n\t\t\t\t<Grid Grid.Row=\"1\">\n\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t<Button x:Name=\"PCST\" Style=\"{StaticResource SquareButton}\" Height=\"80\" Command=\"{Binding ProductSelection}\" CommandParameter=\"Close\" Grid.Column=\"0\" Margin=\"3\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"{Binding Image}\" />\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t</Grid>\n\t\t\t\t<ScrollViewer x:Name=\"TreeSelectScroll\" VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"2\">\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding TreeRows}\" ItemTemplate=\"{StaticResource TreeRowTemplate}\">\n\t\t\t\t\t</ItemsControl>\n\t\t\t\t</ScrollViewer>\n\t\t\t</Grid>\n\t\t</Grid>\n\t</Border>\n</UserControl>"
  },
  {
    "path": "content/xaml/CreatureInfo.xaml",
    "content": "<UserControl\n\tx:Class=\"IngnomiaGUI.CreatureInfo\"\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\n\tx:Name=\"CreatureInfoWindow\">\n\t<UserControl.DataContext>\n\t\t<local:CreatureInfoModel />\n\t</UserControl.DataContext>\n\t<UserControl.Resources>\n\t\t<ResourceDictionary>\n\t\t\t<ResourceDictionary.MergedDictionaries>\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\n\t\t\t</ResourceDictionary.MergedDictionaries>\n\t\t</ResourceDictionary>\n\t</UserControl.Resources>\n\n\t<Grid x:Name=\"LayoutRoot\">\n\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"70\" MaxWidth=\"70\" MinHeight=\"500\" MaxHeight=\"500\" Margin=\"2\">\n\t\t\t\t<StackPanel>\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"1\" Height=\"55\" />\n\n\t\t\t\t\t<!--\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"S\" Height=\"55\"\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\n\t\t\t\t\t\tCommandParameter=\"Schedule\" />\n\t\t\t\t\t-->\n\t\t\t\t</StackPanel>\n\t\t\t</Border>\n\n\t\t\t<Border x:Name=\"TabBorder2\" Style=\"{StaticResource Panel}\" MinWidth=\"440\" MaxWidth=\"440\" MinHeight=\"500\" MaxHeight=\"500\" Margin=\"2\" Padding=\"10\">\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"0\">\n\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" FontWeight=\"Bold\" Text=\"{Binding Name}\" />\n\t\t\t\t\t\t<ComboBox x:Name=\"ProfessionSelector\" Grid.Column=\"1\" VerticalAlignment=\"Center\" Margin=\"8,0,0,0\" MaxHeight=\"28\" HorizontalAlignment=\"Stretch\"  MinWidth=\"180\" MaxWidth=\"180\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Professions}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding Profession, Mode=TwoWay}\"\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource PopProfessionTemplate}\" />\n\t\t\t\t\t</StackPanel>\n\t\t\t\t\t<Grid Grid.Row=\"1\">\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t<Border x:Name=\"LeftPanel\" Style=\"{StaticResource PanelCreatureInfo}\" Grid.Column=\"0\" MinWidth=\"200\" MaxWidth=\"200\" MinHeight=\"470\" MaxHeight=\"500\">\n\n\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t\t</Grid.RowDefinitions>\n\n\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Center\" Text=\"{StaticResource CreatureInfo_Equipment}\" Grid.Row=\"0\" />\n\n\t\t\t\t\t\t\t\t<!-- Uniform doll  -->\n\t\t\t\t\t\t\t\t<Canvas Width=\"180\" Height=\"280\" Grid.Row=\"1\">\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"70\" Canvas.Top=\"20\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgHead}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"70\" Canvas.Top=\"90\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgChest}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"125\" Canvas.Top=\"0\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgBack}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"25\" Canvas.Top=\"0\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgNeck}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"20\" Canvas.Top=\"80\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgArms}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"120\" Canvas.Top=\"80\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgHands}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"20\" Canvas.Top=\"130\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgLRing}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"120\" Canvas.Top=\"130\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgRRing}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"10\" Canvas.Top=\"190\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgRightHand}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"130\" Canvas.Top=\"190\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgLeftHand}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"70\" Canvas.Top=\"185\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgLegs}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"12\" Height=\"40\" Canvas.Left=\"70\" Canvas.Top=\"230\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<Image Source=\"{Binding ImgFeet}\" Stretch=\"Uniform\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</Canvas>\n\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Bottom\"  Text=\"{StaticResource CreatureInfo_Inventory}\" Grid.Row=\"2\" />\n\t\t\t\t\t\t\t\t<Grid Grid.Row=\"3\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Bottom\">\n\t\t\t\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"11\" Grid.Row=\"0\" Grid.Column=\"0\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"12\" Grid.Row=\"0\" Grid.Column=\"1\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"13\" Grid.Row=\"0\" Grid.Column=\"2\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"14\" Grid.Row=\"0\" Grid.Column=\"3\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"21\" Grid.Row=\"1\" Grid.Column=\"0\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"22\" Grid.Row=\"1\" Grid.Column=\"1\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"23\" Grid.Row=\"1\" Grid.Column=\"2\" Height=\"40\" />\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"24\" Grid.Row=\"1\" Grid.Column=\"3\" Height=\"40\" />\n\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t</Border>\n\t\t\t\t\t\t<Border x:Name=\"RightPanel\" Style=\"{StaticResource Panel}\" Grid.Column=\"1\" MinWidth=\"200\" MaxWidth=\"200\" MinHeight=\"470\" MaxHeight=\"500\">\n\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\t\t\t\t\tMinHeight=\"60\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"10\" Text=\"{StaticResource CreatureInfo_Str}\" />\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Str}\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\t\t\t\t\tMinHeight=\"60\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"10\" Text=\"{StaticResource CreatureInfo_Dex}\" />\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Dex}\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\t\t\t\t\tMinHeight=\"60\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"10\" Text=\"{StaticResource CreatureInfo_Con}\" />\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Con}\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</StackPanel>\n\n\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\t\t\t\t\tMinHeight=\"60\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"10\" Text=\"{StaticResource CreatureInfo_Int}\" />\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Int}\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\t\t\t\t\tMinHeight=\"60\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"10\" Text=\"{StaticResource CreatureInfo_Wis}\" />\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Wis}\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\t\t\t\t\tMinHeight=\"60\">\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"10\" Text=\"{StaticResource CreatureInfo_Cha}\" />\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Cha}\" />\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t<ProgressBar x:Name=\"progressBar1\" MinHeight=\"40\" Value=\"{Binding Hunger, Mode=OneWay}\" Maximum=\"100\" Margin=\"4\" Foreground=\"Red\" />\n\t\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{StaticResource CreatureInfo_Hunger}\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Hunger}\" Grid.Column=\"1\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t<ProgressBar x:Name=\"progressBar2\" MinHeight=\"40\" Value=\"{Binding Thirst, Mode=OneWay}\" Maximum=\"100\" Margin=\"4\" />\n\t\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{StaticResource CreatureInfo_Thirst}\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Thirst}\" Grid.Column=\"1\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t<ProgressBar x:Name=\"progressBar3\" MinHeight=\"40\" Value=\"{Binding Sleep, Mode=OneWay}\" Maximum=\"100\" Margin=\"4\" Foreground=\"Green\" />\n\t\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{StaticResource CreatureInfo_Sleep}\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Sleep}\" Grid.Column=\"1\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t<ProgressBar x:Name=\"progressBar4\" MinHeight=\"40\" Value=\"{Binding Happiness, Mode=OneWay}\" Maximum=\"100\" Margin=\"4\" Foreground=\"Purple\" />\n\t\t\t\t\t\t\t\t\t<Grid>\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{StaticResource CreatureInfo_Happiness}\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"20\" Text=\"{Binding Happiness}\" Grid.Column=\"1\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Margin=\"5\" />\n\t\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t</Grid>\n\t\t\t\t\t\t\t\t<TextBlock  FontSize=\"16\" TextWrapping=\"Wrap\" Text=\"{Binding Activity}\" />\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</Border>\n\t\t\t\t\t</Grid>\n\t\t\t\t</Grid>\n\t\t\t</Border>\n\t\t\t<Button Content=\"X\" MaxHeight=\"32\" Margin=\"2\" VerticalAlignment=\"Top\"\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\n\t\t\t\tCommandParameter=\"CreatureWindow\" />\n\t\t</StackPanel>\n\t</Grid>\n</UserControl>"
  },
  {
    "path": "content/xaml/DebugGui.xaml",
    "content": "<UserControl\n\tx:Class=\"IngnomiaGUI.DebugGui\"\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\n\tx:Name=\"DebugControl\">\n\t<UserControl.DataContext>\n\t\t<local:DebugModel />\n\t</UserControl.DataContext>\n\t<UserControl.Resources>\n\t\t<ResourceDictionary>\n\t\t\t<ResourceDictionary.MergedDictionaries>\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\n\t\t\t</ResourceDictionary.MergedDictionaries>\n\t\t</ResourceDictionary>\n\t</UserControl.Resources>\n\n\t<Grid x:Name=\"LayoutRoot\">\n\t\t<StackPanel Orientation=\"Horizontal\">\n\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"100\" Margin=\"2\">\n\t\t\t\t<StackPanel>\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\n\t\t\t\t\t\tCommandParameter=\"First\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"buttons/skills.png\" Stretch=\"None\" />\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource DebugPage_Misc}\"></TextBlock>\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\n\t\t\t\t\t\tCommandParameter=\"Second\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"buttons/schedule.png\" Stretch=\"None\" />\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource DebugPage_Stuff}\"></TextBlock>\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\n\t\t\t\t\t\tCommandParameter=\"Third\">\n\t\t\t\t\t\t<StackPanel>\n\t\t\t\t\t\t\t<Image Source=\"buttons/professions.png\" Stretch=\"None\" />\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource DebugPage_More}\"></TextBlock>\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Button>\n\t\t\t\t</StackPanel>\n\t\t\t</Border>\n\n\t\t\t<Border x:Name=\"TabBorder2\" Style=\"{StaticResource Panel}\" MinWidth=\"1400\" MaxWidth=\"1400\" Margin=\"2\">\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid x:Name=\"LayoutSkills\" Visibility=\"{Binding ShowFirst}\">\n\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource DebugPage_DebugFirstPage}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\n\t\t\t\t\t\t<StackPanel Grid.Row=\"1\" Grid.Column=\"0\">\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource DebugPage_SpawnGnome}\" Command=\"{Binding SpawnCmd}\"\tCommandParameter=\"Gnome\" Margin=\"2\" />\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource DebugPage_SpawnTrader}\" Command=\"{Binding SpawnCmd}\"\tCommandParameter=\"Trader\" Margin=\"2\" />\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource DebugPage_SpawnGoblin}\" Command=\"{Binding SpawnCmd}\"\tCommandParameter=\"Goblin\" Margin=\"2\" />\n\t\t\t\t\t\t\t<ComboBox VerticalAlignment=\"Center\" Margin=\"2\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding WindowSizes}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedWindowSize, Mode=TwoWay}\"\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t</Grid>\n\n\t\t\t\t\t<Grid x:Name=\"LayoutSchedule\" Visibility=\"{Binding ShowSecond}\">\n\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource DebugPage_DebugSecondPage}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\n\t\t\t\t\t</Grid>\n\n\t\t\t\t\t<Grid x:Name=\"LayoutProfEdit\" Visibility=\"{Binding ShowThird}\">\n\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\n\t\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource DebugPage_DebugThirdPage}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\n\t\t\t\t\t</Grid>\n\t\t\t\t</Grid>\n\t\t\t</Border>\n\t\t\t<Button Content=\"X\" MaxHeight=\"32\" Margin=\"2\" VerticalAlignment=\"Top\"\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\n\t\t\t\tCommandParameter=\"DebugWindow\" />\n\t\t</StackPanel>\n\t</Grid>\n</UserControl>"
  },
  {
    "path": "content/xaml/Fonts/SIL Open Font License.txt",
    "content": "Copyright (c) 2009 - 2014 Grand Chaos Productions (http://grandchaos9000.deviantart.com), with Reserved Font Name 8-bit Operator+.\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: http://scripts.sil.org/OFL\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 development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.\r\n\r\nThe OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to 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 Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.\r\n\r\n\"Reserved Font Name\" refers to any names specified as such after the copyright statement(s).\r\n\r\n\"Original Version\" refers to the collection of Font Software components as distributed by the Copyright Holder(s).\r\n\r\n\"Modified Version\" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.\r\n\r\n\"Author\" refers to any designer, engineer, programmer, technical writer 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 a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:\r\n\r\n1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.\r\n\r\n2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary 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 Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.\r\n\r\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.\r\n\r\n5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.\r\n\r\nTERMINATION\r\nThis license becomes null and void if any of the above conditions are not met.\r\n\r\nDISCLAIMER\r\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.\r\n"
  },
  {
    "path": "content/xaml/GameGui.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.GameGui\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tFontFamily=\"Fonts/#8-bit Operator+\"\r\n\tx:Name=\"GameGuiRoot\" Focusable=\"True\" IsTabStop=\"False\" d:DataContext=\"{d:DesignData /SampleData/GameModelSampleData.xaml}\" d:DesignWidth=\"1920\" d:DesignHeight=\"1080\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:GameModel />\r\n\t</UserControl.DataContext>\r\n\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"GameGrid\">\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t<RowDefinition Height=\"*\" />\r\n\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t</Grid.RowDefinitions>\r\n\r\n\t\t<Grid x:Name=\"TopRow\" Grid.Row=\"0\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"15*\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t<Grid x:Name=\"TimeGrid\" Grid.Column=\"0\">\r\n\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t<Border x:Name=\"KingdomControl\" Grid.Row=\"0\" Style=\"{StaticResource Panel}\">\r\n\t\t\t\t\t<Grid x:Name=\"LeftInfoGrid\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<TextBlock Grid.Row=\"0\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding KingdomName}\" />\r\n\t\t\t\t\t\t<TextBlock Grid.Row=\"1\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding KingdomInfo1}\" />\r\n\t\t\t\t\t\t<TextBlock Grid.Row=\"2\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding KingdomInfo2}\" />\r\n\t\t\t\t\t\t<TextBlock Grid.Row=\"3\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding KingdomInfo3}\" />\r\n\t\t\t\t\t\t<TextBlock Grid.Row=\"4\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding Level}\" />\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Border>\r\n\t\t\t\t<Border Grid.Row=\"1\" Style=\"{StaticResource Panel}\">\r\n\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ToggleButton Grid.Column=\"0\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding RenderDesignations}\">\r\n\t\t\t\t\t\t\tD<!--<Image Source=\"buttons/pause.png\" Stretch=\"None\" /> -->\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t\t<ToggleButton Grid.Column=\"1\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding RenderJobs}\">\r\n\t\t\t\t\t\t\tJ<!--<Image Source=\"buttons/slow.png\" Stretch=\"None\" /> -->\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t\t<ToggleButton Grid.Column=\"2\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding RenderWalls}\">\r\n\t\t\t\t\t\t\tW<!--<Image Source=\"buttons/fast.png\" Stretch=\"None\" /> -->\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t\t<ToggleButton Grid.Column=\"3\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding RenderAxles}\">\r\n\t\t\t\t\t\t\tA<!--<Image Source=\"buttons/fast.png\" Stretch=\"None\" /> -->\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Border>\r\n\t\t\t</Grid>\r\n\r\n\t\t\t<Grid x:Name=\"TimeGrid2\" Grid.Column=\"2\">\r\n\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t<Border x:Name=\"TimeControl\" Grid.Row=\"0\" Style=\"{StaticResource Panel}\">\r\n\t\t\t\t\t<Grid x:Name=\"RightInfoGrid\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t<TextBlock Grid.Row=\"0\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding Day}\" />\r\n\t\t\t\t\t\t\t<Button x:Name=\"BDbg\" Content=\"{StaticResource GameGui_D}\" MaxWidth=\"30\" Command=\"{Binding CmdRightCommandButton}\" CommandParameter=\"Debug\">\r\n\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t<Grid Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<Image Grid.Column=\"0\" Source=\"{Binding TimeImagePath}\" />\r\n\t\t\t\t\t\t\t<StackPanel Grid.Column=\"1\">\r\n\t\t\t\t\t\t\t\t<TextBlock FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding Year}\" />\r\n\t\t\t\t\t\t\t\t<TextBlock FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"\" />\r\n\t\t\t\t\t\t\t\t<TextBlock FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding Time}\" />\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t<TextBlock Grid.Row=\"2\"  FontSize=\"14\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" Text=\"{Binding Sun}\" />\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Border>\r\n\t\t\t\t<Border x:Name=\"TimeControl2\" Grid.Row=\"1\" Style=\"{StaticResource Panel}\">\r\n\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB1\" Grid.Column=\"0\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding Paused}\">\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/pause.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB2\" Grid.Column=\"1\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding NormalSpeed}\">\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/slow.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB3\" Grid.Column=\"2\" Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding FastSpeed}\">\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/fast.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t</ToggleButton>\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Border>\r\n\t\t\t</Grid>\r\n\t\t</Grid>\r\n\t\t\r\n\t\t<Grid Grid.Row=\"1\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" >\r\n\t\t\t<ItemsControl ItemsSource=\"{Binding WatchList, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource ItemTemplate16B}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Grid>\r\n\t\t\r\n\t\t\r\n\r\n\t\t<local:StockpileGui x:Name=\"SPGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowStockpile }\" />\r\n\t\t<local:WorkshopGui x:Name=\"WSGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowWorkshop }\" />\r\n\t\t<local:PopulationWindow x:Name=\"PopulationGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowPopulation }\" />\r\n\t\t<local:DebugGui x:Name=\"DebugGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowDebug }\" />\r\n\t\t<local:NeighborsGui x:Name=\"NeighborsGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowNeighbors }\" />\r\n\t\t<local:MilitaryGui x:Name=\"MilitaryGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowMilitary }\" />\r\n\t\t<local:InventoryGui x:Name=\"InventoryGui\" Grid.Row=\"1\" HorizontalAlignment=\"Center\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowInventory }\" />\r\n\r\n\t\t<Grid x:Name=\"LayoutMessage\" MaxHeight=\"400\" VerticalAlignment=\"Center\" Grid.Row=\"1\" Visibility=\"{Binding ShowMessage}\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t<Border Grid.Column=\"1\" Style=\"{StaticResource Panel}\" MinWidth=\"70\" MaxWidth=\"70\" HorizontalAlignment=\"Right\">\r\n\t\t\t</Border>\r\n\r\n\t\t\t<Border Grid.Column=\"2\" Style=\"{StaticResource Panel}\" MinWidth=\"500\" MaxWidth=\"500\" MinHeight=\"300\" MaxHeight=\"300\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding MessageHeader}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" FontSize=\"20\" FontWeight=\"Bold\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<TextBlock VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"1\" TextWrapping=\"Wrap\"\r\n\t\t\t\t\t\tText=\"{Binding MessageText}\" />\r\n\r\n\t\t\t\t\t<Grid Grid.Row=\"2\" VerticalAlignment=\"Bottom\">\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<Button Grid.Column=\"0\" Content=\"{StaticResource GameGui_Yes}\" Command=\"{Binding MessageCmd}\" MinWidth=\"100\" CommandParameter=\"yes\" Visibility=\"{Binding ShowMessageButtonYesNo}\" />\r\n\t\t\t\t\t\t<Button Grid.Column=\"1\" Content=\"{StaticResource GameGui_Ok}\"  Command=\"{Binding MessageCmd}\" MinWidth=\"100\" CommandParameter=\"ok\" Visibility=\"{Binding ShowMessageButtonOk}\" />\r\n\t\t\t\t\t\t<Button Grid.Column=\"2\" Content=\"{StaticResource GameGui_No}\"  Command=\"{Binding MessageCmd}\" MinWidth=\"100\" CommandParameter=\"no\" Visibility=\"{Binding ShowMessageButtonYesNo}\" />\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<!--\r\n\t\t\t<Button Content=\"X\" MaxHeight=\"32\" MaxWidth=\"32\" Margin=\"2\" VerticalAlignment=\"Top\" HorizontalAlignment=\"Left\" Grid.Column=\"3\"\r\n\t\t\t\tCommand=\"{Binding CloseMessageWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"PopWindow\"\r\n\t\t\t/> -->\r\n\t\t</Grid>\r\n\r\n\t\t<Grid x:Name=\"MiddleRow\"  Grid.Row=\"1\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t<ColumnDefinition Width=\"10*\" />\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t<RowDefinition Height=\"*\" />\r\n\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t<Border x:Name=\"CommandButtonBorder\" Grid.Column=\"0\" Style=\"{StaticResource Panel}\" Visibility=\"{Binding ShowCommandButtons}\" VerticalAlignment=\"Bottom\">\r\n\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\">\r\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding CommandButtons}\" ItemTemplate=\"{StaticResource CommandButtonTemplate}\">\r\n\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t</ScrollViewer>\r\n\t\t\t</Border>\r\n\r\n\t\t\t<Border x:Name=\"CategoryButtonBorder\" Grid.Column=\"1\" Style=\"{StaticResource Panel}\" Visibility=\"{Binding ShowCategoryButtons}\">\r\n\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\">\r\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding BuildButtons}\" ItemTemplate=\"{StaticResource BuildButtonsItemTemplate}\">\r\n\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t</ScrollViewer>\r\n\t\t\t</Border>\r\n\t\t\t<Border x:Name=\"BuildItemsBorder\"  Grid.Column=\"2\" Style=\"{StaticResource Panel}\" Visibility=\"{Binding ShowCategoryButtons}\">\r\n\t\t\t\t<ScrollViewer x:Name=\"BuildItemScroll\" VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\">\r\n\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding BuildItems}\" ItemTemplate=\"{StaticResource BuildItemTemplate}\" />\r\n\t\t\t\t</ScrollViewer>\r\n\t\t\t</Border>\r\n\r\n\t\t\t<local:TileInfo x:Name=\"TileInfo\" Grid.Column=\"4\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowTileInfo }\" HorizontalAlignment=\"Right\" />\r\n\r\n\t\t\t<local:CreatureInfo x:Name=\"CreatureInfo\"\r\n\t\t\t\tGrid.Column=\"4\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Bottom\"\r\n\t\t\t\tVisibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowCreatureInfo }\" />\r\n\t\t</Grid>\r\n\r\n\t\t<Viewbox Grid.Row=\"2\" StretchDirection=\"DownOnly\">\r\n\t\t\t<Grid x:Name=\"BottomRow\" MinWidth=\"{Binding ActualWidth, ElementName=GameGuiRoot}\">\r\n\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t<Border x:Name=\"LeftButtonBorder\" Grid.Column=\"0\" Style=\"{StaticResource Panel}\">\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t<Button x:Name=\"LCB2\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\t\t\tCommand=\"{Binding CmdLeftCommandButton}\" CommandParameter=\"Build\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/build-all.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Build}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"LCB1\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\t\t\tCommand=\"{Binding CmdLeftCommandButton}\" CommandParameter=\"Mine\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/mine.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Mine}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"LCB3\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\t\t\tCommand=\"{Binding CmdLeftCommandButton}\" CommandParameter=\"Agri\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/agriculture.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Agriculture}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"LCB4\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\t\t\tCommand=\"{Binding CmdLeftCommandButton}\" CommandParameter=\"Designation\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/designation.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Designations}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"LCB5\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\t\t\tCommand=\"{Binding CmdLeftCommandButton}\" CommandParameter=\"Job\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/jobs.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Job}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"LCB6\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\t\t\tCommand=\"{Binding CmdLeftCommandButton}\" CommandParameter=\"Magic\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/magic.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Magic}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</Border>\r\n\t\t\t\t<local:SelectionGui x:Name=\"SelectionGui\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowSelection }\" />\r\n\t\t\t\t<Border x:Name=\"RightButtonBorder\" Grid.Column=\"3\" Style=\"{StaticResource Panel}\">\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t<Button x:Name=\"RCB2\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding CmdRightCommandButton}\" CommandParameter=\"Kingdom\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/kingdom.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Kingdom}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"RCB1\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding CmdRightCommandButton}\" CommandParameter=\"Inventory\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/stockpile.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Stockpiles}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"RCB3\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding CmdRightCommandButton}\" CommandParameter=\"Military\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/military.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Military}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"RCB4\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding CmdRightCommandButton}\" CommandParameter=\"Population\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/population.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Population}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button x:Name=\"RCB5\" Style=\"{StaticResource CommandButton}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding CmdRightCommandButton}\" CommandParameter=\"Missions\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/mission.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<Viewbox MaxHeight=\"20\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource GameGui_Missions}\" />\r\n\t\t\t\t\t\t\t\t</Viewbox>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</Border>\r\n\t\t\t</Grid>\r\n\t\t</Viewbox>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/IngamePage.xaml",
    "content": "﻿<UserControl\r\n\tx:Class=\"IngnomiaGUI.IngamePage\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\tx:Name=\"IngameMenuControl\">\r\n\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/pageswap.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" RenderTransformOrigin=\"0.5,0.5\">\r\n\r\n\t\t<i:Interaction.Triggers>\r\n\t\t\t<ei:StoryboardCompletedTrigger Storyboard=\"{StaticResource FadeInIngame}\">\r\n\t\t\t\t<noesis:SetFocusAction TargetName=\"IMResume\" />\r\n\t\t\t</ei:StoryboardCompletedTrigger>\r\n\t\t</i:Interaction.Triggers>\r\n\r\n\t\t<Grid.RenderTransform>\r\n\t\t\t<TransformGroup>\r\n\t\t\t\t<ScaleTransform ScaleX=\"1\" ScaleY=\"1\" />\r\n\t\t\t\t<SkewTransform />\r\n\t\t\t\t<RotateTransform />\r\n\t\t\t\t<TranslateTransform X=\"0\" Y=\"0\" />\r\n\t\t\t</TransformGroup>\r\n\t\t</Grid.RenderTransform>\r\n\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t<RowDefinition Height=\"9*\" />\r\n\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t<TextBlock Grid.Row=\"0\" Grid.Column=\"1\" FontSize=\"100\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource InGamePage_Ingnomia}\" />\r\n\r\n\t\t<Viewbox Grid.Row=\"1\" Grid.Column=\"1\" StretchDirection=\"DownOnly\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Button x:Name=\"IMResume\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource InGamePage_Resume}\" Command=\"{Binding Resume}\" />\r\n\t\t\t\t<Button x:Name=\"IMLoadGame\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource InGamePage_LoadGame}\" Command=\"{Binding LoadGame}\" />\r\n\t\t\t\t<Button x:Name=\"IMSaveGame\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource InGamePage_SaveGame}\" Command=\"{Binding SaveGame}\" />\r\n\t\t\t\t<Button x:Name=\"IMSettings\"    Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource InGamePage_Settings}\" Command=\"{Binding Settings}\" />\r\n\t\t\t\t<Button x:Name=\"IMQuit\"      Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource InGamePage_QuitGame}\" Command=\"{Binding BackToMain}\" />\r\n\t\t\t</StackPanel>\r\n\t\t</Viewbox>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/InventoryGui.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.InventoryGui\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"InventoryControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:InventoryModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid MinHeight=\"700\" MaxHeight=\"700\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<Border Style=\"{StaticResource Panel}\" MinWidth=\"100\" Margin=\"2\">\r\n\t\t\t</Border>\r\n\r\n\t\t\t<Border Style=\"{StaticResource Panel}\" MinWidth=\"1400\" MaxWidth=\"1400\" Margin=\"2\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding Categories, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource InvCategoryTemplate}\">\r\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"InventoryWindow\">\r\n\t\t\t\t<Image Source=\"buttons/cross.png\" />\r\n\t\t\t</Button>\r\n\t\t\t\r\n\t\t</StackPanel>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/LoadGamePage.xaml",
    "content": "﻿<UserControl\r\n\tx:Class=\"IngnomiaGUI.LoadGamePage\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"LoadGameMenuControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:LoadGameModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" RenderTransformOrigin=\"0.5,0.5\">\r\n\t\t<Grid.RenderTransform>\r\n\t\t\t<TransformGroup>\r\n\t\t\t\t<ScaleTransform ScaleX=\"1\" ScaleY=\"1\" />\r\n\t\t\t\t<SkewTransform />\r\n\t\t\t\t<RotateTransform />\r\n\t\t\t\t<TranslateTransform X=\"0\" Y=\"0\" />\r\n\t\t\t</TransformGroup>\r\n\t\t</Grid.RenderTransform>\r\n\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t<RowDefinition Height=\"9*\" />\r\n\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t<Viewbox Grid.Row=\"0\" Grid.Column=\"1\">\r\n\t\t\t<TextBlock FontSize=\"10\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource LoadGamePage_LoadGame}\" />\r\n\t\t</Viewbox>\r\n\r\n\t\t<Grid Grid.Row=\"1\" Grid.Column=\"1\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"2*\" />\r\n\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<ListBox x:Name=\"LBLoadKingdoms\" Grid.Column=\"0\"\r\n\t\t\t\tItemsSource=\"{Binding SavedKingdoms}\"\r\n\t\t\t\tSelectedItem=\"{Binding SelectedKingdom, Mode=TwoWay}\"\r\n\t\t\t\tItemTemplate=\"{StaticResource SavedKingdomTemplate}\" />\r\n\t\t\t<Grid Grid.Column=\"1\">\r\n\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t<RowDefinition Height=\"3*\" />\r\n\t\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t\t<Grid Grid.Row=\"0\">\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"*\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" Grid.Row=\"0\">\r\n\t\t\t\t\t\t<TextBlock FontSize=\"20\" Text=\"{StaticResource LoadGamePage_HereSelectedGameInfo}\" TextWrapping=\"Wrap\" Margin=\"5\" />\r\n\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t<Button x:Name=\"BuLoadGame\" FontSize=\"20\" Content=\"{StaticResource LoadGamePage_Load}\" Margin=\"5\" Grid.Row=\"1\" Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainMenu}}, Path=DataContext.ContinueGame }\" CommandParameter=\"{Binding SelectedGame.Path}\" />\r\n\t\t\t\t</Grid>\r\n\r\n\t\t\t\t<ListBox x:Name=\"LBLoadGames\" Grid.Row=\"1\"\r\n\t\t\t\t\tItemsSource=\"{Binding SavedGames}\"\r\n\t\t\t\t\tSelectedItem=\"{Binding SelectedGame, Mode=TwoWay}\"\r\n\t\t\t\t\tItemTemplate=\"{StaticResource SavedKingdomTemplate}\" />\r\n\t\t\t</Grid>\r\n\t\t</Grid>\r\n\r\n\t\t<Button Grid.Row=\"2\" Grid.Column=\"1\" x:Name=\"Back\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource LoadGamePage_Back}\" Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainMenu}}, Path=DataContext.Back }\" />\r\n\t\t<TextBlock x:Name=\"SettingsDescription\" />\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/Main.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.Main\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"MainControl\" Focusable=\"True\" IsTabStop=\"False\" d:DataContext=\"{d:DesignData /SampleData/ViewModelSampleData.xaml}\" d:DesignWidth=\"1920\" d:DesignHeight=\"1080\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:ViewModel />\r\n\t</UserControl.DataContext>\r\n\r\n\t<Grid>\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\t\t<Viewbox Visibility=\"{Binding ShowMainMenu}\">\r\n\t\t\t<local:MainMenu x:Name=\"MainMenu\" Grid.Row=\"1\" Grid.Column=\"1\" Width=\"{Binding RelativeSource={RelativeSource FindAncestor,\r\nAncestorType=UserControl}, Path=DataContext.WindowWidth}\" Height=\"{Binding RelativeSource={RelativeSource FindAncestor,\r\nAncestorType=UserControl}, Path=DataContext.WindowHeight}\" />\r\n\t\t</Viewbox>\r\n\t\t<Viewbox Visibility=\"{Binding ShowGameGUI}\">\r\n\t\t\t<local:GameGui x:Name=\"GameGui\" Grid.Row=\"1\" Grid.Column=\"1\" Width=\"{Binding RelativeSource={RelativeSource FindAncestor,\r\nAncestorType=UserControl}, Path=DataContext.WindowWidth}\" Height=\"{Binding RelativeSource={RelativeSource FindAncestor,\r\nAncestorType=UserControl}, Path=DataContext.WindowHeight}\" />\r\n\t\t</Viewbox>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/MainMenu.xaml",
    "content": "﻿<UserControl\r\n\tx:Class=\"IngnomiaGUI.MainMenu\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tFontFamily=\"Fonts/#8-bit Operator+\"\r\n\tx:Name=\"MainMenuControl\" Focusable=\"True\" IsTabStop=\"False\">\r\n\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/pageswap.xaml\" />\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\t<i:Interaction.Triggers>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Value=\"{x:Static local:State.NewGame}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeInNewGame}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Comparison=\"NotEqual\" Value=\"{x:Static local:State.NewGame}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeOutNewGame}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Value=\"{x:Static local:State.LoadGame}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeInLoadGame}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Comparison=\"NotEqual\" Value=\"{x:Static local:State.LoadGame}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeOutLoadGame}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Value=\"{x:Static local:State.Settings}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeInSettings}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Comparison=\"NotEqual\" Value=\"{x:Static local:State.Settings}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeOutSettings}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Value=\"{x:Static local:State.Wait}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeInWait}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Comparison=\"NotEqual\" Value=\"{x:Static local:State.Wait}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeOutWait}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Value=\"{x:Static local:State.Ingame}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeInIngame}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Comparison=\"NotEqual\" Value=\"{x:Static local:State.Ingame}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeOutIngame}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Value=\"{x:Static local:State.Main}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeInMain}\" />\r\n\t\t</ei:DataTrigger>\r\n\t\t<ei:DataTrigger Binding=\"{Binding State}\" Comparison=\"NotEqual\" Value=\"{x:Static local:State.Main}\">\r\n\t\t\t<ei:ControlStoryboardAction Storyboard=\"{StaticResource FadeOutMain}\" />\r\n\t\t</ei:DataTrigger>\r\n\t</i:Interaction.Triggers>\r\n\r\n\t<Grid x:Name=\"MenuGrid\">\r\n\t\t<Grid.Background>\r\n\t\t\t<LinearGradientBrush StartPoint=\"0,0\" EndPoint=\"0,1\">\r\n\t\t\t\t<GradientStop Offset=\"0\" Color=\"#FF123F61\" />\r\n\t\t\t\t<GradientStop Offset=\"0.6\" Color=\"#FF0E4B79\" />\r\n\t\t\t\t<GradientStop Offset=\"0.7\" Color=\"#FF106097\" />\r\n\t\t\t</LinearGradientBrush>\r\n\t\t</Grid.Background>\r\n\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\t\t<local:MainPage     x:Name=\"MainPage\"     Grid.Row=\"1\" Grid.Column=\"1\" />\r\n\t\t<local:SettingsPage x:Name=\"SettingsPage\" Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"Hidden\" />\r\n\t\t<local:LoadGamePage x:Name=\"LoadGamePage\" Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"Hidden\" />\r\n\t\t<local:NewGamePage  x:Name=\"NewGamePage\"  Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"Hidden\" />\r\n\t\t<local:WaitPage  \tx:Name=\"WaitPage\"     Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"Hidden\" />\r\n\t\t<local:IngamePage  \tx:Name=\"IngamePage\"   Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"Hidden\" />\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/MainPage.xaml",
    "content": "﻿<UserControl\n\tx:Class=\"IngnomiaGUI.MainPage\"\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\n\txmlns:system=\"clr-namespace:System;assembly=mscorlib\"\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\n\tx:Name=\"MainMenuControl\">\n\n\t<UserControl.Resources>\n\t\t<ResourceDictionary>\n\t\t\t<ResourceDictionary.MergedDictionaries>\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/pageswap.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\n\t\t\t</ResourceDictionary.MergedDictionaries>\n\t\t</ResourceDictionary>\n\t</UserControl.Resources>\n\n\t<Grid x:Name=\"LayoutRoot\" RenderTransformOrigin=\"0.5,0.5\">\n\n\t\t<i:Interaction.Triggers>\n\t\t\t<ei:StoryboardCompletedTrigger Storyboard=\"{StaticResource FadeInMain}\">\n\t\t\t\t<noesis:SetFocusAction TargetName=\"MMContinue\" />\n\t\t\t</ei:StoryboardCompletedTrigger>\n\t\t</i:Interaction.Triggers>\n\n\t\t<Grid.RenderTransform>\n\t\t\t<TransformGroup>\n\t\t\t\t<ScaleTransform ScaleX=\"1\" ScaleY=\"1\" />\n\t\t\t\t<SkewTransform />\n\t\t\t\t<RotateTransform />\n\t\t\t\t<TranslateTransform X=\"0\" Y=\"0\" />\n\t\t\t</TransformGroup>\n\t\t</Grid.RenderTransform>\n\n\t\t<Grid.RowDefinitions>\n\t\t\t<RowDefinition Height=\"2*\" />\n\t\t\t<RowDefinition Height=\"9*\" />\n\t\t\t<RowDefinition Height=\"1*\" />\n\t\t</Grid.RowDefinitions>\n\t\t<Grid.ColumnDefinitions>\n\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t\t<ColumnDefinition Width=\"5*\" />\n\t\t\t<ColumnDefinition Width=\"1*\" />\n\t\t</Grid.ColumnDefinitions>\n\n\t\t<TextBlock Grid.Row=\"0\" Grid.Column=\"1\" FontSize=\"50\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource MainPage_Ingnomia}\" />\n\n\t\t<Viewbox Grid.Row=\"1\" Grid.Column=\"1\" StretchDirection=\"DownOnly\">\n\t\t\t<StackPanel>\n\t\t\t\t<Button x:Name=\"MMContinue\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource MainPage_Continue}\" Command=\"{Binding ContinueGame}\" />\n\t\t\t\t<Button x:Name=\"MMNewGame\"   Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource MainPage_NewGame}\" Command=\"{Binding NewGame}\" />\n\t\t\t\t<Button x:Name=\"MMSetupGame\" Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource MainPage_SetUpGame}\" Command=\"{Binding SetupGame}\" />\n\t\t\t\t<Button x:Name=\"MMLoadGame\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource MainPage_LoadGame}\" Command=\"{Binding LoadGame}\" />\n\t\t\t\t<Button x:Name=\"MMSettings\"    Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource MainPage_Settings}\" Command=\"{Binding Settings}\" />\n\t\t\t\t<Button x:Name=\"MMExit\"      Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource MainPage_Exit}\" Command=\"{Binding Exit}\" />\n\t\t\t\t<Grid>\n\t\t\t\t\t<ContentControl Style=\"{StaticResource HintStyle}\" Content=\"{StaticResource MainPage_Hint_MMContinue}\" IsEnabled=\"{Binding IsMouseOver, ElementName=MMContinue}\" />\n\t\t\t\t\t<ContentControl Style=\"{StaticResource HintStyle}\" Content=\"{StaticResource MainPage_Hint_MMNewGame}\" IsEnabled=\"{Binding IsMouseOver, ElementName=MMNewGame}\" />\n\t\t\t\t\t<ContentControl Style=\"{StaticResource HintStyle}\" Content=\"{StaticResource MainPage_Hint_MMSetupGame}\" IsEnabled=\"{Binding IsMouseOver, ElementName=MMSetupGame}\" />\n\t\t\t\t\t<ContentControl Style=\"{StaticResource HintStyle}\" Content=\"{StaticResource MainPage_Hint_MMLoadGame}\" IsEnabled=\"{Binding IsMouseOver, ElementName=MMLoadGame}\" />\n\t\t\t\t\t<ContentControl Style=\"{StaticResource HintStyle}\" Content=\"{StaticResource MainPage_Hint_MMSettings}\" IsEnabled=\"{Binding IsMouseOver, ElementName=MMSettings}\" />\n\t\t\t\t\t<ContentControl Style=\"{StaticResource HintStyle}\" Content=\"{StaticResource MainPage_Hint_MMExit}\" IsEnabled=\"{Binding IsMouseOver, ElementName=MMExit}\" />\n\t\t\t\t</Grid>\n\t\t\t</StackPanel>\n\t\t</Viewbox>\n\t\t<TextBlock Grid.Row=\"2\" Grid.Column=\"0\" FontSize=\"16\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Bottom\" Text=\"{Binding Version}\" />\n\t</Grid>\n</UserControl>"
  },
  {
    "path": "content/xaml/MilitaryGui.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.MilitaryGui\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"MilitaryControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:MilitaryModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid MinHeight=\"700\" MaxHeight=\"700\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"100\" Margin=\"2\">\r\n\t\t\t\t<StackPanel>\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"First\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/squads.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource MilitaryGui_Squads}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"Second\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/roles.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource MilitaryGui_Roles}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t\t<!--\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"Third\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/professions.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource MilitaryGui_More}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t\t-->\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Border>\r\n\r\n\t\t\t<Border Style=\"{StaticResource Panel}\" MinWidth=\"1400\" MaxWidth=\"1400\" Margin=\"2\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid x:Name=\"LayoutSquads\" Visibility=\"{Binding ShowFirst}\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource MilitaryGui_MilitarySquads}\" HorizontalAlignment=\"Left\" Margin=\"5\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t<ScrollViewer x:Name=\"SVSquads\" CanContentScroll=\"True\" MinWidth=\"1290\" MaxWidth=\"1290\"\r\n\t\t\t\t\t\t\t\tHorizontalScrollBarVisibility=\"Visible\" VerticalScrollBarVisibility=\"Hidden\">\r\n\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding SquadList}\" ItemTemplate=\"{StaticResource SquadTemplate}\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" />\r\n\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t</ScrollViewer>\r\n\r\n\t\t\t\t\t\t\t<Button Content=\"+\" Margin=\"2\" FontSize=\"40\" FontWeight=\"Bold\" MinWidth=\"100\" Command=\"{Binding AddSquadCmd }\" />\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t<Grid Visibility=\"{Binding ShowSecond}\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource MilitaryGui_MilitaryRoles}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t<ScrollViewer x:Name=\"SVRoles\" CanContentScroll=\"True\" MinWidth=\"1290\" MaxWidth=\"1290\"\r\n\t\t\t\t\t\t\t\tHorizontalScrollBarVisibility=\"Visible\" VerticalScrollBarVisibility=\"Hidden\">\r\n\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding RoleList}\" ItemTemplate=\"{StaticResource MilRoleTemplate}\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" />\r\n\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t</ScrollViewer>\r\n\r\n\t\t\t\t\t\t\t<Button Content=\"+\" Margin=\"2\" FontSize=\"40\" FontWeight=\"Bold\" MinWidth=\"100\" Command=\"{Binding AddRoleCmd }\" />\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t<Grid Visibility=\"{Binding ShowThird}\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource MilitaryGui_MilitaryPriorities}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"MilitaryWindow\">\r\n\t\t\t\t<Image Source=\"buttons/cross.png\" />\r\n\t\t\t</Button>\r\n\t\t</StackPanel>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/Neighbors.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.NeighborsGui\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"NeighborsControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:NeighborsModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\t<Grid>\r\n\t\t<Grid x:Name=\"LayoutRoot\">\r\n\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"100\" Margin=\"2\">\r\n\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"First\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/skills.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource Neighbors_Neighbors}\"></TextBlock>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"Second\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Image Source=\"buttons/schedule.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource Neighbors_Missions}\"></TextBlock>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<!--\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\" Content=\"P\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"Third\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/professions.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource Neighbors_More}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t\t-->\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</Border>\r\n\r\n\t\t\t\t<Border x:Name=\"TabBorder2\" Style=\"{StaticResource Panel}\" MinWidth=\"1400\" MaxWidth=\"1400\" Margin=\"2\">\r\n\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t<Grid x:Name=\"LayoutNeighbors\" Visibility=\"{Binding ShowFirst}\">\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource Neighbors_NeighborsPage}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\r\n\t\t\t\t\t\t\t<ScrollViewer x:Name=\"SVNeighbors\" HorizontalScrollBarVisibility=\"Hidden\" CanContentScroll=\"True\" Grid.Row=\"1\" Grid.Column=\"0\">\r\n\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding NeighborList}\" ItemTemplate=\"{StaticResource NeighborKingdomTemplate}\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t</ScrollViewer>\r\n\r\n\t\t\t\t\t\t\t<ScrollViewer x:Name=\"SVMissions\" HorizontalScrollBarVisibility=\"Hidden\" CanContentScroll=\"True\" Grid.Row=\"1\" Grid.Column=\"1\">\r\n\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding MissionList}\" ItemTemplate=\"{StaticResource MissionTemplate}\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t<Grid x:Name=\"LayoutMissions\" Visibility=\"{Binding ShowSecond}\">\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource Neighbors_MissionsPage}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t<Grid x:Name=\"LayoutProfEdit\" Visibility=\"{Binding ShowThird}\">\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource Neighbors_NeighborsThirdPage}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Border>\r\n\t\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\" Grid.Column=\"2\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"NeighborsWindow\">\r\n\t\t\t\t\t<Image Source=\"buttons/cross.png\" />\r\n\t\t\t\t</Button>\r\n\t\t\t</StackPanel>\r\n\t\t</Grid>\r\n\r\n\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"600\" MaxWidth=\"600\" MinHeight=\"300\" MaxHeight=\"300\"\r\n\t\t\tBorderBrush=\"Black\" BorderThickness=\"2,2,2,2\"\r\n\t\t\tCornerRadius=\"8\" Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"{Binding ShowGnomeSelect}\">\r\n\t\t\t<Grid>\r\n\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t<TextBlock Text=\"{Binding MissionTitle}\" FontWeight=\"Bold\" FontSize=\"20\" Margin=\"4\" VerticalAlignment=\"Top\" Grid.Row=\"0\" />\r\n\t\t\t\t<TextBlock Text=\"{Binding MissionTarget}\" FontSize=\"20\" Margin=\"4\" Grid.Row=\"1\" />\r\n\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"2\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\">\r\n\t\t\t\t\t<TextBlock Text=\"Select gnome:\" FontSize=\"20\" Margin=\"4\" />\r\n\t\t\t\t\t<ComboBox x:Name=\"MissionGnome1Selector\"\r\n\t\t\t\t\tMargin=\"8,0,0,0\" MinHeight=\"50\" MaxHeight=\"50\" MinWidth=\"300\"\r\n\t\t\t\t\tItemsSource=\"{Binding MissionGnomes}\"\r\n\t\t\t\t\tSelectedItem=\"{Binding SelectedGnome, Mode=TwoWay}\"\r\n\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate20}\" />\r\n\t\t\t\t</StackPanel>\r\n\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"3\" VerticalAlignment=\"Center\" HorizontalAlignment=\"Center\">\r\n\t\t\t\t\t<TextBlock Text=\"Select action:\" FontSize=\"20\" Margin=\"4\" />\r\n\t\t\t\t\t<ComboBox x:Name=\"MissionActionSelector\"\r\n\t\t\t\t\tMargin=\"8,0,0,0\" MinHeight=\"50\" MaxHeight=\"50\" MinWidth=\"300\"\r\n\t\t\t\t\tItemsSource=\"{Binding MissionActions}\"\r\n\t\t\t\t\tSelectedItem=\"{Binding SelectedAction, Mode=TwoWay}\"\r\n\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate20}\" />\r\n\t\t\t\t</StackPanel>\r\n\r\n\t\t\t\t<Grid Grid.Row=\"4\" VerticalAlignment=\"Bottom\">\r\n\r\n\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t\t\t<Button Content=\"Back\" Command=\"{Binding CmdNewMissionBack}\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" FontSize=\"20\" />\r\n\t\t\t\t\t<Button Content=\"Start\" Command=\"{Binding CmdNewMissionStart}\" Grid.Column=\"1\" HorizontalAlignment=\"Right\" FontSize=\"20\" />\r\n\t\t\t\t</Grid>\r\n\t\t\t</Grid>\r\n\t\t</Border>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/NewGamePage.xaml",
    "content": "﻿<UserControl\r\n\tx:Class=\"IngnomiaGUI.NewGamePage\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"NewGameMenuControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:NewGameModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/pageswap.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" RenderTransformOrigin=\"0.5,0.5\">\r\n\t\t<i:Interaction.Triggers>\r\n\t\t\t<ei:StoryboardCompletedTrigger Storyboard=\"{StaticResource FadeInNewGame}\">\r\n\t\t\t\t<noesis:SetFocusAction TargetName=\"Back\" />\r\n\t\t\t</ei:StoryboardCompletedTrigger>\r\n\t\t</i:Interaction.Triggers>\r\n\r\n\t\t<Grid.RenderTransform>\r\n\t\t\t<TransformGroup>\r\n\t\t\t\t<ScaleTransform ScaleX=\"1\" ScaleY=\"1\" />\r\n\t\t\t\t<SkewTransform />\r\n\t\t\t\t<RotateTransform />\r\n\t\t\t\t<TranslateTransform X=\"0\" Y=\"0\" />\r\n\t\t\t</TransformGroup>\r\n\t\t</Grid.RenderTransform>\r\n\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t<RowDefinition Height=\"10*\" />\r\n\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t<Viewbox Grid.Row=\"0\" Grid.Column=\"1\">\r\n\t\t\t<TextBlock FontSize=\"10\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource NewGamePage_SetUpNewGame}\" />\r\n\t\t</Viewbox>\r\n\t\t<Viewbox Grid.Row=\"1\" Grid.Column=\"1\" MinWidth=\"800\" MaxWidth=\"800\" MinHeight=\"600\" MaxHeight=\"600\">\r\n\t\t\t<Grid >\r\n\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\r\n\t\t\t\t<TabControl Grid.Row=\"0\" Style=\"{StaticResource MainMenuTabControlStyle}\">\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_World}\">\r\n\t\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" Text=\"{StaticResource NewGamePage_KingdomName}\" Margin=\"0,0,0,5\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"1\" x:Name=\"KingdomName\" Text=\"{Binding KingdomName}\" />\r\n\t\t\t\t\t\t\t\t\t<Button Grid.Column=\"2\" x:Name=\"RandomName\"  Content=\"{StaticResource NewGamePage_Random}\" Command=\"{Binding RandomKingdomName}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" Text=\"{StaticResource NewGamePage_Seed}\" Margin=\"0,0,0,5\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"1\" x:Name=\"Seed\" Text=\"{Binding Seed}\" />\r\n\t\t\t\t\t\t\t\t\t<Button Grid.Column=\"2\" x:Name=\"RandomSeed\"  Content=\"{StaticResource NewGamePage_Random}\" Command=\"{Binding RandomSeed}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_WorldSize}\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel MaxWidth=\"1000\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_LargerSizePerformance}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t</TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t\t</TextBlock>\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderSize\" Minimum=\"0\" Maximum=\"300\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding WorldSize}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"40\" x:Name=\"TextBoxWorldSize\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderSize,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<!--\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_ZLevels}\" />\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderZLevels\" Minimum=\"0\" Maximum=\"200\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding ZLevels}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"30\" x:Name=\"TextBoxZLevels\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderZLevels,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_Ground}\" />\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderGround\" Minimum=\"0\" Maximum=\"170\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding Ground}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"30\" x:Name=\"TextBoxGround\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderGround,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t-->\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_Flatness}\" />\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderFlatness\" Minimum=\"0\" Maximum=\"20\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding Flatness}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"40\" x:Name=\"TextBoxFlatness\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderFlatness,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_OceanSize}\" />\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderOceanSize\" Minimum=\"0\" Maximum=\"15\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding OceanSize}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"40\" x:Name=\"TextBoxOceanSize\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderOceanSize,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_Rivers}\" />\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderRivers\" Minimum=\"0\" Maximum=\"10\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding Rivers}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"40\" x:Name=\"TextBoxRivers\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderRivers,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_RiverSize}\" />\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderRiverSize\" Minimum=\"0\" Maximum=\"20\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding RiverSize}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"40\" x:Name=\"TextBoxRiverSize\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderRiverSize,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t<Grid HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_StartArea}\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Width=\"300\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"Size of vegetation free area\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"around your starting position.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t</TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t\t</TextBlock>\r\n\t\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderStartZone\" Minimum=\"0\" Maximum=\"20\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding StartZone}\" />\r\n\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"40\" x:Name=\"TextBoxStartingZone\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderStartZone,Path=Value}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_StartingItems}\">\r\n\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"12*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<Grid Grid.Row=\"0\" HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" Text=\"{StaticResource NewGamePage_Presets}\" Margin=\"2\" />\r\n\t\t\t\t\t\t\t\t<ComboBox x:Name=\"PresetSelector\" Grid.Column=\"1\" VerticalAlignment=\"Center\" Margin=\"0,0,8,0\"\r\n\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Presets}\"\r\n\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPreset, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t<Button Grid.Column=\"2\" x:Name=\"NewPreset\"  Content=\"{StaticResource NewGamePage_NewPreset}\" Command=\"{Binding NewPreset}\" Margin=\"1\" />\r\n\t\t\t\t\t\t\t\t<Button Grid.Column=\"3\" x:Name=\"SavePreset\"  Content=\"Save preset\" Command=\"{Binding SavePreset}\" Margin=\"1\" />\r\n\t\t\t\t\t\t\t\t<Button Grid.Column=\"4\" x:Name=\"DeletePreset\"  Content=\"{StaticResource NewGamePage_DeletePreset}\" Command=\"{Binding DeletePreset}\" Margin=\"1\" />\r\n\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t<Grid Grid.Row=\"1\" HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<TextBlock Grid.Column=\"0\" Text=\"{StaticResource NewGamePage_Gnomes}\" Margin=\"2\" />\r\n\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderGnomes\" Minimum=\"1\" Maximum=\"100\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding NumGnomes}\" />\r\n\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" x:Name=\"NumGnomes\" Width=\"50\" MaxLength=\"3\" Text=\"{Binding ElementName=sliderGnomes,Path=Value}\" />\r\n\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t<TabControl Grid.Row=\"2\" Width=\"580\" Height= \"300\">\r\n\t\t\t\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_Items}\">\r\n\t\t\t\t\t\t\t\t\t<Grid VerticalAlignment=\"Top\">\r\n\t\t\t\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t\t\t\t\t\t\t\t<Grid VerticalAlignment=\"Top\" HorizontalAlignment=\"Stretch\" Margin=\"2\" Grid.Row=\"0\">\r\n\t\t\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"0\" Width=\"50\" x:Name=\"TextBoxItemAmount\"  MaxLength=\"3\" Text=\"{Binding ItemAmount}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<ComboBox Grid.Column=\"1\" x:Name=\"ItemSelector\"  VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Items}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedItem, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<ComboBox Grid.Column=\"2\" x:Name=\"ItemMat1Selector\" VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Materials1}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedMaterial1, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<ComboBox Grid.Column=\"3\" x:Name=\"ItemMat2Selector\" VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Materials2}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedMaterial2, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<Button Grid.Column=\"4\" x:Name=\"AddItem\"  Content=\"{StaticResource NewGamePage_Add}\" Command=\"{Binding AddItem}\" Margin=\"2\" />\r\n\t\t\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t\t\t<Grid Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t\t\t\t\t<ScrollViewer x:Name=\"StartItemsScroll\" CanContentScroll=\"True\" MinHeight=\"150\" MaxHeight=\"150\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ItemsControl x:Name=\"ICStartingItems\" ItemsSource=\"{Binding StartingItems}\" ItemTemplate=\"{StaticResource StartItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_Animals}\">\r\n\t\t\t\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t\t\t\t\t\t\t\t<Grid  VerticalAlignment=\"Top\" HorizontalAlignment=\"Stretch\" Margin=\"2\" Grid.Row=\"0\">\r\n\t\t\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"0\" Width=\"30\" x:Name=\"TextBoxAnimalAmount\"  MaxLength=\"3\" Text=\"{Binding AnimalAmount}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<ComboBox Grid.Column=\"1\" x:Name=\"AnimalSelector\"  VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Animals}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedAnimal, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<ComboBox Grid.Column=\"2\" x:Name=\"AnimalGenderSelector\" VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Genders}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedGender, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t<Button Grid.Column=\"4\" x:Name=\"AddAnimal\"  Content=\"{StaticResource NewGamePage_Add}\" Command=\"{Binding AddAnimal}\" Margin=\"2\" />\r\n\t\t\t\t\t\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t\t\t\t\t\t<Grid Grid.Row=\"1\" VerticalAlignment=\"Top\">\r\n\t\t\t\t\t\t\t\t\t\t\t<ScrollViewer x:Name=\"StartAnimalsScroll\" CanContentScroll=\"True\" MinHeight=\"150\" MaxHeight=\"150\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ItemsControl x:Name=\"ICStartingAnimals\" ItemsSource=\"{Binding StartingAnimals, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource StartAnimalTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t\t\t</TabControl>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_Enemies}\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<CheckBox Content=\"{StaticResource NewGamePage_PeacefulMode}\" IsChecked=\"{Binding Peaceful}\">\r\n\t\t\t\t\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t\t\t<StackPanel Width=\"300\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NoEnemyKingdoms}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_PeacefulAnimalsMayStillAttack}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t</CheckBox>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_Flora}\">\r\n\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"12*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<Grid  Grid.Row=\"0\" HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_TreeDensity}\" />\r\n\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderTreeDensity\" Minimum=\"0\" Maximum=\"100\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding TreeDensity}\" />\r\n\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"35\" x:Name=\"TextBoxTreeDens\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderTreeDensity,Path=Value}\" />\r\n\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t<Grid Grid.Row=\"1\" HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"2.2*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"7.8*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_PlantDensity}\" />\r\n\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderPlantDensity\" Minimum=\"0\" Maximum=\"100\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\" Value=\"{Binding PlantDensity}\" />\r\n\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"35\" x:Name=\"TextBoxPlantDens\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderPlantDensity,Path=Value}\" />\r\n\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t<Grid Grid.Row=\"2\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<Grid Grid.Column=\"0\">\r\n\t\t\t\t\t\t\t\t\t<ScrollViewer x:Name=\"AllowedTreeScroll\" CanContentScroll=\"True\">\r\n\t\t\t\t\t\t\t\t\t\t<ItemsControl x:Name=\"ICAllowedTrees\" ItemsSource=\"{Binding AllowedTrees, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource ListCheckBoxTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid Grid.Column=\"1\">\r\n\t\t\t\t\t\t\t\t\t<ScrollViewer x:Name=\"AllowedPlantsScroll\" CanContentScroll=\"True\">\r\n\t\t\t\t\t\t\t\t\t\t<ItemsControl x:Name=\"ICAllowedPlants\" ItemsSource=\"{Binding AllowedPlants, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource ListCheckBoxTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource NewGamePage_Fauna}\">\r\n\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"12*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<Grid  Grid.Row=\"0\" HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"8*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NumberMaxWildAnimalsPage}\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel MaxWidth=\"1000\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NumberMaxWildAnimals}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NumberMaxWildAnimalsAtStart}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t</TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t</TextBlock>\r\n\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderWildAnimals\" Minimum=\"0\" Maximum=\"500\" IsSnapToTickEnabled=\"True\" TickFrequency=\"10\" Value=\"{Binding NumWildAnimals}\" />\r\n\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"35\" x:Name=\"TextBoxWildAnimals\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderWildAnimals,Path=Value}\" />\r\n\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t<Grid Grid.Row=\"1\" HorizontalAlignment=\"Stretch\" Margin=\"5\">\r\n\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"8*\" />\r\n\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"*\" />\r\n\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NumberMaxAnimalsPage}\">\r\n\t\t\t\t\t\t\t\t\t<TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel MaxWidth=\"1000\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NumberMaxAnimals}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource NewGamePage_NumberMaxAnimalsIncludesDomesticated}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t</TextBlock.ToolTip>\r\n\t\t\t\t\t\t\t\t</TextBlock>\r\n\t\t\t\t\t\t\t\t<Slider Grid.Column=\"1\" x:Name=\"sliderMaxPerType\" Minimum=\"0\" Maximum=\"999\" IsSnapToTickEnabled=\"True\" TickFrequency=\"10\" Value=\"{Binding MaxPerType}\" />\r\n\t\t\t\t\t\t\t\t<TextBox Grid.Column=\"2\" Width=\"35\" x:Name=\"TextBoxMaxPerType\"  MaxLength=\"3\" Text=\"{Binding ElementName=sliderMaxPerType,Path=Value}\" />\r\n\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t<Grid Grid.Row=\"2\">\r\n\t\t\t\t\t\t\t\t<ScrollViewer x:Name=\"AllowedAnimalsScroll\" CanContentScroll=\"True\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl x:Name=\"ICAllowedAnimals\" ItemsSource=\"{Binding AllowedWildAnimals, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource AnimalCheckBoxTemplate}\" />\r\n\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t</TabControl>\r\n\t\t\t\t<Grid Grid.Row=\"1\">\r\n\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t<Button Grid.Column=\"0\" x:Name=\"Back\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource NewGamePage_Back}\" Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainMenu}}, Path=DataContext.Back }\" />\r\n\t\t\t\t\t<Button Grid.Column=\"2\" x:Name=\"Embark\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource NewGamePage_Embark}\" Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainMenu}}, Path=DataContext.NewGame }\" />\r\n\t\t\t\t</Grid>\r\n\t\t\t\t<TextBlock Grid.Row=\"2\"  x:Name=\"SettingsDescription\" />\r\n\t\t\t</Grid>\r\n\t\t</Viewbox>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/PopulationWindow.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.PopulationWindow\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"PopulationControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:PopulationModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"100\" Margin=\"2\">\r\n\t\t\t\t<StackPanel>\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"Skills\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/skills.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource PopulationWindow_Skills}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"Schedule\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/schedule.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource PopulationWindow_Schedule}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t\t<Button Style=\"{StaticResource SquareButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding PageCmd}\"\r\n\t\t\t\t\t\tCommandParameter=\"ProfEdit\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Image Source=\"buttons/professions.png\" Stretch=\"None\" />\r\n\t\t\t\t\t\t\t<TextBlock HorizontalAlignment=\"Center\" Text=\"{StaticResource PopulationWindow_EditProf}\"></TextBlock>\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</Button>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Border>\r\n\r\n\t\t\t<Border x:Name=\"TabBorder2\" Style=\"{StaticResource Panel}\" MinWidth=\"1400\" MaxWidth=\"1400\" Margin=\"2\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid x:Name=\"LayoutSkills\" Visibility=\"{Binding ShowSkills}\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<StackPanel Grid.Row=\"0\" Grid.Column=\"0\" Orientation=\"Horizontal\" VerticalAlignment=\"Bottom\">\r\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_Name}\" MinWidth=\"185\" Margin=\"2\" Command=\"{Binding CmdSort}\" CommandParameter=\"Name\" />\r\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_Professions}\" MinWidth=\"180\" Margin=\"2\" Command=\"{Binding CmdSort}\" CommandParameter=\"Prof\" />\r\n\t\t\t\t\t\t</StackPanel>\r\n\r\n\t\t\t\t\t\t<ScrollViewer x:Name=\"SVSkillHeaders\" HorizontalScrollBarVisibility=\"Hidden\" CanContentScroll=\"True\" Grid.Row=\"0\" Grid.Column=\"1\">\r\n\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding SkillHeaders}\" ItemTemplate=\"{StaticResource PopGnomeSkillHeaderTemplate}\">\r\n\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" />\r\n\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t</ScrollViewer>\r\n\r\n\t\t\t\t\t\t<ItemsControl x:Name=\"SVNames\"\r\n\t\t\t\t\t\t\t\t\t  ItemsSource=\"{Binding Gnomes}\" ItemTemplate=\"{StaticResource PopGnomeNameTemplate}\"\r\n\t\t\t\t\t\t\t\t\t  Grid.Row=\"1\" Grid.Column=\"0\"\r\n\t\t\t\t\t\t\t\t\t  Style=\"{StaticResource VirtualList}\"\r\n\t\t\t\t\t\t\t\t\t  ScrollViewer.VerticalScrollBarVisibility=\"Hidden\">\r\n\t\t\t\t\t\t</ItemsControl>\r\n\r\n\t\t\t\t\t\t<ItemsControl x:Name=\"SVSkills\"\r\n\t\t\t\t\t\t\t\t\t  ItemsSource=\"{Binding Gnomes}\" ItemTemplate=\"{StaticResource PopGnomeSkillRowTemplate}\"\r\n\t\t\t\t\t\t\t\t\t  Grid.Row=\"1\" Grid.Column=\"1\"\r\n\t\t\t\t\t\t\t\t\t  Style=\"{StaticResource VirtualList}\"\r\n\t\t\t\t\t\t\t\t\t  ScrollViewer.HorizontalScrollBarVisibility=\"Auto\" ScrollViewer.VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t<Grid x:Name=\"LayoutSchedule\" Visibility=\"{Binding ShowSchedule}\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t\t\t\t<ScrollViewer x:Name=\"SVSchedHeaders\" HorizontalScrollBarVisibility=\"Hidden\" CanContentScroll=\"True\" Grid.Row=\"0\" Grid.Column=\"1\">\r\n\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"0\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"0\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"1\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"1\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"2\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"2\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"3\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"3\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"4\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"4\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"5\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"5\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"6\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"6\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"7\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"7\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"8\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"8\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"9\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"9\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"10\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"10\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"11\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"11\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"12\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"12\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"13\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"13\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"14\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"14\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"15\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"15\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"16\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"16\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"17\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"17\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"18\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"18\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"19\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"19\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"20\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"20\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"21\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"21\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"22\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"22\" />\r\n\t\t\t\t\t\t\t\t<Button Style=\"{StaticResource GnomeScheduleButtonStyle}\" Content=\"23\" Command=\"{Binding CmdSetHourForAll}\" CommandParameter=\"23\" />\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</ScrollViewer>\r\n\r\n\t\t\t\t\t\t<ItemsControl x:Name=\"SchedNames\"\r\n\t\t\t\t\t\t\t\t\t  ItemsSource=\"{Binding Schedules}\" ItemTemplate=\"{StaticResource PopScheduleNameTemplate}\"\r\n\t\t\t\t\t\t\t\t\t  Grid.Row=\"1\" Grid.Column=\"0\"\r\n\t\t\t\t\t\t\t\t\t  Style=\"{StaticResource VirtualList}\"\r\n\t\t\t\t\t\t\t\t\t  ScrollViewer.VerticalScrollBarVisibility=\"Hidden\">\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t<ItemsControl x:Name=\"SVActivities\"\r\n\t\t\t\t\t\t\t\t\t  ItemsSource=\"{Binding Schedules}\" ItemTemplate=\"{StaticResource PopGnomeSchedRowTemplate}\"\r\n\t\t\t\t\t\t\t\t\t  Grid.Row=\"1\" Grid.Column=\"1\"  Style=\"{StaticResource VirtualList}\"\r\n\t\t\t\t\t\t\t\t\t  ScrollViewer.VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t</ItemsControl>\r\n\r\n\t\t\t\t\t\t<Grid Grid.Row=\"1\" Grid.Column=\"2\">\r\n\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_None}\"  MinWidth=\"185\" Margin=\"2\" Command=\"{Binding CmdSetActivityType}\" Background=\"{StaticResource ActivityNoneBrush}\" CommandParameter=\"None\" />\r\n\t\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_Eat}\"   MinWidth=\"185\" Margin=\"2\" Command=\"{Binding CmdSetActivityType}\" Background=\"{StaticResource ActivityEatBrush}\" CommandParameter=\"Eat\" />\r\n\t\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_Sleep}\" MinWidth=\"185\" Margin=\"2\" Command=\"{Binding CmdSetActivityType}\" Background=\"{StaticResource ActivitySleepBrush}\" CommandParameter=\"Sleep\" />\r\n\t\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_Train}\" MinWidth=\"185\" Margin=\"2\" Command=\"{Binding CmdSetActivityType}\" Background=\"{StaticResource ActivityTrainBrush}\" CommandParameter=\"Train\" />\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</Grid>\r\n\r\n\t\t\t\t\t<Grid x:Name=\"LayoutProfEdit\" Visibility=\"{Binding ShowProfEdit}\">\r\n\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t\t\t\t\t<TextBlock Text=\"{StaticResource PopulationWindow_EditProfessions}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"20\" Grid.Row=\"0\" />\r\n\r\n\t\t\t\t\t\t<Grid Grid.Row=\"1\" Grid.Column=\"0\">\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<ComboBox x:Name=\"ProfessionSelector\" VerticalAlignment=\"Top\" Margin=\"8,0,0,0\" MaxHeight=\"28\" HorizontalAlignment=\"Stretch\"  MinWidth=\"180\" MaxWidth=\"180\"\r\n\t\t\t\t\t\t\t\tGrid.Row=\"0\"\r\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Professions}\"\r\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding Profession, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource PopProfessionTemplate}\" />\r\n\t\t\t\t\t\t\t<TextBox x:Name=\"ProfName\" Grid.Row=\"1\" MinWidth=\"180\" Text=\"{Binding ProfName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" HorizontalAlignment=\"Left\" Margin=\"3\" />\r\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_New}\" MinWidth=\"180\"   Margin=\"2\" Grid.Column=\"2\" HorizontalAlignment=\"Center\" Grid.Row=\"2\"\r\n\t\t\t\t\t\t\t\tCommand=\"{Binding CmdProfNew }\" />\r\n\t\t\t\t\t\t\t<Button Content=\"{StaticResource PopulationWindow_Delete}\" MinWidth=\"180\" Margin=\"2\" Grid.Column=\"2\" HorizontalAlignment=\"Center\" Grid.Row=\"3\"\r\n\t\t\t\t\t\t\t\tCommand=\"{Binding CmdProfDelete }\" />\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t<ScrollViewer x:Name=\"ProfEditSkills\" VerticalScrollBarVisibility=\"Auto\" HorizontalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\" Grid.Column=\"1\" Margin=\"5\">\r\n\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding ProfSkills}\" ItemTemplate=\"{StaticResource ProfSkillTemplate}\">\r\n\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t<ScrollViewer x:Name=\"AllProfSkills\" VerticalScrollBarVisibility=\"Auto\" HorizontalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\" Grid.Column=\"2\" Margin=\"5\">\r\n\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding AllProfSkills}\" ItemTemplate=\"{StaticResource ProfSkillTemplate2}\">\r\n\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t</Grid>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"PopWindow\">\r\n\t\t\t\t<Image Source=\"buttons/cross.png\" />\r\n\t\t\t</Button>\r\n\t\t</StackPanel>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/SelectionGui.xaml",
    "content": "<UserControl\n\tx:Class=\"IngnomiaGUI.SelectionGui\"\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\n\tx:Name=\"SelectionDisplay\">\n\t<UserControl.DataContext>\n\t\t<local:SelectionModel />\n\t</UserControl.DataContext>\n\t<UserControl.Resources>\n\t\t<ResourceDictionary>\n\t\t\t<ResourceDictionary.MergedDictionaries>\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\n\t\t\t</ResourceDictionary.MergedDictionaries>\n\t\t</ResourceDictionary>\n\t</UserControl.Resources>\n\n\t<Grid>\n\t\t<Border Style=\"{StaticResource Panel}\" Width=\"150\" Height=\"100\" Margin=\"2\">\n\t\t\t<StackPanel>\n\t\t\t\t<TextBlock Text=\"{Binding Cursor}\"></TextBlock>\n\t\t\t\t<TextBlock Text=\"{Binding Action}\"></TextBlock>\n\t\t\t\t<TextBlock Text=\"{Binding FirstClick}\"></TextBlock>\n\t\t\t\t<TextBlock Text=\"{Binding Size}\"></TextBlock>\n\t\t\t</StackPanel>\n\t\t</Border>\n\t</Grid>\n</UserControl>"
  },
  {
    "path": "content/xaml/SettingsPage.xaml",
    "content": "﻿<UserControl\r\n\tx:Class=\"IngnomiaGUI.SettingsPage\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"SettingsMenuControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:SettingsModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" RenderTransformOrigin=\"0.5,0.5\">\r\n\t\t<Grid.RenderTransform>\r\n\t\t\t<TransformGroup>\r\n\t\t\t\t<ScaleTransform ScaleX=\"1\" ScaleY=\"1\" />\r\n\t\t\t\t<SkewTransform />\r\n\t\t\t\t<RotateTransform />\r\n\t\t\t\t<TranslateTransform X=\"0\" Y=\"0\" />\r\n\t\t\t</TransformGroup>\r\n\t\t</Grid.RenderTransform>\r\n\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t<RowDefinition Height=\"10*\" />\r\n\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t<Viewbox Grid.Row=\"0\" Grid.Column=\"1\">\r\n\t\t\t<TextBlock FontSize=\"10\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource SettingsPage_Settings}\" />\r\n\t\t</Viewbox>\r\n\t\t<Viewbox Grid.Row=\"1\" Grid.Column=\"1\" MinWidth=\"800\" MaxWidth=\"800\" MinHeight=\"600\" MaxHeight=\"600\" >\r\n\t\t\t<Grid >\r\n\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t\t<TabControl Style=\"{StaticResource MainMenuTabControlStyle}\" Grid.Row=\"0\">\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource SettingsPage_Game}\">\r\n\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"6*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<ScrollViewer HorizontalScrollBarVisibility=\"Hidden\" CanContentScroll=\"True\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t<StackPanel >\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" Text=\"{StaticResource SettingsPage_UiScale}\" VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t\t\t<ComboBox   Grid.Column=\"2\" VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding UIScales}\"\r\n\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding UIScale, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t<!--\r\n\t\t\t\t\t\t\t\t\t<Slider     Grid.Column=\"2\" Minimum=\"5\" Maximum=\"20\" VerticalAlignment=\"Center\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tValue=\"{Binding UIScale}\" />\r\n\t\t\t\t\t\t\t\t\t-->\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" VerticalAlignment=\"Center\" Text=\"{StaticResource SettingsPage_FullScreen}\"/>\r\n\t\t\t\t\t\t\t\t\t<CheckBox   Grid.Column=\"2\" VerticalAlignment=\"Center\" Content=\"\" IsChecked=\"{Binding FullScreen}\"/>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" VerticalAlignment=\"Center\" FontSize=\"10\" Text=\"{StaticResource SettingsPage_Language}\"/>\r\n\t\t\t\t\t\t\t\t\t<ComboBox   Grid.Column=\"2\" VerticalAlignment=\"Center\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding Languages}\"\r\n\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedLanguage, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" Text=\"{StaticResource SettingsPage_KeyboardSpeed}\" VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t\t\t<Slider     Grid.Column=\"2\" Minimum=\"0\" Maximum=\"200\" VerticalAlignment=\"Center\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tValue=\"{Binding KeyboardSpeed}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" Text=\"{StaticResource SettingsPage_LightMin}\" VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t\t\t<Slider     Grid.Column=\"2\" Minimum=\"0\" Maximum=\"100\" VerticalAlignment=\"Center\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tValue=\"{Binding LightMin}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" VerticalAlignment=\"Center\" Text=\"Mousewheel behavior\"/>\r\n\t\t\t\t\t\t\t\t\t<CheckBox   Grid.Column=\"2\" VerticalAlignment=\"Center\" Content=\"\" IsChecked=\"{Binding MouseWheelBehavior}\"/>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource SettingsPage_Controls}\">\r\n\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" Text=\"{StaticResource SettingsPage_KeybindingsPlaceholder}\" VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t\t<TabItem Header=\"{StaticResource SettingsPage_Audio}\">\r\n\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"6*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t<ScrollViewer HorizontalScrollBarVisibility=\"Hidden\" CanContentScroll=\"True\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t<StackPanel >\r\n\t\t\t\t\t\t\t\t<Grid Margin=\"0,20,0,0\">\r\n\t\t\t\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t\t\t\t<TextBlock  Grid.Column=\"1\" FontSize=\"10\" Text=\"{StaticResource SettingsPage_AudioMasterVolume}\" VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t\t\t<Slider     Grid.Column=\"2\" Minimum=\"0\" Maximum=\"100\" VerticalAlignment=\"Center\" IsSnapToTickEnabled=\"True\" TickFrequency=\"1\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tValue=\"{Binding AudioMasterVolume}\" />\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t</TabItem>\r\n\t\t\t\t</TabControl>\r\n\r\n\t\t\t\t<Button Grid.Row=\"1\" x:Name=\"Back\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource SettingsPage_Back}\"\r\n\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainMenu}}, Path=DataContext.Back }\" />\r\n\r\n\t\t\t\t<!--\r\n\t\t\t\t<Grid Grid.Row=\"1\">\r\n\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"3*\" />\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t<Button Grid.Column=\"0\" x:Name=\"Back\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource SettingsPage_Back}\"\r\n\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainMenu}}, Path=DataContext.Back }\" />\r\n\t\t\t\t\t<Button Grid.Column=\"2\" x:Name=\"Embark\"  Style=\"{StaticResource MenuButtonStyle}\" Content=\"{StaticResource SettingsPage_Accept}\" />\r\n\t\t\t\t</Grid>\r\n\t\t\t\t-->\r\n\t\t\t</Grid>\r\n\t\t</Viewbox>\r\n\r\n\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/StockpileGui.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.StockpileGui\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\tx:Name=\"StockpileControl\"  d:DataContext=\"{d:DesignData /SampleData/StockpileModelSampleData.xaml}\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:StockpileModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" MinHeight=\"700\" MaxHeight=\"700\">\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\t\t<StackPanel Grid.Column=\"1\" Orientation=\"Horizontal\">\r\n\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"100\" MinHeight=\"700\" Margin=\"2\" />\r\n\t\t\t<Border x:Name=\"TabBorder2\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\">\r\n\t\t\t\t<StackPanel>\r\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource StockpileGui_Stockpile}\" />\r\n\t\t\t\t\t<TextBox x:Name=\"SPName\" Text=\"{Binding Name}\" Margin=\"10,5,10,5\" />\r\n\t\t\t\t\t<ComboBox x:Name=\"PrioritySelector\" Margin=\"10,5,10,5\"\r\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\r\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t<CheckBox x:Name=\"CBSuspend\" Content=\"{StaticResource StockpileGui_Suspend}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpileSuspend}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpilePushable}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpilePullable}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t\t\t</CheckBox>\r\n\t\t\t\t\t<CheckBox x:Name=\"CBAllowPull\" Content=\"{StaticResource StockpileGui_PullFromHere}\" IsChecked=\"{Binding PullFromHere, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpilePullFromHere}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpilePullFromHigher}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t\t\t</CheckBox>\r\n\t\t\t\t\t<CheckBox x:Name=\"CBPullFrom\" Content=\"{StaticResource StockpileGui_PullFromOther}\" IsChecked=\"{Binding PullFromOther, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpilePullFromOther}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource StockpileGui_StockpilePullFromLower}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t\t\t</CheckBox>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t<Button Content=\"{StaticResource StockpileGui_CopySetup}\" Margin=\"10,4,4,4\" />\r\n\t\t\t\t\t\t<Button Content=\"{StaticResource StockpileGui_PasteSetup}\" Margin=\"4\" />\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Border>\r\n\t\t\t<Border x:Name=\"TabBorder3\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource StockpileGui_Filters}\" Grid.Row=\"0\" />\r\n\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t<!--\r\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding Filters, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource FilterUnrollTemplate}\">\r\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t-->\r\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding Filters, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{StaticResource FilterCategoryTemplate}\">\r\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Border x:Name=\"TabBorder4\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource StockpileGui_Stock}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding StockedItems}\" ItemTemplate=\"{StaticResource ItemTemplate20}\">\r\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Border x:Name=\"TabBorder5\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource StockpileGui_Limits}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<TextBlock FontSize=\"16\"  HorizontalAlignment=\"Left\" Text=\"{StaticResource StockpileGui_LimitsImplementedLater}\" Grid.Row=\"1\" />\r\n\t\t\t\t\t<!--\r\n\t\t\t\t\t<CheckBox x:Name=\"CBLimitMode\" Content=\"Seperate limit for each material\" IsChecked=\"{Binding LimitCondensed, Mode=TwoWay}\" Margin=\"10,5,10,5\" Grid.Row=\"1\" />\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"2\">\r\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding Limits}\" ItemTemplate=\"{StaticResource LimitItemTemplate}\">\r\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t-->\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"MilitaryWindow\">\r\n\t\t\t\t<Image Source=\"buttons/cross.png\" />\r\n\t\t\t</Button>\r\n\t\t</StackPanel>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkAqua.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF10DDDf</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF55EDED</Color>\n    <Color x:Key=\"Color.Accent1\">#FF2FEBEB</Color>\n    <Color x:Key=\"Color.Accent2\">#FF0CBFC2</Color>\n    <Color x:Key=\"Color.Accent3\">#FF0899A1</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkBlue.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF1098DF</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF56BDEC</Color>\n    <Color x:Key=\"Color.Accent1\">#FF2EAEEB</Color>\n    <Color x:Key=\"Color.Accent2\">#FF0B80C1</Color>\n    <Color x:Key=\"Color.Accent3\">#FF0864A1</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkCrimson.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FFDE1043</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFED5580</Color>\n    <Color x:Key=\"Color.Accent1\">#FFEB2F64</Color>\n    <Color x:Key=\"Color.Accent2\">#FFC20C39</Color>\n    <Color x:Key=\"Color.Accent3\">#FFA10829</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkEmerald.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF10DE62</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF55ED8D</Color>\n    <Color x:Key=\"Color.Accent1\">#FF2FEB74</Color>\n    <Color x:Key=\"Color.Accent2\">#FF0CC254</Color>\n    <Color x:Key=\"Color.Accent3\">#FF08A14A</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkGreen.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF2AA60C</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF5AB541</Color>\n    <Color x:Key=\"Color.Accent1\">#FF43B324</Color>\n    <Color x:Key=\"Color.Accent2\">#FF218C08</Color>\n    <Color x:Key=\"Color.Accent3\">#FF187306</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkLime.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF99DF10</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFBDED55</Color>\n    <Color x:Key=\"Color.Accent1\">#FFAFEB2F</Color>\n    <Color x:Key=\"Color.Accent2\">#FF85C20C</Color>\n    <Color x:Key=\"Color.Accent3\">#FF69A108</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkOrange.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FFDF9910</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFECB556</Color>\n    <Color x:Key=\"Color.Accent1\">#FFEBA62E</Color>\n    <Color x:Key=\"Color.Accent2\">#FFC1840B</Color>\n    <Color x:Key=\"Color.Accent3\">#FFA17608</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkPurple.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF894EED</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFA67FF5</Color>\n    <Color x:Key=\"Color.Accent1\">#FF9D71F5</Color>\n    <Color x:Key=\"Color.Accent2\">#FF7743D1</Color>\n    <Color x:Key=\"Color.Accent3\">#FF6737B0</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.DarkRed.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Dark.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FFDE2B10</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFED6755</Color>\n    <Color x:Key=\"Color.Accent1\">#FFEB452F</Color>\n    <Color x:Key=\"Color.Accent2\">#FFC2240C</Color>\n    <Color x:Key=\"Color.Accent3\">#FFA11F08</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightAqua.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF10DDDf</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF0899A1</Color>\n    <Color x:Key=\"Color.Accent1\">#FF0CBFC2</Color>\n    <Color x:Key=\"Color.Accent2\">#FF2FEBEB</Color>\n    <Color x:Key=\"Color.Accent3\">#FF55EDED</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightBlue.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF1098DF</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF0864A1</Color>\n    <Color x:Key=\"Color.Accent1\">#FF0B80C1</Color>\n    <Color x:Key=\"Color.Accent2\">#FF2EAEEB</Color>\n    <Color x:Key=\"Color.Accent3\">#FF56BDEC</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightCrimson.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FFDE1043</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFA10829</Color>\n    <Color x:Key=\"Color.Accent1\">#FFC20C39</Color>\n    <Color x:Key=\"Color.Accent2\">#FFEB2F64</Color>\n    <Color x:Key=\"Color.Accent3\">#FFED5580</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightEmerald.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF10DE62</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF08A14A</Color>\n    <Color x:Key=\"Color.Accent1\">#FF0CC254</Color>\n    <Color x:Key=\"Color.Accent2\">#FF2FEB74</Color>\n    <Color x:Key=\"Color.Accent3\">#FF55ED8D</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightGreen.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF2AA60C</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF187306</Color>\n    <Color x:Key=\"Color.Accent1\">#FF218C08</Color>\n    <Color x:Key=\"Color.Accent2\">#FF43B324</Color>\n    <Color x:Key=\"Color.Accent3\">#FF5AB541</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightLime.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF99DF10</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF69A108</Color>\n    <Color x:Key=\"Color.Accent1\">#FF85C20C</Color>\n    <Color x:Key=\"Color.Accent2\">#FFAFEB2F</Color>\n    <Color x:Key=\"Color.Accent3\">#FFBDED55</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightOrange.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FFDF9910</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFA17608</Color>\n    <Color x:Key=\"Color.Accent1\">#FFC1840B</Color>\n    <Color x:Key=\"Color.Accent2\">#FFEBA62E</Color>\n    <Color x:Key=\"Color.Accent3\">#FFECB556</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightPurple.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FF894EED</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FF6737B0</Color>\n    <Color x:Key=\"Color.Accent1\">#FF7743D1</Color>\n    <Color x:Key=\"Color.Accent2\">#FF9D71F5</Color>\n    <Color x:Key=\"Color.Accent3\">#FFA67FF5</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Brushes.LightRed.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Colors.Light.xaml\"/>\n    </ResourceDictionary.MergedDictionaries>\n\n    <Color x:Key=\"Color.Accent\">#FFDE2B10</Color>\n\n    <Color x:Key=\"Color.Accent0\">#FFA11F08</Color>\n    <Color x:Key=\"Color.Accent1\">#FFC2240C</Color>\n    <Color x:Key=\"Color.Accent2\">#FFEB452F</Color>\n    <Color x:Key=\"Color.Accent3\">#FFED6755</Color>\n\n    <SolidColorBrush x:Key=\"Brush.Window.Background\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Glyph.Normal\" Color=\"{StaticResource Color.Gray0}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Over\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Pressed\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Checked\" Color=\"{StaticResource Color.White}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Glyph.DisabledChecked\" Color=\"{StaticResource Color.Gray8}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Foreground.Normal\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Placeholder\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.Disabled\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledChecked\" Color=\"{StaticResource Color.Accent0}\" />\n    <SolidColorBrush x:Key=\"Brush.Foreground.DisabledPlaceholder\" Color=\"{StaticResource Color.Gray4}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Background.Normal\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Pressed\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Background.Popup\" Color=\"{StaticResource Color.Gray9}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Border.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Pressed\" Color=\"{StaticResource Color.Gray2}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Checked\" Color=\"{StaticResource Color.Accent1}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Focus\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.FocusAccent\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.DisabledChecked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Border.Popup\" Color=\"{StaticResource Color.Gray6}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Track.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Thumb.Normal\" Color=\"{StaticResource Color.Gray3}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Over\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Pressed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.Thumb.Disabled\" Color=\"{StaticResource Color.Gray5}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Header.Normal\" Color=\"{StaticResource Color.Gray7}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.Checked\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedOver\" Color=\"{StaticResource Color.Accent2}\" />\n    <SolidColorBrush x:Key=\"Brush.Header.CheckedPressed\" Color=\"{StaticResource Color.Accent}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Normal\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.Hyperlink.Over\" Color=\"{StaticResource Color.Black}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TextBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TextBox.Focused\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.Item.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.Selected\" Color=\"{StaticResource Color.Accent3}\" />\n    <SolidColorBrush x:Key=\"Brush.Item.SelectedOver\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Normal\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ComboBox.Edit\" Color=\"{StaticResource Color.White}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TabControl.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Over\" Color=\"{StaticResource Color.Gray9}\" />\n    <SolidColorBrush x:Key=\"Brush.TabControl.Selected\" Color=\"{StaticResource Color.Accent2}\" />\n\n    <SolidColorBrush x:Key=\"Brush.TreeView.Collapsed\" Color=\"{StaticResource Color.Gray1}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Expanded\" Color=\"{StaticResource Color.Black}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.Over\" Color=\"{StaticResource Color.Accent}\" />\n    <SolidColorBrush x:Key=\"Brush.TreeView.SelectedOver\" Color=\"{StaticResource Color.Accent0}\" />\n\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Normal\" Color=\"{StaticResource Color.Gray8}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Over\" Color=\"{StaticResource Color.Gray6}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Pressed\" Color=\"{StaticResource Color.Gray5}\" />\n    <SolidColorBrush x:Key=\"Brush.ToolBar.Checked\" Color=\"{StaticResource Color.Accent2}\" />\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Colors.Dark.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <Color x:Key=\"Color.Black\">#e4e6e8</Color>\n\n    <Color x:Key=\"Color.Gray0\">#bdc0c4</Color>\n    <Color x:Key=\"Color.Gray1\">#9fa3a7</Color>\n    <Color x:Key=\"Color.Gray2\">#82878c</Color>\n    <Color x:Key=\"Color.Gray3\">#6d7378</Color>\n    <Color x:Key=\"Color.Gray4\">#595f65</Color>\n    <Color x:Key=\"Color.Gray5\">#4b5258</Color>\n    <Color x:Key=\"Color.Gray6\">#3e464c</Color>\n    <Color x:Key=\"Color.Gray7\">#323940</Color>\n    <Color x:Key=\"Color.Gray8\">#2c343a</Color>\n    <Color x:Key=\"Color.Gray9\">#262e35</Color>\n\n    <Color x:Key=\"Color.White\">#20282f</Color>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Colors.Light.xaml",
    "content": "﻿<ResourceDictionary xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n                    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n\n    <Color x:Key=\"Color.Black\">#20282f</Color>\n\n    <Color x:Key=\"Color.Gray0\">#41484e</Color>\n    <Color x:Key=\"Color.Gray1\">#5d6469</Color>\n    <Color x:Key=\"Color.Gray2\">#7b8085</Color>\n    <Color x:Key=\"Color.Gray3\">#93979b</Color>\n    <Color x:Key=\"Color.Gray4\">#abaeb2</Color>\n    <Color x:Key=\"Color.Gray5\">#bbbec1</Color>\n    <Color x:Key=\"Color.Gray6\">#cbced0</Color>\n    <Color x:Key=\"Color.Gray7\">#dcdee0</Color>\n    <Color x:Key=\"Color.Gray8\">#e5e6e8</Color>\n    <Color x:Key=\"Color.Gray9\">#edeff0</Color>\n\n    <Color x:Key=\"Color.White\">#f6f7f8</Color>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkAqua.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkAqua.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkBlue.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkBlue.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkCrimson.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkCrimson.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkEmerald.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkEmerald.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkGreen.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkGreen.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkLime.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkLime.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkOrange.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkOrange.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkPurple.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkPurple.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.DarkRed.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.DarkRed.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Fonts.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <FontFamily x:Key=\"Font.Family.Default\">Fonts/#PT Root UI</FontFamily>\n    <sys:Double x:Key=\"Font.Size.Header\">17</sys:Double>\n    <sys:Double x:Key=\"Font.Size.Normal\">15</sys:Double>\n    <sys:Double x:Key=\"Font.Size.ToolTip\">12</sys:Double>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightAqua.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightAqua.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightBlue.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightBlue.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightCrimson.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightCrimson.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightEmerald.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightEmerald.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightGreen.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightGreen.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightLime.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightLime.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightOrange.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightOrange.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightPurple.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightPurple.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.LightRed.xaml",
    "content": "﻿<ResourceDictionary\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\">\n\n    <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"NoesisTheme.Brushes.LightRed.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Fonts.xaml\" />\n        <ResourceDictionary Source=\"NoesisTheme.Styles.xaml\" />\n    </ResourceDictionary.MergedDictionaries>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/Theme/NoesisTheme.Styles.xaml",
    "content": "﻿<ResourceDictionary\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\"\n  xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\n  xmlns:sys=\"clr-namespace:System;assembly=mscorlib\"\n  xmlns:local=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\">\n\n  <sys:Double x:Key=\"Size.ScrollBar\">17</sys:Double>\n  <sys:Double x:Key=\"Size.GroupBox.Border\">1</sys:Double>\n\n  <Thickness x:Key=\"Border.Normal\">0</Thickness>\n  <Thickness x:Key=\"Border.Box\">1</Thickness>\n  <Thickness x:Key=\"Border.Over\">2</Thickness>\n  <Thickness x:Key=\"Border.Focus\">2</Thickness>\n\n  <Thickness x:Key=\"Margin.Focus.Uniform\">-3</Thickness>\n  <Thickness x:Key=\"Margin.Focus.Padded\">-8,-3</Thickness>\n\n  <CornerRadius x:Key=\"Corner.Border0\">1.75</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border0.Top\">1.75,1.75,0,0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border0.Bottom\">0,0,1.75,1.75</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border0.Left\">1.75,0,0,1.75</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border0.Right\">0,1.75,1.75,0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border1\">1.25</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border1.Top\">1.25,1.25,0,0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border1.Bottom\">0,0,1.25,1.25</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border1.Left\">1.25,0,0,1.25</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border1.Right\">0,1.25,1.25,0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border2\">0.75</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border2.Top\">0.75,0.75,0,0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border2.Bottom\">0,0,0.75,0.75</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border2.Left\">0.75,0,0,0.75</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Border2.Right\">0,0.75,0.75,0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Focus\">0</CornerRadius>\n  <CornerRadius x:Key=\"Corner.Popup\">3</CornerRadius>\n\n  <!-- Popup Animations -->\n  <Storyboard x:Key=\"Anim.Popup.Fade\" Storyboard.TargetProperty=\"Opacity\">\n    <DoubleAnimationUsingKeyFrames>\n      <EasingDoubleKeyFrame KeyTime=\"0\" Value=\"0\"/>\n      <EasingDoubleKeyFrame KeyTime=\"0:0:0.150\" Value=\"1\"/>\n    </DoubleAnimationUsingKeyFrames>\n  </Storyboard>\n  <Storyboard x:Key=\"Anim.Popup.Slide\" Storyboard.TargetProperty=\"Opacity\">\n    <DoubleAnimationUsingKeyFrames>\n      <EasingDoubleKeyFrame KeyTime=\"0\" Value=\"0\"/>\n      <EasingDoubleKeyFrame KeyTime=\"0:0:0.150\" Value=\"1\"/>\n    </DoubleAnimationUsingKeyFrames>\n  </Storyboard>\n  <Storyboard x:Key=\"Anim.Popup.Scroll\" Storyboard.TargetProperty=\"Opacity\">\n    <DoubleAnimationUsingKeyFrames>\n      <EasingDoubleKeyFrame KeyTime=\"0\" Value=\"0\"/>\n      <EasingDoubleKeyFrame KeyTime=\"0:0:0.150\" Value=\"1\"/>\n    </DoubleAnimationUsingKeyFrames>\n  </Storyboard>\n\n  <!-- Focus Styles -->\n  <Style x:Key=\"Style.Focus.Outer.Uniform\" TargetType=\"Control\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Control\">\n          <Border BorderThickness=\"{DynamicResource Border.Focus}\" BorderBrush=\"{DynamicResource Brush.Border.Focus}\" Margin=\"{DynamicResource Margin.Focus.Uniform}\" CornerRadius=\"{DynamicResource Corner.Focus}\"/>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <Style x:Key=\"Style.Focus.Outer.Padded\" TargetType=\"Control\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Control\">\n          <Border BorderThickness=\"{DynamicResource Border.Focus}\" BorderBrush=\"{DynamicResource Brush.Border.Focus}\" Margin=\"{DynamicResource Margin.Focus.Padded}\" CornerRadius=\"{DynamicResource Corner.Focus}\"/>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <Style x:Key=\"Style.Focus.Inner.Uniform\" TargetType=\"Control\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Control\">\n          <Border BorderThickness=\"{DynamicResource Border.Focus}\" BorderBrush=\"{DynamicResource Brush.Border.Focus}\" CornerRadius=\"{DynamicResource Corner.Focus}\"/>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n\n  <!-- Base Control Styles -->\n  <Style x:Key=\"Style.Base\">\n    <Setter Property=\"Control.Foreground\" Value=\"{DynamicResource Brush.Foreground.Normal}\"/>\n    <Setter Property=\"Control.HorizontalContentAlignment\" Value=\"Stretch\"/>\n    <Setter Property=\"Control.VerticalContentAlignment\" Value=\"Stretch\"/>\n    <Setter Property=\"FrameworkElement.FocusVisualStyle\" Value=\"{x:Null}\"/>\n  </Style>\n  <Style TargetType=\"Control\" BasedOn=\"{StaticResource Style.Base}\"/>\n  <Style TargetType=\"ContentControl\" BasedOn=\"{StaticResource Style.Base}\"/>\n  <Style TargetType=\"HeaderedContentControl\" BasedOn=\"{StaticResource Style.Base}\"/>\n  <Style TargetType=\"ItemsControl\" BasedOn=\"{StaticResource Style.Base}\">\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n  </Style>\n  <Style TargetType=\"HeaderedItemsControl\" BasedOn=\"{StaticResource Style.Base}\">\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n  </Style>\n  <Style TargetType=\"UserControl\" BasedOn=\"{StaticResource Style.Base}\"/>\n  <Style TargetType=\"Page\" BasedOn=\"{StaticResource Style.Base}\"/>\n  <Style TargetType=\"Separator\">\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Normal}\"/>\n  </Style>\n\n  <!-- ToolTip -->\n  <ControlTemplate x:Key=\"Template.ToolTip\" TargetType=\"ToolTip\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"1\" CornerRadius=\"{DynamicResource Corner.Popup}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n    </Border>\n  </ControlTemplate>\n  <Style TargetType=\"ToolTip\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.ToolTip}\"/>\n    <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Normal}\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Popup}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Popup}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"1\"/>\n    <Setter Property=\"Padding\" Value=\"8,6\"/>\n    <Setter Property=\"Placement\" Value=\"Mouse\"/>\n    <Setter Property=\"VerticalOffset\" Value=\"21\"/> <!-- Cursor Height -->\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolTip}\"/>\n  </Style>\n\n  <!-- Label -->\n  <ControlTemplate x:Key=\"Template.Label\" TargetType=\"Label\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"Label\" BasedOn=\"{StaticResource {x:Type Control}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"BorderBrush\" Value=\"Transparent\"/>\n    <Setter Property=\"UseLayoutRounding\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.Label}\"/>\n  </Style>\n\n  <!-- Button/RepeatButton -->\n  <ControlTemplate x:Key=\"Template.ButtonBase\" TargetType=\"ButtonBase\">\n    <Grid x:Name=\"TemplateRoot\" RenderTransformOrigin=\"0.5,0.5\">\n      <Grid.RenderTransform>\n        <ScaleTransform />\n      </Grid.RenderTransform>\n      <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border0}\"/>\n      <ContentPresenter x:Name=\"PART_ContentPresenter\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Grid>\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Press\">\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"0.99\" Duration=\"0:0:0.1\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"0.99\" Duration=\"0:0:0.1\" DecelerationRatio=\"0.25\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Release\">\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Press}\"/>\n        </Trigger.EnterActions>\n        <Trigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Release}\"/>\n        </Trigger.ExitActions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ButtonBase\" TargetType=\"ButtonBase\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Padding\" Value=\"8,7\"/>\n    <Setter Property=\"UseLayoutRounding\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ButtonBase}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n  </Style>\n  <Style TargetType=\"Button\" BasedOn=\"{StaticResource Style.ButtonBase}\"/>\n  <Style TargetType=\"RepeatButton\" BasedOn=\"{StaticResource Style.ButtonBase}\"/>\n\n  <!-- ToggleButton -->\n  <ControlTemplate x:Key=\"Template.ToggleButton\" TargetType=\"ToggleButton\">\n    <Grid x:Name=\"TemplateRoot\" RenderTransformOrigin=\"0.5,0.5\">\n      <Grid.RenderTransform>\n        <ScaleTransform />\n      </Grid.RenderTransform>\n      <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border0}\"/>\n      <ContentPresenter x:Name=\"PART_ContentPresenter\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Grid>\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Press\">\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"0.99\" Duration=\"0:0:0.1\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"0.99\" Duration=\"0:0:0.1\" DecelerationRatio=\"0.25\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Release\">\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n        <DoubleAnimation Storyboard.TargetName=\"TemplateRoot\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Press}\"/>\n        </Trigger.EnterActions>\n        <Trigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Release}\"/>\n        </Trigger.ExitActions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsChecked\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEnabled\" Value=\"False\"/>\n          <Condition Property=\"IsChecked\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.DisabledChecked}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"Border\"/>\n      </MultiTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ToggleButton\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Padding\" Value=\"8,7\"/>\n    <Setter Property=\"UseLayoutRounding\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToggleButton}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n  </Style>\n\n  <!-- ToggleSwitch -->\n  <ControlTemplate x:Key=\"Template.ToggleSwitch\" TargetType=\"ToggleButton\">\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Loaded\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"Tag\" Storyboard.TargetName=\"Root\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"1\"/>\n        </ObjectAnimationUsingKeyFrames>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Check.Loaded\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.X\" Storyboard.TargetName=\"Knob\" To=\"24\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Check\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.X\" Storyboard.TargetName=\"Knob\" To=\"24\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Uncheck\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.X\" Storyboard.TargetName=\"Knob\" To=\"0\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"Root\" Background=\"Transparent\" Tag=\"0\">\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n      </Grid.ColumnDefinitions>\n      <Border Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding Background}\"/>\n      <Border x:Name=\"Border\" Grid.Column=\"0\" Background=\"{DynamicResource Brush.Background.Normal}\" BorderBrush=\"{DynamicResource Brush.Border.Normal}\" BorderThickness=\"{DynamicResource Border.Normal}\" Width=\"44\" Height=\"20\" CornerRadius=\"10\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n      <Decorator Margin=\"{TemplateBinding BorderThickness}\">\n        <Ellipse x:Name=\"Knob\" Grid.Column=\"0\" Width=\"10\" Height=\"10\" Margin=\"5\" HorizontalAlignment=\"Left\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Fill=\"{DynamicResource Brush.Glyph.Normal}\">\n          <Ellipse.RenderTransform>\n            <TranslateTransform/>\n          </Ellipse.RenderTransform>\n        </Ellipse>\n      </Decorator>\n      <ContentPresenter x:Name=\"PART_ContentPresenter\" Grid.Column=\"1\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <EventTrigger RoutedEvent=\"FrameworkElement.Loaded\" SourceName=\"Root\">\n        <BeginStoryboard Storyboard=\"{StaticResource Anim.Loaded}\"/>\n      </EventTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"9\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Knob\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"10\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Pressed}\" TargetName=\"Knob\"/>\n      </Trigger>\n      <Trigger Property=\"IsChecked\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Checked}\" TargetName=\"Knob\"/>\n      </Trigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsChecked, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Check.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsChecked, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Check}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Uncheck}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Knob\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEnabled\" Value=\"False\"/>\n          <Condition Property=\"IsChecked\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.DisabledChecked}\" TargetName=\"Knob\"/>\n      </MultiTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ToggleSwitch\" TargetType=\"ToggleButton\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Left\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Padding\" Value=\"6,0,0,0\"/>\n    <Setter Property=\"UseLayoutRounding\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToggleSwitch}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Padded}\"/>\n  </Style>\n\n  <!-- CheckBox -->\n  <Geometry x:Key=\"Geometry.CheckBox.Check\">M0,7.5L5.5,12.5 14,2.75 11.75,1 5.5,9 1.5,5.5z</Geometry>\n  <ControlTemplate x:Key=\"Template.CheckBox\" TargetType=\"CheckBox\">\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Loaded\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"Tag\" Storyboard.TargetName=\"Root\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"1\"/>\n        </ObjectAnimationUsingKeyFrames>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Check.Loaded\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleX\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0\"/>\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleY\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Check\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleX\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0:0:0.1\" DecelerationRatio=\"1\"/>\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleY\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0:0:0.1\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Uncheck\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleX\" Storyboard.TargetName=\"Check\" To=\"0\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleY\" Storyboard.TargetName=\"Check\" To=\"0\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"Root\" Background=\"Transparent\" Tag=\"0\">\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n      </Grid.ColumnDefinitions>\n      <Border Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding Background}\"/>\n      <Border x:Name=\"Border\" Grid.Column=\"0\" Background=\"{DynamicResource Brush.Background.Normal}\" BorderBrush=\"{DynamicResource Brush.Border.Normal}\" BorderThickness=\"{DynamicResource Border.Normal}\" CornerRadius=\"{DynamicResource Corner.Border0}\" Width=\"20\" Height=\"20\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n      <Decorator Grid.Column=\"0\" Margin=\"{TemplateBinding BorderThickness}\" Width=\"20\" Height=\"20\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\">\n        <Grid>\n          <Path x:Name=\"Check\" Data=\"{StaticResource Geometry.CheckBox.Check}\" Width=\"14\" Height=\"14\" Fill=\"{DynamicResource Brush.Glyph.Checked}\" RenderTransformOrigin=\"0.5,0.5\">\n            <Path.RenderTransform>\n              <ScaleTransform ScaleX=\"0\" ScaleY=\"0\"/>\n            </Path.RenderTransform>\n          </Path>\n          <Rectangle x:Name=\"CheckIndeterminate\" Width=\"10\" Height=\"10\" Fill=\"{DynamicResource Brush.Glyph.Normal}\" Visibility=\"Collapsed\"/>\n        </Grid>\n      </Decorator>\n      <ContentPresenter x:Name=\"PART_ContentPresenter\" Grid.Column=\"1\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <EventTrigger RoutedEvent=\"FrameworkElement.Loaded\" SourceName=\"Root\">\n        <BeginStoryboard Storyboard=\"{StaticResource Anim.Loaded}\"/>\n      </EventTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsChecked\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsChecked, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Check.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsChecked, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Check}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Uncheck}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsThreeState\" Value=\"True\"/>\n          <Condition Property=\"IsChecked\" Value=\"{x:Null}\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Visibility\" Value=\"Collapsed\" TargetName=\"Check\"/>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"CheckIndeterminate\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Check\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"CheckIndeterminate\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEnabled\" Value=\"False\"/>\n          <Condition Property=\"IsChecked\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.DisabledChecked}\" TargetName=\"Check\"/>\n      </MultiTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"CheckBox\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Left\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Padding\" Value=\"6,0,0,0\"/>\n    <Setter Property=\"UseLayoutRounding\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.CheckBox}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Padded}\"/>\n  </Style>\n\n  <!-- RadioButton -->\n  <ControlTemplate x:Key=\"Template.RadioButton\" TargetType=\"RadioButton\">\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Loaded\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"Tag\" Storyboard.TargetName=\"Root\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"1\"/>\n        </ObjectAnimationUsingKeyFrames>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Check.Loaded\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleX\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0\"/>\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleY\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Check\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleX\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0:0:0.1\" DecelerationRatio=\"1\"/>\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleY\" Storyboard.TargetName=\"Check\" To=\"1\" Duration=\"0:0:0.1\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Uncheck\">\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleX\" Storyboard.TargetName=\"Check\" To=\"0\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n        <DoubleAnimation Storyboard.TargetProperty=\"RenderTransform.ScaleY\" Storyboard.TargetName=\"Check\" To=\"0\" Duration=\"0:0:0.2\" DecelerationRatio=\"1\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"Root\" Background=\"Transparent\" Tag=\"0\">\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n      </Grid.ColumnDefinitions>\n      <Border Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding Background}\"/>\n      <Border x:Name=\"Border\" Grid.Column=\"0\" Background=\"{DynamicResource Brush.Background.Normal}\" BorderBrush=\"{DynamicResource Brush.Border.Normal}\" BorderThickness=\"{DynamicResource Border.Normal}\" Width=\"20\" Height=\"20\" CornerRadius=\"10\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n      <Decorator Grid.Column=\"0\" Margin=\"{TemplateBinding BorderThickness}\" Width=\"20\" Height=\"20\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\">\n        <Ellipse x:Name=\"Check\" Width=\"10\" Height=\"10\" Fill=\"{DynamicResource Brush.Glyph.Checked}\" RenderTransformOrigin=\"0.5,0.5\">\n          <Ellipse.RenderTransform>\n            <ScaleTransform ScaleX=\"0\" ScaleY=\"0\"/>\n          </Ellipse.RenderTransform>\n        </Ellipse>\n      </Decorator>\n      <ContentPresenter x:Name=\"PART_ContentPresenter\" Grid.Column=\"1\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <EventTrigger RoutedEvent=\"FrameworkElement.Loaded\" SourceName=\"Root\">\n        <BeginStoryboard Storyboard=\"{StaticResource Anim.Loaded}\"/>\n      </EventTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsChecked\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsChecked, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Check.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsChecked, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Check}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Uncheck}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Check\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEnabled\" Value=\"False\"/>\n          <Condition Property=\"IsChecked\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"Border\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.DisabledChecked}\" TargetName=\"Check\"/>\n      </MultiTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"RadioButton\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Normal}\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Left\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Padding\" Value=\"6,0,0,0\"/>\n    <Setter Property=\"UseLayoutRounding\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.RadioButton}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Padded}\"/>\n  </Style>\n\n  <!-- ProgressBar -->\n  <ControlTemplate x:Key=\"Template.ProgressBar\" TargetType=\"ProgressBar\">\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Indeterminate\">\n        <DoubleAnimation Storyboard.TargetProperty=\"Background.RelativeTransform.X\" Storyboard.TargetName=\"IndicatorIndeterminate\" From=\"-1\" To=\"1\" Duration=\"0:0:2\" RepeatBehavior=\"Forever\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"TemplateRoot\" MinHeight=\"4\">\n      <Border x:Name=\"PART_Track\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\">\n        <Grid>\n          <Border x:Name=\"PART_Indicator\" Background=\"{TemplateBinding Foreground}\" HorizontalAlignment=\"Left\"/>\n          <Border x:Name=\"IndicatorIndeterminate\" Visibility=\"Collapsed\">\n            <Border.Background>\n              <LinearGradientBrush StartPoint=\"0,0\" EndPoint=\"1,0\">\n                <LinearGradientBrush.RelativeTransform>\n                  <TranslateTransform />\n                </LinearGradientBrush.RelativeTransform>\n                <GradientStop Color=\"{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}\" Offset=\"0\"/>\n                <GradientStop Color=\"{Binding Foreground.Color, RelativeSource={RelativeSource TemplatedParent}}\" Offset=\"0.5\"/>\n                <GradientStop Color=\"{Binding Background.Color, RelativeSource={RelativeSource TemplatedParent}}\" Offset=\"1\"/>\n              </LinearGradientBrush>\n            </Border.Background>\n          </Border>\n        </Grid>\n      </Border>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"Orientation\" Value=\"Vertical\">\n        <Setter Property=\"LayoutTransform\" TargetName=\"TemplateRoot\">\n          <Setter.Value>\n            <RotateTransform Angle=\"-90\"/>\n          </Setter.Value>\n        </Setter>\n      </Trigger>\n      <Trigger Property=\"IsIndeterminate\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Indeterminate}\"/>\n        </Trigger.EnterActions>\n        <Setter Property=\"Visibility\" Value=\"Collapsed\" TargetName=\"PART_Indicator\"/>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"IndicatorIndeterminate\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"false\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ProgressBar\" BasedOn=\"{StaticResource {x:Type Control}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Background.Checked}\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Normal}\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ProgressBar}\"/>\n  </Style>\n\n  <!-- Slider -->\n  <Style x:Key=\"Style.Slider.Thumb\" TargetType=\"Thumb\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Thumb\">\n          <Grid Background=\"Transparent\">\n            <Ellipse x:Name=\"Thumb\" Fill=\"{TemplateBinding Background}\" Width=\"20\" Height=\"20\" Margin=\"-8\"/>\n          </Grid>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsDragging\" Value=\"True\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Thumb.Pressed}\" TargetName=\"Thumb\"/>\n            </Trigger>\n            <Trigger Property=\"IsEnabled\" Value=\"False\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"Thumb\"/>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <Style x:Key=\"Style.Slider.RepeatButton\" TargetType=\"RepeatButton\" BasedOn=\"{StaticResource {x:Type RepeatButton}}\">\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"IsTabStop\" Value=\"False\"/>\n    <Setter Property=\"Focusable\" Value=\"False\"/>\n    <Setter Property=\"ClickMode\" Value=\"Press\"/>\n    <Setter Property=\"Delay\" Value=\"250\"/>\n    <Setter Property=\"Interval\" Value=\"100\"/>\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"RepeatButton\">\n          <Border Background=\"Transparent\" Padding=\"{TemplateBinding Padding}\">\n            <Border Background=\"{TemplateBinding Background}\" CornerRadius=\"{DynamicResource Corner.Border2}\"/>\n          </Border>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <ControlTemplate x:Key=\"Template.Slider.Horizontal\" TargetType=\"Slider\">\n    <Grid x:Name=\"TemplateRoot\" Height=\"20\" Margin=\"8,0\">\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"*\"/>\n        <RowDefinition Height=\"Auto\"/>\n      </Grid.RowDefinitions>\n      <Border x:Name=\"Background\" Grid.Row=\"1\" Height=\"2\" Background=\"{TemplateBinding Background}\" CornerRadius=\"{DynamicResource Corner.Border2}\"/>\n      <Border Grid.Row=\"0\" Height=\"8\">\n        <TickBar x:Name=\"TopTicks\" Fill=\"{TemplateBinding Background}\" Placement=\"Top\" VerticalAlignment=\"Top\" Height=\"4\" Visibility=\"Hidden\"/>\n      </Border>\n      <Border Grid.Row=\"2\" Height=\"8\">\n        <TickBar x:Name=\"BottomTicks\" Fill=\"{TemplateBinding Background}\" Placement=\"Bottom\" VerticalAlignment=\"Bottom\" Height=\"4\" Visibility=\"Hidden\"/>\n      </Border>\n      <Track x:Name=\"PART_Track\" Grid.RowSpan=\"3\" Orientation=\"Horizontal\">\n        <Track.DecreaseRepeatButton>\n          <RepeatButton x:Name=\"DecreaseButton\" Command=\"Slider.DecreaseLarge\" Padding=\"0,9\" Margin=\"0,0,-1,0\" Background=\"{TemplateBinding Foreground}\" Style=\"{StaticResource Style.Slider.RepeatButton}\"/>\n        </Track.DecreaseRepeatButton>\n        <Track.IncreaseRepeatButton>\n          <RepeatButton x:Name=\"IncreaseButton\" Command=\"Slider.IncreaseLarge\" Padding=\"0,9\" Background=\"Transparent\" Style=\"{StaticResource Style.Slider.RepeatButton}\"/>\n        </Track.IncreaseRepeatButton>\n        <Track.Thumb>\n          <Thumb x:Name=\"Thumb\" Background=\"{TemplateBinding Foreground}\" Style=\"{StaticResource Style.Slider.Thumb}\"/>\n        </Track.Thumb>\n      </Track>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsDirectionReversed\" Value=\"True\">\n        <Setter Property=\"Margin\" Value=\"-2,0,0,0\" TargetName=\"DecreaseButton\"/>\n      </Trigger>\n      <Trigger Property=\"local:Element.IsFocusEngaged\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Thumb\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Thumb\"/>\n      </Trigger>\n      <Trigger Property=\"TickPlacement\" Value=\"TopLeft\">\n        <Setter TargetName=\"TopTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n      </Trigger>\n      <Trigger Property=\"TickPlacement\" Value=\"BottomRight\">\n        <Setter TargetName=\"BottomTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n      </Trigger>\n      <Trigger Property=\"TickPlacement\" Value=\"Both\">\n        <Setter TargetName=\"TopTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n        <Setter TargetName=\"BottomTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"DecreaseButton\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.Slider.Vertical\" TargetType=\"Slider\">\n    <Grid x:Name=\"TemplateRoot\" Width=\"20\" Margin=\"0,8\">\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n        <ColumnDefinition Width=\"Auto\"/>\n      </Grid.ColumnDefinitions>\n      <Border x:Name=\"Background\" Grid.Column=\"1\" Width=\"2\" Background=\"{TemplateBinding Background}\" CornerRadius=\"{DynamicResource Corner.Border2}\"/>\n      <Border Grid.Column=\"0\" Width=\"8\">\n        <TickBar x:Name=\"LeftTicks\" Fill=\"{TemplateBinding Background}\" Placement=\"Left\" HorizontalAlignment=\"Left\" Width=\"4\" Visibility=\"Hidden\"/>\n      </Border>\n      <Border Grid.Column=\"2\" Width=\"8\">\n        <TickBar x:Name=\"RightTicks\" Fill=\"{TemplateBinding Background}\" Placement=\"Right\" HorizontalAlignment=\"Right\" Width=\"4\" Visibility=\"Hidden\"/>\n      </Border>\n      <Track x:Name=\"PART_Track\" Grid.ColumnSpan=\"3\" Orientation=\"Vertical\">\n        <Track.DecreaseRepeatButton>\n          <RepeatButton x:Name=\"DecreaseButton\" Command=\"Slider.DecreaseLarge\" Padding=\"9,0\" Margin=\"0,-1,0,0\" Background=\"{TemplateBinding Foreground}\" Style=\"{StaticResource Style.Slider.RepeatButton}\"/>\n        </Track.DecreaseRepeatButton>\n        <Track.IncreaseRepeatButton>\n          <RepeatButton x:Name=\"IncreaseButton\" Command=\"Slider.IncreaseLarge\" Padding=\"9,0\" Background=\"Transparent\" Style=\"{StaticResource Style.Slider.RepeatButton}\"/>\n        </Track.IncreaseRepeatButton>\n        <Track.Thumb>\n          <Thumb x:Name=\"Thumb\" Background=\"{TemplateBinding Foreground}\" Style=\"{StaticResource Style.Slider.Thumb}\"/>\n        </Track.Thumb>\n      </Track>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsDirectionReversed\" Value=\"True\">\n        <Setter Property=\"Margin\" Value=\"0,0,0,-2\" TargetName=\"DecreaseButton\"/>\n      </Trigger>\n      <Trigger Property=\"local:Element.IsFocusEngaged\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Border.Pressed}\" TargetName=\"Thumb\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Thumb\"/>\n      </Trigger>\n      <Trigger Property=\"TickPlacement\" Value=\"TopLeft\">\n        <Setter TargetName=\"LeftTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n      </Trigger>\n      <Trigger Property=\"TickPlacement\" Value=\"BottomRight\">\n        <Setter TargetName=\"RightTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n      </Trigger>\n      <Trigger Property=\"TickPlacement\" Value=\"Both\">\n        <Setter TargetName=\"LeftTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n        <Setter TargetName=\"RightTicks\" Property=\"Visibility\" Value=\"Visible\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Border.DisabledChecked}\" TargetName=\"DecreaseButton\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"Slider\" BasedOn=\"{StaticResource {x:Type Control}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Background.Checked}\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Normal}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"Orientation\" Value=\"Horizontal\">\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.Slider.Horizontal}\"/>\n      </Trigger>\n      <Trigger Property=\"Orientation\" Value=\"Vertical\">\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.Slider.Vertical}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ScrollBar -->\n  <Style x:Key=\"Style.ScrollBar.Thumb\" TargetType=\"Thumb\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Thumb\">\n          <Grid Background=\"Transparent\">\n            <Border x:Name=\"Thumb\" Background=\"{DynamicResource Brush.Thumb.Normal}\"/>\n          </Grid>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\">\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Thumb.Over}\" TargetName=\"Thumb\"/>\n            </Trigger>\n            <Trigger Property=\"IsDragging\" Value=\"True\">\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Thumb.Pressed}\" TargetName=\"Thumb\"/>\n            </Trigger>\n            <Trigger Property=\"IsEnabled\" Value=\"False\">\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Thumb.Disabled}\" TargetName=\"Thumb\"/>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <Style x:Key=\"Style.ScrollBar.LineButton\" TargetType=\"RepeatButton\" BasedOn=\"{StaticResource {x:Type RepeatButton}}\">\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"IsTabStop\" Value=\"False\"/>\n    <Setter Property=\"Focusable\" Value=\"False\"/>\n    <Setter Property=\"ClickMode\" Value=\"Press\"/>\n    <Setter Property=\"Delay\" Value=\"250\"/>\n    <Setter Property=\"Interval\" Value=\"100\"/>\n    <Setter Property=\"Width\" Value=\"{DynamicResource Size.ScrollBar}\"/>\n    <Setter Property=\"Height\" Value=\"{DynamicResource Size.ScrollBar}\"/>\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"RepeatButton\">\n          <Border x:Name=\"Border\" Background=\"Transparent\">\n            <Path x:Name=\"Arrow\" Data=\"{TemplateBinding Content}\" Stroke=\"{DynamicResource Brush.Glyph.Normal}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\"/>\n          </Border>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\">\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Normal}\" TargetName=\"Border\"/>\n              <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Arrow\"/>\n            </Trigger>\n            <Trigger Property=\"IsPressed\" Value=\"True\">\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Thumb.Pressed}\" TargetName=\"Border\"/>\n              <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Pressed}\" TargetName=\"Arrow\"/>\n            </Trigger>\n            <Trigger Property=\"IsEnabled\" Value=\"False\">\n              <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Arrow\"/>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <Style x:Key=\"Style.ScrollBar.PageButton\" TargetType=\"RepeatButton\" BasedOn=\"{StaticResource {x:Type RepeatButton}}\">\n    <Setter Property=\"IsTabStop\" Value=\"False\"/>\n    <Setter Property=\"Focusable\" Value=\"False\"/>\n    <Setter Property=\"ClickMode\" Value=\"Press\"/>\n    <Setter Property=\"Delay\" Value=\"250\"/>\n    <Setter Property=\"Interval\" Value=\"100\"/>\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"RepeatButton\">\n          <Border Background=\"Transparent\"/>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ScrollBar.Horizontal\" TargetType=\"ScrollBar\">\n    <ControlTemplate.Resources>\n      <Geometry x:Key=\"Geometry.LeftArrow\">M4,0L0,4 4,8</Geometry>\n      <Geometry x:Key=\"Geometry.RightArrow\">M0,0 L4,4 0,8</Geometry>\n      <Storyboard x:Key=\"Anim.ExpandBar\" BeginTime=\"0:0:0.1\">\n        <DoubleAnimation Storyboard.TargetName=\"Background\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineLeftButton\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineRightButton\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"Thumb\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0:0:0.1\" DecelerationRatio=\"0.5\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.CollapseBar\" BeginTime=\"0:0:2\">\n        <DoubleAnimation Storyboard.TargetName=\"Background\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineLeftButton\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineRightButton\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"Thumb\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"0.2\" Duration=\"0:0:0.15\" DecelerationRatio=\"0.5\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"TemplateRoot\" Background=\"Transparent\">\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n        <ColumnDefinition Width=\"Auto\"/>\n      </Grid.ColumnDefinitions>\n      <Border x:Name=\"Background\" Grid.ColumnSpan=\"3\" Background=\"{DynamicResource Brush.Track.Normal}\" Opacity=\"0\"/>\n      <RepeatButton x:Name=\"LineLeftButton\" Grid.Column=\"0\" Command=\"ScrollBar.LineLeftCommand\" Style=\"{StaticResource Style.ScrollBar.LineButton}\" Content=\"{StaticResource Geometry.LeftArrow}\" Opacity=\"0\"/>\n      <RepeatButton x:Name=\"LineRightButton\" Grid.Column=\"2\" Command=\"ScrollBar.LineRightCommand\" Style=\"{StaticResource Style.ScrollBar.LineButton}\" Content=\"{StaticResource Geometry.RightArrow}\" Opacity=\"0\"/>\n      <Track x:Name=\"PART_Track\" Grid.Column=\"1\" Orientation=\"Horizontal\">\n        <Track.DecreaseRepeatButton>\n          <RepeatButton x:Name=\"PageLeftButton\" Command=\"ScrollBar.PageLeftCommand\" Style=\"{StaticResource Style.ScrollBar.PageButton}\"/>\n        </Track.DecreaseRepeatButton>\n        <Track.IncreaseRepeatButton>\n          <RepeatButton x:Name=\"IncreaseButton\" Command=\"ScrollBar.PageRightCommand\" Style=\"{StaticResource Style.ScrollBar.PageButton}\"/>\n        </Track.IncreaseRepeatButton>\n        <Track.Thumb>\n          <Thumb x:Name=\"Thumb\" Style=\"{StaticResource Style.ScrollBar.Thumb}\" RenderTransformOrigin=\"0,0.8\">\n            <Thumb.RenderTransform>\n              <ScaleTransform ScaleY=\"0.2\"/>\n            </Thumb.RenderTransform>\n          </Thumb>\n        </Track.Thumb>\n      </Track>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.ExpandBar}\"/>\n        </Trigger.EnterActions>\n        <Trigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.CollapseBar}\"/>\n        </Trigger.ExitActions>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.ScrollBar.Vertical\" TargetType=\"ScrollBar\">\n    <ControlTemplate.Resources>\n      <Geometry x:Key=\"Geometry.UpArrow\">M0,4L4,0 8,4</Geometry>\n      <Geometry x:Key=\"Geometry.DownArrow\">M0,0 L4,4 8,0</Geometry>\n      <Storyboard x:Key=\"Anim.ExpandBar\" BeginTime=\"0:0:0.1\">\n        <DoubleAnimation Storyboard.TargetName=\"Background\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineUpButton\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineDownButton\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"Thumb\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0:0:0.1\" DecelerationRatio=\"0.5\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.CollapseBar\" BeginTime=\"0:0:2\">\n        <DoubleAnimation Storyboard.TargetName=\"Background\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineUpButton\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"LineDownButton\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"Thumb\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"0.2\" Duration=\"0:0:0.15\" DecelerationRatio=\"0.5\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"TemplateRoot\" Background=\"Transparent\">\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"*\"/>\n        <RowDefinition Height=\"Auto\"/>\n      </Grid.RowDefinitions>\n      <Border x:Name=\"Background\" Grid.RowSpan=\"3\" Background=\"{DynamicResource Brush.Track.Normal}\" Opacity=\"0\"/>\n      <RepeatButton x:Name=\"LineUpButton\" Grid.Row=\"0\" Command=\"ScrollBar.LineUpCommand\" Style=\"{StaticResource Style.ScrollBar.LineButton}\" Content=\"{StaticResource Geometry.UpArrow}\" Opacity=\"0\"/>\n      <RepeatButton x:Name=\"LineDownButton\" Grid.Row=\"2\" Command=\"ScrollBar.LineDownCommand\" Style=\"{StaticResource Style.ScrollBar.LineButton}\" Content=\"{StaticResource Geometry.DownArrow}\" Opacity=\"0\"/>\n      <Track x:Name=\"PART_Track\" Grid.Row=\"1\" Orientation=\"Vertical\" IsDirectionReversed=\"True\">\n        <Track.DecreaseRepeatButton>\n          <RepeatButton x:Name=\"PageUpButton\" Command=\"ScrollBar.PageUpCommand\" Style=\"{StaticResource Style.ScrollBar.PageButton}\"/>\n        </Track.DecreaseRepeatButton>\n        <Track.IncreaseRepeatButton>\n          <RepeatButton x:Name=\"IncreaseButton\" Command=\"ScrollBar.PageDownCommand\" Style=\"{StaticResource Style.ScrollBar.PageButton}\"/>\n        </Track.IncreaseRepeatButton>\n        <Track.Thumb>\n          <Thumb x:Name=\"Thumb\" Style=\"{StaticResource Style.ScrollBar.Thumb}\" RenderTransformOrigin=\"0.8,0\">\n            <Thumb.RenderTransform>\n              <ScaleTransform ScaleX=\"0.2\"/>\n            </Thumb.RenderTransform>\n          </Thumb>\n        </Track.Thumb>\n      </Track>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.ExpandBar}\"/>\n        </Trigger.EnterActions>\n        <Trigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.CollapseBar}\"/>\n        </Trigger.ExitActions>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ScrollBar\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"ForceCursor\" Value=\"True\"/>\n    <Setter Property=\"Cursor\" Value=\"Arrow\"/>\n    <Style.Triggers>\n      <Trigger Property=\"Orientation\" Value=\"Horizontal\">\n        <Setter Property=\"Height\" Value=\"{DynamicResource Size.ScrollBar}\"/>\n        <Setter Property=\"MinHeight\" Value=\"{DynamicResource Size.ScrollBar}\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.ScrollBar.Horizontal}\"/>\n      </Trigger>\n      <Trigger Property=\"Orientation\" Value=\"Vertical\">\n        <Setter Property=\"Width\" Value=\"{DynamicResource Size.ScrollBar}\"/>\n        <Setter Property=\"MinWidth\" Value=\"{DynamicResource Size.ScrollBar}\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.ScrollBar.Vertical}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ScrollViewer -->\n  <ControlTemplate x:Key=\"Template.ScrollViewer\" TargetType=\"ScrollViewer\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border0}\">\n      <Grid>\n        <Grid.RowDefinitions>\n          <RowDefinition Height=\"*\"/>\n          <RowDefinition Height=\"Auto\"/>\n        </Grid.RowDefinitions>\n        <Grid.ColumnDefinitions>\n          <ColumnDefinition Width=\"*\"/>\n          <ColumnDefinition Width=\"Auto\"/>\n        </Grid.ColumnDefinitions>\n        <Decorator x:Name=\"ShowBarsRef\" IsEnabled=\"False\"/>\n        <ScrollContentPresenter Grid.RowSpan=\"2\" Grid.ColumnSpan=\"2\" Content=\"{TemplateBinding Content}\" ContentTemplate=\"{TemplateBinding ContentTemplate}\" ContentTemplateSelector=\"{TemplateBinding ContentTemplateSelector}\" CanContentScroll=\"{TemplateBinding CanContentScroll}\" Margin=\"{TemplateBinding Padding}\"/>\n        <Rectangle x:Name=\"Corner\" Grid.Row=\"1\" Grid.Column=\"1\" Fill=\"{DynamicResource Brush.Track.Normal}\" IsEnabled=\"False\" Opacity=\"0\"/>\n        <ScrollBar x:Name=\"PART_HorizontalScrollBar\" Grid.Column=\"0\" Grid.Row=\"1\" Orientation=\"Horizontal\" MaxHeight=\"{TemplateBinding MinHeight}\" Visibility=\"{TemplateBinding ComputedHorizontalScrollBarVisibility}\" Value=\"{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}\" ViewportSize=\"{TemplateBinding ViewportWidth}\" Minimum=\"0\" Maximum=\"{TemplateBinding ScrollableWidth}\" Opacity=\"0\"/>\n        <ScrollBar x:Name=\"PART_VerticalScrollBar\" Grid.Column=\"1\" Grid.Row=\"0\" Orientation=\"Vertical\" MaxWidth=\"{TemplateBinding MinWidth}\" Visibility=\"{TemplateBinding ComputedVerticalScrollBarVisibility}\" Value=\"{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}\" ViewportSize=\"{TemplateBinding ViewportHeight}\" Minimum=\"0\" Maximum=\"{TemplateBinding ScrollableHeight}\" Opacity=\"0\"/>\n      </Grid>\n    </Border>\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.ShowBars\" BeginTime=\"0:0:0.1\">\n        <DoubleAnimation Storyboard.TargetName=\"PART_HorizontalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.5\" DecelerationRatio=\"0.5\"/>\n        <DoubleAnimation Storyboard.TargetName=\"PART_VerticalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.5\" DecelerationRatio=\"0.5\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.HideBars\" BeginTime=\"0:0:2\">\n        <DoubleAnimation Storyboard.TargetName=\"PART_HorizontalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n        <DoubleAnimation Storyboard.TargetName=\"PART_VerticalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.ShowCorner\" BeginTime=\"0:0:0.1\">\n        <DoubleAnimation Storyboard.TargetName=\"Corner\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.HideCorner\" BeginTime=\"0:0:2\">\n        <DoubleAnimation Storyboard.TargetName=\"Corner\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsKeyboardFocusWithin\" Value=\"True\">\n        <Setter Property=\"IsEnabled\" Value=\"True\" TargetName=\"ShowBarsRef\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"IsEnabled\" Value=\"True\" TargetName=\"ShowBarsRef\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"True\" SourceName=\"ShowBarsRef\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.ShowBars}\"/>\n        </Trigger.EnterActions>\n        <Trigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.HideBars}\"/>\n        </Trigger.ExitActions>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"PART_HorizontalScrollBar\">\n        <Setter Property=\"IsEnabled\" Value=\"True\" TargetName=\"Corner\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"PART_VerticalScrollBar\">\n        <Setter Property=\"IsEnabled\" Value=\"True\" TargetName=\"Corner\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"True\" SourceName=\"Corner\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.ShowCorner}\"/>\n        </Trigger.EnterActions>\n        <Trigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.HideCorner}\"/>\n        </Trigger.ExitActions>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ScrollViewer\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ScrollViewer}\"/>\n  </Style>\n\n  <!-- GroupBox -->\n  <ControlTemplate x:Key=\"Template.GroupBox.NoHeader\" TargetType=\"GroupBox\">\n    <Grid>\n      <Rectangle Stroke=\"{TemplateBinding BorderBrush}\" StrokeThickness=\"{DynamicResource Size.GroupBox.Border}\" RadiusX=\"4\" RadiusY=\"4\"/>\n      <Decorator Margin=\"5\">\n        <ContentPresenter Margin=\"{TemplateBinding Padding}\"/>\n      </Decorator>\n    </Grid>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.GroupBox\" TargetType=\"GroupBox\">\n    <Grid>\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"5\" MaxHeight=\"5\"/>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"*\"/>\n        <RowDefinition Height=\"5\"/>\n      </Grid.RowDefinitions>\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n        <ColumnDefinition Width=\"9\" MaxWidth=\"9\"/>\n      </Grid.ColumnDefinitions>\n      <Path Grid.Row=\"1\" Grid.Column=\"0\" Data=\"M8,0L4,0A4,4,0,0,0,0,4\" StrokeStartLineCap=\"Square\" Stretch=\"Fill\" StrokeEndLineCap=\"Square\" Stroke=\"{TemplateBinding BorderBrush}\" StrokeThickness=\"{DynamicResource Size.GroupBox.Border}\" VerticalAlignment=\"Bottom\" Margin=\"0,4,0,-4\"/>\n      <Border Grid.Row=\"2\" Grid.RowSpan=\"2\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" Background=\"{TemplateBinding BorderBrush}\" Width=\"{DynamicResource Size.GroupBox.Border}\" Margin=\"0,4,0,0\"/>\n      <Path Grid.Row=\"4\" Grid.Column=\"0\" Data=\"M0,0A4,4,0,0,0,4,4L8,4\" StrokeStartLineCap=\"Square\" Stretch=\"Fill\" StrokeEndLineCap=\"Square\" Stroke=\"{TemplateBinding BorderBrush}\" StrokeThickness=\"{DynamicResource Size.GroupBox.Border}\"/>\n      <Border Grid.Row=\"5\" Grid.Column=\"1\" Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding BorderBrush}\" Height=\"{DynamicResource Size.GroupBox.Border}\" VerticalAlignment=\"Bottom\"/>\n      <Path Grid.Row=\"4\" Grid.Column=\"3\" Data=\"M0,4L4,4A4,4,0,0,0,8,0\" StrokeStartLineCap=\"Square\" Stretch=\"Fill\" StrokeEndLineCap=\"Square\" Stroke=\"{TemplateBinding BorderBrush}\" StrokeThickness=\"{DynamicResource Size.GroupBox.Border}\"/>\n      <Border Grid.Row=\"2\" Grid.RowSpan=\"2\" Grid.Column=\"3\" HorizontalAlignment=\"Right\" Background=\"{TemplateBinding BorderBrush}\" Width=\"{DynamicResource Size.GroupBox.Border}\" Margin=\"0,4,0,0\"/>\n      <Path Grid.Row=\"1\" Grid.Column=\"3\" Data=\"M8,4A4,4,0,0,0,4,0L0,0\" StrokeStartLineCap=\"Square\" Stretch=\"Fill\" StrokeEndLineCap=\"Square\" Stroke=\"{TemplateBinding BorderBrush}\" StrokeThickness=\"{DynamicResource Size.GroupBox.Border}\" VerticalAlignment=\"Bottom\" Margin=\"0,4,0,-4\"/>\n      <Border Grid.Row=\"1\" Grid.Column=\"2\" Background=\"{TemplateBinding BorderBrush}\" Height=\"{DynamicResource Size.GroupBox.Border}\" VerticalAlignment=\"Bottom\"/>\n      <Border x:Name=\"ContentHost\" Grid.Row=\"3\" Grid.Column=\"1\" Grid.ColumnSpan=\"2\" Margin=\"-4,0\">\n        <ContentPresenter Margin=\"{TemplateBinding Padding}\"/>\n      </Border>\n      <ContentPresenter x:Name=\"HeaderHost\" Grid.Row=\"0\" Grid.RowSpan=\"3\" Grid.Column=\"1\" ContentSource=\"Header\" Margin=\"4,0\" TextElement.FontSize=\"{DynamicResource Font.Size.Header}\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"Header\" Value=\"{x:Null}\">\n        <Setter Property=\"Margin\" Value=\"0\" TargetName=\"HeaderHost\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"GroupBox\" BasedOn=\"{StaticResource {x:Type HeaderedContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"Padding\" Value=\"4\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.GroupBox}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"Header\" Value=\"{x:Null}\">\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.GroupBox.NoHeader}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- Expander -->\n  <Style x:Key=\"Style.Expander.Toggle\" TargetType=\"ToggleButton\" BasedOn=\"{StaticResource {x:Type ToggleButton}}\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"ToggleButton\">\n          <Grid Background=\"Transparent\">\n            <ContentPresenter />\n          </Grid>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n  </Style>\n  <Geometry x:Key=\"Geometry.Expander.Arrow\">M0,0L6,6 0,12</Geometry>\n  <ControlTemplate x:Key=\"Template.Expander\" TargetType=\"Expander\">\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Loaded\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"Tag\" Storyboard.TargetName=\"Root\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"1\"/>\n        </ObjectAnimationUsingKeyFrames>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Vertical.Loaded\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0\"/>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Vertical.Up.Loaded\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"-90\" Duration=\"0\"/>\n        <StaticResource ResourceKey=\"Anim.Expand.Vertical.Loaded\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Vertical.Down.Loaded\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"90\" Duration=\"0\"/>\n        <StaticResource ResourceKey=\"Anim.Expand.Vertical.Loaded\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Horizontal.Loaded\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"90\" Duration=\"0\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0\">\n          <DoubleAnimation.EasingFunction>\n            <BackEase EasingMode=\"EaseOut\" Amplitude=\"0.2\"/>\n          </DoubleAnimation.EasingFunction>\n        </DoubleAnimation>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Vertical\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0\"/>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0:0:0.2\">\n          <DoubleAnimation.EasingFunction>\n            <BackEase EasingMode=\"EaseOut\" Amplitude=\"0.2\"/>\n          </DoubleAnimation.EasingFunction>\n        </DoubleAnimation>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Vertical.Up\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"-90\" Duration=\"0:0:0.15\"/>\n        <StaticResource ResourceKey=\"Anim.Expand.Vertical\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Vertical.Down\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"90\" Duration=\"0:0:0.15\"/>\n        <StaticResource ResourceKey=\"Anim.Expand.Vertical\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Collapse.Vertical\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"0\" Duration=\"0:0:0.2\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0:0:0.2\" Value=\"{x:Static Visibility.Collapsed}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"0\" Duration=\"0:0:0.2\" AccelerationRatio=\"0.5\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Horizontal\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"90\" Duration=\"0:0:0.15\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"1\" Duration=\"0:0:0.2\">\n          <DoubleAnimation.EasingFunction>\n            <BackEase EasingMode=\"EaseOut\" Amplitude=\"0.2\"/>\n          </DoubleAnimation.EasingFunction>\n        </DoubleAnimation>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Collapse.Horizontal\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"0\" Duration=\"0:0:0.2\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0:0:0.2\" Value=\"{x:Static Visibility.Collapsed}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ContentBg\" Storyboard.TargetProperty=\"RenderTransform.ScaleX\" To=\"0\" Duration=\"0:0:0.2\" AccelerationRatio=\"0.5\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"Root\" Tag=\"0\">\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"*\"/>\n        <RowDefinition Height=\"Auto\"/>\n      </Grid.RowDefinitions>\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n        <ColumnDefinition Width=\"Auto\"/>\n      </Grid.ColumnDefinitions>\n      <ToggleButton x:Name=\"ExpanderButton\" Style=\"{StaticResource Style.Expander.Toggle}\" IsChecked=\"{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\" Foreground=\"{TemplateBinding Foreground}\">\n        <Border x:Name=\"HeaderBg\" Background=\"{DynamicResource Brush.Header.Normal}\" CornerRadius=\"{DynamicResource Corner.Border0.Top}\">\n          <Grid>\n            <Grid.ColumnDefinitions>\n              <ColumnDefinition Width=\"Auto\"/>\n              <ColumnDefinition Width=\"*\"/>\n            </Grid.ColumnDefinitions>\n            <Path x:Name=\"Arrow\" Grid.Column=\"0\" Stroke=\"{DynamicResource Brush.Glyph.Normal}\" Data=\"{StaticResource Geometry.Expander.Arrow}\" Margin=\"14,11.5\" RenderTransformOrigin=\"0.5,0.5\">\n              <Path.RenderTransform>\n                <RotateTransform />\n              </Path.RenderTransform>\n            </Path>\n            <ContentPresenter x:Name=\"HeaderHost\" Grid.Column=\"1\" ContentSource=\"Header\" VerticalAlignment=\"Center\" Margin=\"0,0,14,0\" TextElement.FontSize=\"{DynamicResource Font.Size.Header}\"/>\n          </Grid>\n        </Border>\n      </ToggleButton>\n      <Decorator x:Name=\"ContentBorder\" Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"Collapsed\">\n        <Border x:Name=\"ContentBg\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border0.Bottom}\" Padding=\"{TemplateBinding Padding}\">\n          <Border.RenderTransform>\n            <ScaleTransform ScaleX=\"0\" ScaleY=\"0\"/>\n          </Border.RenderTransform>\n          <ContentPresenter x:Name=\"ContentHost\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n        </Border>\n      </Decorator>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <EventTrigger RoutedEvent=\"FrameworkElement.Loaded\" SourceName=\"Root\">\n        <BeginStoryboard Storyboard=\"{StaticResource Anim.Loaded}\"/>\n      </EventTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ExpanderButton\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Over}\" TargetName=\"HeaderBg\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\" SourceName=\"ExpanderButton\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Pressed}\" TargetName=\"HeaderBg\"/>\n      </Trigger>\n      <Trigger Property=\"IsExpanded\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Checked}\" TargetName=\"HeaderBg\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsExpanded\" Value=\"True\"/>\n          <Condition Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ExpanderButton\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.CheckedOver}\" TargetName=\"HeaderBg\"/>\n      </MultiTrigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsExpanded\" Value=\"True\"/>\n          <Condition Property=\"IsPressed\" Value=\"True\" SourceName=\"ExpanderButton\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.CheckedPressed}\" TargetName=\"HeaderBg\"/>\n      </MultiTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Up\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Vertical.Up.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Down\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Vertical.Down.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Left\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Horizontal.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Right\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Horizontal.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Up\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Vertical.Up}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Collapse.Vertical}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Down\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Vertical.Down}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Collapse.Vertical}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Left\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Horizontal}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Collapse.Horizontal}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding ExpandDirection, RelativeSource={RelativeSource Self}}\" Value=\"Right\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Horizontal}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Collapse.Horizontal}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEnabled\" Value=\"False\"/>\n          <Condition Property=\"IsExpanded\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.DisabledChecked}\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Foreground.DisabledChecked}\" TargetName=\"Arrow\"/>\n      </MultiTrigger>\n      <Trigger Property=\"ExpandDirection\" Value=\"Down\">\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"Grid.Column\" Value=\"1\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"RenderTransformOrigin\" Value=\"0.5,0\" TargetName=\"ContentBg\"/>\n      </Trigger>\n      <Trigger Property=\"ExpandDirection\" Value=\"Up\">\n        <Setter Property=\"Grid.Row\" Value=\"2\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"Grid.Column\" Value=\"1\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"RenderTransformOrigin\" Value=\"0.5,1\" TargetName=\"ContentBg\"/>\n      </Trigger>\n      <Trigger Property=\"ExpandDirection\" Value=\"Right\">\n        <Setter Property=\"Grid.Row\" Value=\"1\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"RenderTransformOrigin\" Value=\"0,0.5\" TargetName=\"ContentBg\"/>\n        <Setter Property=\"LayoutTransform\" TargetName=\"ExpanderButton\">\n          <Setter.Value>\n            <RotateTransform Angle=\"-90\"/>\n          </Setter.Value>\n        </Setter>\n      </Trigger>\n      <Trigger Property=\"ExpandDirection\" Value=\"Left\">\n        <Setter Property=\"Grid.Row\" Value=\"1\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"Grid.Column\" Value=\"2\" TargetName=\"ExpanderButton\"/>\n        <Setter Property=\"RenderTransformOrigin\" Value=\"1,0.5\" TargetName=\"ContentBg\"/>\n        <Setter Property=\"LayoutTransform\" TargetName=\"ExpanderButton\">\n          <Setter.Value>\n            <RotateTransform Angle=\"90\"/>\n          </Setter.Value>\n        </Setter>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"Expander\" BasedOn=\"{StaticResource {x:Type HeaderedContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"Transparent\"/>\n    <Setter Property=\"Padding\" Value=\"8\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.Expander}\"/>\n  </Style>\n\n  <!-- Hyperlink -->\n  <Style TargetType=\"Hyperlink\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Hyperlink.Normal}\"/>\n    <Setter Property=\"TextDecorations\" Value=\"Underline\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Hyperlink.Over}\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"True\">\n        <Setter Property=\"Cursor\" Value=\"Hand\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- Menu -->\n  <ControlTemplate x:Key=\"Template.Menu\" TargetType=\"Menu\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ItemsPresenter />\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ItemsPanelTemplate x:Key=\"Template.Menu.ItemsPanel\">\n    <StackPanel Orientation=\"Horizontal\"/>\n  </ItemsPanelTemplate>\n  <Style TargetType=\"Menu\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Normal}\"/>\n    <Setter Property=\"ItemsPanel\" Value=\"{StaticResource Template.Menu.ItemsPanel}\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.Menu}\"/>\n  </Style>\n\n  <!-- MenuItem Separator -->\n  <ControlTemplate x:Key=\"Template.MenuItem.Separator\" TargetType=\"Separator\">\n    <Rectangle Height=\"1\" Fill=\"{DynamicResource Brush.Border.Popup}\" Margin=\"32,5,4,5\"/>\n  </ControlTemplate>\n  <Style x:Key=\"Style.MenuItem.Separator\" TargetType=\"Separator\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.Separator}\"/>\n  </Style>\n\n  <!-- MenuItem -->\n  <Geometry x:Key=\"Geometry.MenuItem.Arrow\">M0,0L6,6 0,12</Geometry>\n  <ControlTemplate x:Key=\"Template.MenuItem.TopLevelHeader\" TargetType=\"MenuItem\">\n    <Grid>\n      <Border x:Name=\"Header\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n        <ContentPresenter ContentSource=\"Header\" VerticalAlignment=\"Center\"/>\n      </Border>\n      <Popup IsOpen=\"{TemplateBinding IsSubmenuOpen}\" Focusable=\"False\" Placement=\"Bottom\" PopupAnimation=\"Fade\" AllowsTransparency=\"True\">\n        <Border Background=\"{DynamicResource Brush.Background.Popup}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1\" CornerRadius=\"{DynamicResource Corner.Border1}\" Padding=\"0,6\">\n          <ItemsPresenter />\n        </Border>\n      </Popup>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsHighlighted\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Header\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.MenuItem.TopLevelItem\" TargetType=\"MenuItem\">\n    <Border x:Name=\"Header\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter ContentSource=\"Header\" VerticalAlignment=\"Center\"/>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsHighlighted\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Header\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.MenuItem.SubmenuHeader\" TargetType=\"MenuItem\">\n    <Grid>\n      <Border x:Name=\"Header\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n        <Grid>\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"Auto\" SharedSizeGroup=\"Icon\"/>\n            <ColumnDefinition Width=\"*\" SharedSizeGroup=\"Header\"/>\n            <ColumnDefinition Width=\"Auto\" SharedSizeGroup=\"Shortcut\"/>\n            <ColumnDefinition Width=\"Auto\"/>\n          </Grid.ColumnDefinitions>\n          <Decorator Grid.Column=\"0\" MinWidth=\"32\">\n            <ContentPresenter x:Name=\"Icon\" Margin=\"6,0\" VerticalAlignment=\"Center\" ContentSource=\"Icon\"/>\n          </Decorator>\n          <ContentPresenter x:Name=\"HeaderHost\" Grid.Column=\"1\" Margin=\"6,0\" ContentSource=\"Header\" VerticalAlignment=\"Center\"/>\n          <Decorator Grid.Column=\"3\" MinWidth=\"24\">\n            <Path x:Name=\"Arrow\" Data=\"{StaticResource Geometry.MenuItem.Arrow}\" Margin=\"6,0\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Stroke=\"{DynamicResource Brush.Glyph.Normal}\"/>\n          </Decorator>\n        </Grid>\n      </Border>\n      <Popup IsOpen=\"{TemplateBinding IsSubmenuOpen}\" Focusable=\"False\" HorizontalOffset=\"-2\" VerticalOffset=\"-7\" Placement=\"Right\" PopupAnimation=\"Fade\" AllowsTransparency=\"True\">\n        <Border Background=\"{DynamicResource Brush.Background.Popup}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1\" CornerRadius=\"{DynamicResource Corner.Border1}\" Padding=\"0,6\">\n          <ItemsPresenter />\n        </Border>\n      </Popup>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsHighlighted\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Header\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.MenuItem.SubmenuItem\" TargetType=\"MenuItem\">\n    <Border x:Name=\"Header\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <Grid>\n        <Grid.ColumnDefinitions>\n          <ColumnDefinition Width=\"Auto\" SharedSizeGroup=\"Icon\"/>\n          <ColumnDefinition Width=\"*\" SharedSizeGroup=\"Header\"/>\n          <ColumnDefinition Width=\"Auto\" SharedSizeGroup=\"Shortcut\"/>\n          <ColumnDefinition Width=\"Auto\"/>\n        </Grid.ColumnDefinitions>\n        <Decorator Grid.Column=\"0\" MinWidth=\"32\">\n          <Grid>\n            <ContentPresenter x:Name=\"Icon\" Margin=\"6,0\" VerticalAlignment=\"Center\" ContentSource=\"Icon\"/>\n            <Path x:Name=\"Check\" Margin=\"6,0\" Data=\"{StaticResource Geometry.CheckBox.Check}\" Fill=\"{DynamicResource Brush.Glyph.Normal}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Visibility=\"Hidden\"/>\n          </Grid>\n        </Decorator>\n        <ContentPresenter x:Name=\"HeaderHost\" Grid.Column=\"1\" Margin=\"6,0\" ContentSource=\"Header\" VerticalAlignment=\"Center\"/>\n        <TextBlock x:Name=\"InputGestureText\" Grid.Column=\"2\" Text=\"{TemplateBinding InputGestureText}\" Foreground=\"{DynamicResource Brush.Foreground.Placeholder}\" VerticalAlignment=\"Center\" Margin=\"12,0,0,0\"/>\n        <Decorator Grid.Column=\"3\" MinWidth=\"24\"/>\n      </Grid>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsCheckable\" Value=\"True\">\n        <Setter TargetName=\"Icon\" Property=\"Visibility\" Value=\"Collapsed\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsCheckable\" Value=\"True\"/>\n          <Condition Property=\"IsChecked\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter TargetName=\"Check\" Property=\"Visibility\" Value=\"Visible\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsHighlighted\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Selected}\" TargetName=\"Header\"/>\n        <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Check\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ItemsPanelTemplate x:Key=\"Template.MenuItem.ItemsPanel\">\n    <StackPanel Grid.IsSharedSizeScope=\"True\" KeyboardNavigation.DirectionalNavigation=\"Cycle\"/>\n  </ItemsPanelTemplate>\n  <Style TargetType=\"MenuItem\" BasedOn=\"{StaticResource {x:Type HeaderedItemsControl}}\">\n    <Style.Resources>\n      <Style x:Key=\"{x:Static MenuItem.SeparatorStyleKey}\" TargetType=\"Separator\" BasedOn=\"{StaticResource Style.MenuItem.Separator}\"/>\n    </Style.Resources>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"TopLevelHeader\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Header}\"/>\n        <Setter Property=\"Padding\" Value=\"12,7.5\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.TopLevelHeader}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"TopLevelItem\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Header}\"/>\n        <Setter Property=\"Padding\" Value=\"12,7.5\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.TopLevelItem}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"SubmenuHeader\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Normal}\"/>\n        <Setter Property=\"Padding\" Value=\"0,7\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.SubmenuHeader}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"SubmenuItem\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Normal}\"/>\n        <Setter Property=\"Padding\" Value=\"0,7\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.SubmenuItem}\"/>\n      </Trigger>\n    </Style.Triggers>\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"ItemsPanel\" Value=\"{StaticResource Template.MenuItem.ItemsPanel}\"/>\n  </Style>\n\n  <!-- ContextMenu -->\n  <ControlTemplate x:Key=\"Template.ContextMenu\" TargetType=\"ContextMenu\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\" CornerRadius=\"{DynamicResource Corner.Border1}\">\n      <ItemsPresenter />\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ContextMenu\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Style.Resources>\n      <Style x:Key=\"{x:Static MenuItem.SeparatorStyleKey}\" TargetType=\"Separator\" BasedOn=\"{StaticResource Style.MenuItem.Separator}\"/>\n    </Style.Resources>\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Background.Popup}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Popup}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"1\"/>\n    <Setter Property=\"Padding\" Value=\"0,6\"/>\n    <Setter Property=\"Cursor\" Value=\"Arrow\"/>\n    <Setter Property=\"ForceCursor\" Value=\"True\"/>\n    <Setter Property=\"ItemsPanel\" Value=\"{StaticResource Template.MenuItem.ItemsPanel}\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ContextMenu}\"/>\n  </Style>\n\n  <!-- TextBox -->\n  <Style x:Key=\"Style.TextBox.Placeholder\" TargetType=\"TextBlock\">\n    <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Placeholder}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.DisabledPlaceholder}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n  <ControlTemplate x:Key=\"Template.TextBox\" TargetType=\"TextBox\">\n    <Grid>\n      <Border Background=\"{TemplateBinding Background}\" CornerRadius=\"{DynamicResource Corner.Border0}\"/>\n      <Grid>\n        <Border x:Name=\"Placeholder\" Padding=\"{TemplateBinding Padding}\" Margin=\"2,0\" Visibility=\"Collapsed\">\n          <TextBlock Text=\"{Binding (local:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}\" Style=\"{DynamicResource Style.TextBox.Placeholder}\"/>\n        </Border>\n        <ScrollViewer x:Name=\"PART_ContentHost\" Focusable=\"False\" Padding=\"{TemplateBinding Padding}\" Foreground=\"{TemplateBinding Foreground}\"/>\n      </Grid>\n      <Border x:Name=\"Border\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border1}\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"Text\" Value=\"\">\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsKeyboardFocused\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Focused}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Focus}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\"/>\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"TextBox\" BasedOn=\"{StaticResource {x:Type Control}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Box}\"/>\n    <Setter Property=\"CaretBrush\" Value=\"{DynamicResource Brush.Foreground.Normal}\"/>\n    <Setter Property=\"SelectionBrush\" Value=\"{DynamicResource Brush.Background.Checked}\"/>\n    <Setter Property=\"SelectionOpacity\" Value=\"0.25\"/>\n    <Setter Property=\"Padding\" Value=\"6,7\"/>\n    <Setter Property=\"KeyboardNavigation.TabNavigation\" Value=\"None\"/>\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n    <Setter Property=\"AllowDrop\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.TextBox}\"/>\n    <Setter Property=\"ContextMenu\">\n      <Setter.Value>\n        <ContextMenu>\n          <MenuItem Command=\"ApplicationCommands.Cut\"/>\n          <MenuItem Command=\"ApplicationCommands.Copy\"/>\n          <MenuItem Command=\"ApplicationCommands.Paste\"/>\n        </ContextMenu>\n      </Setter.Value>\n    </Setter>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"True\">\n        <Setter Property=\"Cursor\" Value=\"IBeam\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- PasswordBox -->\n  <ControlTemplate x:Key=\"Template.PasswordBox.Scroll\" TargetType=\"ScrollViewer\">\n    <ScrollContentPresenter Margin=\"{TemplateBinding Padding}\"/>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.PasswordBox\" TargetType=\"PasswordBox\">\n    <Grid>\n      <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border1}\"/>\n      <Grid>\n        <Border x:Name=\"Placeholder\" Padding=\"{TemplateBinding Padding}\" Margin=\"2,0\" Visibility=\"Collapsed\">\n          <TextBlock Text=\"{Binding (local:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}\" Style=\"{DynamicResource Style.TextBox.Placeholder}\"/>\n        </Border>\n        <ScrollViewer x:Name=\"PART_ContentHost\" Template=\"{StaticResource Template.PasswordBox.Scroll}\" Focusable=\"False\" Padding=\"{TemplateBinding Padding}\" Foreground=\"{TemplateBinding Foreground}\"/>\n      </Grid>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"local:Text.PasswordLength\" Value=\"0\">\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsKeyboardFocused\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Focused}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Focus}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\"/>\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"PasswordBox\" BasedOn=\"{StaticResource {x:Type Control}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Box}\"/>\n    <Setter Property=\"CaretBrush\" Value=\"{DynamicResource Brush.Foreground.Normal}\"/>\n    <Setter Property=\"SelectionBrush\" Value=\"{DynamicResource Brush.Background.Checked}\"/>\n    <Setter Property=\"SelectionOpacity\" Value=\"0.5\"/>\n    <Setter Property=\"Padding\" Value=\"6,7\"/>\n    <Setter Property=\"KeyboardNavigation.TabNavigation\" Value=\"None\"/>\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n    <Setter Property=\"PasswordChar\" Value=\"•\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.PasswordBox}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"True\">\n        <Setter Property=\"Cursor\" Value=\"IBeam\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ListBox -->\n  <ControlTemplate x:Key=\"Template.ListBox\" TargetType=\"ListBox\">\n    <ScrollViewer Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\" Focusable=\"False\">\n      <ItemsPresenter />\n    </ScrollViewer>\n  </ControlTemplate>\n  <Style TargetType=\"ListBox\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"ScrollViewer.HorizontalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.VerticalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.CanContentScroll\" Value=\"True\"/>\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n    <Setter Property=\"VirtualizingPanel.VirtualizationMode\" Value=\"Recycling\"/>\n    <Setter Property=\"VirtualizingPanel.ScrollUnit\" Value=\"Pixel\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ListBox}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ListBoxItem -->\n  <ControlTemplate x:Key=\"Template.ListBoxItem\" TargetType=\"ListBoxItem\">\n    <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsSelected\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Selected}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsMouseOver\" Value=\"True\"/>\n          <Condition Property=\"IsSelected\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.SelectedOver}\" TargetName=\"Border\"/>\n      </MultiTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ListBoxItem\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}\"/>\n    <Setter Property=\"Padding\" Value=\"12,8.5\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ListBoxItem}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Inner.Uniform}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ListView -->\n  <Style x:Key=\"Style.GridView.Scroll\" TargetType=\"ScrollViewer\" BasedOn=\"{StaticResource {x:Type ScrollViewer}}\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"ScrollViewer\">\n          <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border0}\">\n            <Grid>\n              <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\"/>\n                <RowDefinition Height=\"*\"/>\n                <RowDefinition Height=\"Auto\"/>\n              </Grid.RowDefinitions>\n              <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"*\"/>\n                <ColumnDefinition Width=\"Auto\"/>\n              </Grid.ColumnDefinitions>\n              <ScrollViewer Grid.Row=\"0\" Grid.ColumnSpan=\"2\" MinHeight=\"0\" HorizontalScrollBarVisibility=\"Hidden\" VerticalScrollBarVisibility=\"Hidden\" PanningMode=\"HorizontalFirst\" Focusable=\"False\">\n                <GridViewHeaderRowPresenter AllowsColumnReorder=\"{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}\" ColumnHeaderContainerStyle=\"{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}\" ColumnHeaderContextMenu=\"{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}\" ColumnHeaderTemplate=\"{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}\" ColumnHeaderTemplateSelector=\"{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}\" ColumnHeaderToolTip=\"{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}\" Columns=\"{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}\"/>\n              </ScrollViewer>\n              <ScrollContentPresenter x:Name=\"PART_ScrollContentPresenter\" Grid.Row=\"1\" Grid.RowSpan=\"2\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\" CanContentScroll=\"{TemplateBinding CanContentScroll}\" Margin=\"{TemplateBinding Padding}\" KeyboardNavigation.DirectionalNavigation=\"Local\"/>\n              <Rectangle x:Name=\"Corner\" Grid.Row=\"2\" Grid.Column=\"1\" Fill=\"{DynamicResource Brush.Track.Normal}\" IsEnabled=\"False\" Opacity=\"0\"/>\n              <ScrollBar x:Name=\"PART_VerticalScrollBar\" Grid.Row=\"1\" Grid.Column=\"1\" Visibility=\"{TemplateBinding ComputedVerticalScrollBarVisibility}\" Orientation=\"Vertical\" ViewportSize=\"{TemplateBinding ViewportHeight}\" Maximum=\"{TemplateBinding ScrollableHeight}\" Minimum=\"0.0\" Value=\"{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}\" Opacity=\"0\"/>\n              <ScrollBar x:Name=\"PART_HorizontalScrollBar\" Grid.Row=\"2\" Grid.Column=\"0\" Visibility=\"{TemplateBinding ComputedHorizontalScrollBarVisibility}\" Orientation=\"Horizontal\" ViewportSize=\"{TemplateBinding ViewportWidth}\" Maximum=\"{TemplateBinding ScrollableWidth}\" Minimum=\"0.0\" Value=\"{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}\" Opacity=\"0\"/>\n            </Grid>\n          </Border>\n          <ControlTemplate.Resources>\n            <Storyboard x:Key=\"Anim.ShowBars\" BeginTime=\"0:0:0.1\">\n              <DoubleAnimation Storyboard.TargetName=\"PART_HorizontalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.5\" DecelerationRatio=\"0.5\"/>\n              <DoubleAnimation Storyboard.TargetName=\"PART_VerticalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.5\" DecelerationRatio=\"0.5\"/>\n            </Storyboard>\n            <Storyboard x:Key=\"Anim.HideBars\" BeginTime=\"0:0:2\">\n              <DoubleAnimation Storyboard.TargetName=\"PART_HorizontalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n              <DoubleAnimation Storyboard.TargetName=\"PART_VerticalScrollBar\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n            </Storyboard>\n            <Storyboard x:Key=\"Anim.ShowCorner\" BeginTime=\"0:0:0.1\">\n              <DoubleAnimation Storyboard.TargetName=\"Corner\" Storyboard.TargetProperty=\"Opacity\" To=\"1\" Duration=\"0:0:0.1\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n            </Storyboard>\n            <Storyboard x:Key=\"Anim.HideCorner\" BeginTime=\"0:0:2\">\n              <DoubleAnimation Storyboard.TargetName=\"Corner\" Storyboard.TargetProperty=\"Opacity\" To=\"0\" Duration=\"0:0:0.15\" AccelerationRatio=\"0.75\" DecelerationRatio=\"0.25\"/>\n            </Storyboard>\n          </ControlTemplate.Resources>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\">\n              <Trigger.EnterActions>\n                <BeginStoryboard Storyboard=\"{StaticResource Anim.ShowBars}\"/>\n              </Trigger.EnterActions>\n              <Trigger.ExitActions>\n                <BeginStoryboard Storyboard=\"{StaticResource Anim.HideBars}\"/>\n              </Trigger.ExitActions>\n            </Trigger>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"PART_HorizontalScrollBar\">\n              <Setter Property=\"IsEnabled\" Value=\"True\" TargetName=\"Corner\"/>\n            </Trigger>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"PART_VerticalScrollBar\">\n              <Setter Property=\"IsEnabled\" Value=\"True\" TargetName=\"Corner\"/>\n            </Trigger>\n            <Trigger Property=\"IsEnabled\" Value=\"True\" SourceName=\"Corner\">\n              <Trigger.EnterActions>\n                <BeginStoryboard Storyboard=\"{StaticResource Anim.ShowCorner}\"/>\n              </Trigger.EnterActions>\n              <Trigger.ExitActions>\n                <BeginStoryboard Storyboard=\"{StaticResource Anim.HideCorner}\"/>\n              </Trigger.ExitActions>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ListView\" TargetType=\"ListView\">\n    <ScrollViewer Style=\"{StaticResource Style.GridView.Scroll}\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\" Focusable=\"False\">\n      <ItemsPresenter />\n    </ScrollViewer>\n  </ControlTemplate>\n  <Style TargetType=\"ListView\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"ScrollViewer.HorizontalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.VerticalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.CanContentScroll\" Value=\"True\"/>\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n    <Setter Property=\"VirtualizingPanel.VirtualizationMode\" Value=\"Recycling\"/>\n    <Setter Property=\"VirtualizingPanel.ScrollUnit\" Value=\"Pixel\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ListView}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ListViewItem -->\n  <ControlTemplate x:Key=\"Template.ListViewItem\" TargetType=\"ListViewItem\">\n    <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <GridViewRowPresenter />\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsSelected\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Selected}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsMouseOver\" Value=\"True\"/>\n          <Condition Property=\"IsSelected\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.SelectedOver}\" TargetName=\"Border\"/>\n      </MultiTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ListViewItem\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ListView}}}\"/>\n    <Setter Property=\"Padding\" Value=\"0,8.5\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ListViewItem}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Inner.Uniform}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- GridViewColumnHeader -->\n  <Style x:Key=\"Style.GridViewColumnHeader.Gripper\" TargetType=\"Thumb\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Thumb\">\n          <Border Background=\"Transparent\" Margin=\"-12,0\">\n            <Rectangle x:Name=\"Rect\" Fill=\"{TemplateBinding BorderBrush}\" Width=\"1\" Margin=\"12,0\"/>\n          </Border>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Rect\"/>\n              <Setter Property=\"Width\" Value=\"2\" TargetName=\"Rect\"/>\n              <Setter Property=\"Margin\" Value=\"11.5,0\" TargetName=\"Rect\"/>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n    <Style.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"True\">\n        <Setter Property=\"Cursor\" Value=\"ScrollWE\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n  <ControlTemplate x:Key=\"Template.GridViewColumnHeader.Normal\" TargetType=\"GridViewColumnHeader\">\n    <Grid>\n      <Border x:Name=\"HeaderBorder\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\"/>\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n      <Thumb x:Name=\"PART_HeaderGripper\" Style=\"{StaticResource Style.GridViewColumnHeader.Gripper}\" BorderBrush=\"{TemplateBinding BorderBrush}\" HorizontalAlignment=\"Right\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Over}\" TargetName=\"HeaderBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Pressed}\" TargetName=\"HeaderBorder\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.GridViewColumnHeader.Floating\" TargetType=\"GridViewColumnHeader\">\n    <Canvas x:Name=\"PART_FloatingHeaderCanvas\">\n      <Rectangle Width=\"{TemplateBinding ActualWidth}\" Height=\"{TemplateBinding ActualHeight}\" Fill=\"#7F7F7F7F\"/>\n    </Canvas>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.GridViewColumnHeader.Padding\" TargetType=\"GridViewColumnHeader\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\"/>\n  </ControlTemplate>\n  <Style TargetType=\"GridViewColumnHeader\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Header.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"0,0,0,1\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Padding\" Value=\"6,5\"/>\n    <Style.Triggers>\n      <Trigger Property=\"Role\" Value=\"Normal\">\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.GridViewColumnHeader.Normal}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"Floating\">\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.GridViewColumnHeader.Floating}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"Padding\">\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.GridViewColumnHeader.Padding}\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ComboBox -->\n  <Style x:Key=\"Style.ComboBox.Toggle\" TargetType=\"ToggleButton\" BasedOn=\"{StaticResource Style.Expander.Toggle}\"/>\n  <ControlTemplate x:Key=\"Template.ComboBox.TextScroll\" TargetType=\"ScrollViewer\">\n    <Border Background=\"Transparent\" Padding=\"{TemplateBinding Padding}\">\n      <ScrollContentPresenter />\n    </Border>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.ComboBox.Text\" TargetType=\"TextBox\">\n    <ScrollViewer x:Name=\"PART_ContentHost\" Template=\"{StaticResource Template.ComboBox.TextScroll}\" Padding=\"{TemplateBinding Padding}\" Foreground=\"{TemplateBinding Foreground}\" Focusable=\"False\" HorizontalScrollBarVisibility=\"Hidden\" VerticalScrollBarVisibility=\"Disabled\"/>\n  </ControlTemplate>\n  <Geometry x:Key=\"Geometry.ComboBox.Arrow\">M0,0L6,6 12,0</Geometry>\n  <ControlTemplate x:Key=\"Template.ComboBox\" TargetType=\"ComboBox\">\n    <Grid>\n      <ToggleButton x:Name=\"DropDownButton\" Style=\"{StaticResource Style.ComboBox.Toggle}\" Foreground=\"{TemplateBinding Foreground}\" IsChecked=\"{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\" IsTabStop=\"False\">\n        <Grid>\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"*\"/>\n            <ColumnDefinition Width=\"Auto\"/>\n          </Grid.ColumnDefinitions>\n          <Border x:Name=\"Border\" Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border1}\"/>\n          <Grid Grid.Column=\"0\" Margin=\"2,0\">\n            <ContentPresenter x:Name=\"SelectionBoxItemHost\" ContentSource=\"SelectionBoxItem\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"{TemplateBinding Padding}\"/>\n            <TextBlock x:Name=\"Placeholder\" Text=\"{Binding (local:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}\" Style=\"{DynamicResource Style.TextBox.Placeholder}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"{TemplateBinding Padding}\" Visibility=\"Collapsed\"/>\n          </Grid>\n          <Path x:Name=\"Arrow\" Grid.Column=\"1\" Data=\"{StaticResource Geometry.ComboBox.Arrow}\" Stroke=\"{DynamicResource Brush.Glyph.Normal}\" VerticalAlignment=\"Center\" Margin=\"10,1,10,0\" IsHitTestVisible=\"False\">\n            <Path.RenderTransform>\n              <TranslateTransform />\n            </Path.RenderTransform>\n          </Path>\n        </Grid>\n      </ToggleButton>\n      <Popup x:Name=\"PART_Popup\" IsOpen=\"{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}\" Focusable=\"False\" Placement=\"Bottom\" PopupAnimation=\"Slide\" AllowsTransparency=\"True\">\n        <Border x:Name=\"DropDownBorder\" Background=\"{DynamicResource Brush.Background.Popup}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1,0,1,1\" CornerRadius=\"{DynamicResource Corner.Border1.Bottom}\" MinWidth=\"{TemplateBinding ActualWidth}\" MaxHeight=\"{TemplateBinding MaxDropDownHeight}\">\n          <ScrollViewer Focusable=\"False\" Padding=\"0,6\" KeyboardNavigation.TabNavigation=\"Cycle\" KeyboardNavigation.DirectionalNavigation=\"Contained\">\n            <ItemsPresenter />\n          </ScrollViewer>\n        </Border>\n      </Popup>\n    </Grid>\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Expand\">\n        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Y\">\n          <EasingDoubleKeyFrame KeyTime=\"0:0:0.1\" Value=\"2\"/>\n          <EasingDoubleKeyFrame KeyTime=\"0:0:0.3\" Value=\"0\">\n            <EasingDoubleKeyFrame.EasingFunction>\n              <CubicEase EasingMode=\"EaseOut\"/>\n            </EasingDoubleKeyFrame.EasingFunction>\n          </EasingDoubleKeyFrame>\n        </DoubleAnimationUsingKeyFrames>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"SelectedIndex\" Value=\"-1\">\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\" SourceName=\"DropDownButton\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Pressed}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsDropDownOpen\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand}\"/>\n        </Trigger.EnterActions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Pressed}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2.Top}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Arrow\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.ComboBox.Editable\" TargetType=\"ComboBox\">\n    <Grid>\n      <ToggleButton x:Name=\"DropDownButton\" Style=\"{StaticResource Style.ComboBox.Toggle}\" Foreground=\"{TemplateBinding Foreground}\" IsChecked=\"{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\" IsTabStop=\"False\">\n        <Grid>\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"*\"/>\n            <ColumnDefinition Width=\"Auto\"/>\n          </Grid.ColumnDefinitions>\n          <Border x:Name=\"Base\" Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding Background}\" CornerRadius=\"{DynamicResource Corner.Border0}\"/>\n          <Border x:Name=\"ArrowBorder\" Grid.Column=\"1\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1,0,0,0\" CornerRadius=\"{DynamicResource Corner.Border0.Right}\"/>\n          <Border x:Name=\"Border\" Grid.ColumnSpan=\"2\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border1}\" IsHitTestVisible=\"False\"/>\n          <TextBox x:Name=\"PART_EditableTextBox\" Template=\"{StaticResource Template.ComboBox.Text}\" Foreground=\"{TemplateBinding Foreground}\" IsReadOnly=\"{TemplateBinding IsReadOnly}\" Padding=\"{TemplateBinding Padding}\" CaretBrush=\"{TemplateBinding Foreground}\" SelectionBrush=\"{DynamicResource Brush.Background.Checked}\" SelectionOpacity=\"0.5\" FocusVisualStyle=\"{x:Null}\"/>\n          <Decorator Grid.Column=\"0\" Margin=\"2,0\">\n            <TextBlock x:Name=\"Placeholder\" Text=\"{Binding (local:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}\" Style=\"{DynamicResource Style.TextBox.Placeholder}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"{TemplateBinding Padding}\" Visibility=\"Collapsed\"/>\n          </Decorator>\n          <Path x:Name=\"Arrow\" Grid.Column=\"1\" Data=\"{StaticResource Geometry.ComboBox.Arrow}\" Stroke=\"{DynamicResource Brush.Glyph.Normal}\" VerticalAlignment=\"Center\" Margin=\"10,1,10,0\" IsHitTestVisible=\"False\">\n            <Path.RenderTransform>\n              <TranslateTransform />\n            </Path.RenderTransform>\n          </Path>\n        </Grid>\n      </ToggleButton>\n      <Popup x:Name=\"PART_Popup\" IsOpen=\"{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}\" Focusable=\"False\" Placement=\"Bottom\" PopupAnimation=\"Slide\" AllowsTransparency=\"True\">\n        <Border x:Name=\"DropDownBorder\" Background=\"{DynamicResource Brush.Background.Popup}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1,0,1,1\" CornerRadius=\"{DynamicResource Corner.Border1.Bottom}\" MinWidth=\"{TemplateBinding ActualWidth}\" MaxHeight=\"{TemplateBinding MaxDropDownHeight}\">\n          <ScrollViewer Focusable=\"False\" Padding=\"0,6\" KeyboardNavigation.TabNavigation=\"Cycle\" KeyboardNavigation.DirectionalNavigation=\"Contained\">\n            <ItemsPresenter />\n          </ScrollViewer>\n        </Border>\n      </Popup>\n    </Grid>\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Expand\">\n        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Y\">\n          <EasingDoubleKeyFrame KeyTime=\"0:0:0.1\" Value=\"2\"/>\n          <EasingDoubleKeyFrame KeyTime=\"0:0:0.3\" Value=\"0\">\n            <EasingDoubleKeyFrame.EasingFunction>\n              <CubicEase EasingMode=\"EaseOut\"/>\n            </EasingDoubleKeyFrame.EasingFunction>\n          </EasingDoubleKeyFrame>\n        </DoubleAnimationUsingKeyFrames>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"Text\" Value=\"\">\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ArrowBorder\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Over}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\" SourceName=\"DropDownButton\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Pressed}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsDropDownOpen\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand}\"/>\n        </Trigger.EnterActions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Focused}\" TargetName=\"Base\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2.Top}\" TargetName=\"Border\"/>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Pressed}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsKeyboardFocused\" Value=\"True\" SourceName=\"PART_EditableTextBox\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Edit}\" TargetName=\"Base\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Arrow\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ComboBox\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"1\"/>\n    <Setter Property=\"Padding\" Value=\"6,7\"/>\n    <Setter Property=\"MaxDropDownHeight\" Value=\"200\"/>\n    <Setter Property=\"ScrollViewer.HorizontalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.VerticalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.CanContentScroll\" Value=\"False\"/>\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ComboBox}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n    <Style.Triggers>\n      <Trigger Property=\"IsEditable\" Value=\"True\">\n        <Setter Property=\"IsTabStop\" Value=\"False\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.ComboBox.Editable}\"/>\n        <Setter Property=\"FocusVisualStyle\" Value=\"{x:Null}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n\n  <!-- ComboBoxItem -->\n  <ControlTemplate x:Key=\"Template.ComboBoxItem\" TargetType=\"ComboBoxItem\">\n    <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsSelected\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Selected}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsMouseOver\" Value=\"True\"/>\n          <Condition Property=\"IsSelected\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.SelectedOver}\" TargetName=\"Border\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ComboBoxItem\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}\"/>\n    <Setter Property=\"Padding\" Value=\"12,8.5\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ComboBoxItem}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Inner.Uniform}\"/>\n  </Style>\n\n  <!-- TabControl -->\n  <ControlTemplate x:Key=\"Template.TabControl\" TargetType=\"TabControl\">\n    <Grid KeyboardNavigation.TabNavigation=\"Local\">\n      <Grid.RowDefinitions>\n        <RowDefinition x:Name=\"Row0\"/>\n        <RowDefinition x:Name=\"Row1\"/>\n      </Grid.RowDefinitions>\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition x:Name=\"Col0\"/>\n        <ColumnDefinition x:Name=\"Col1\"/>\n      </Grid.ColumnDefinitions>\n      <TabPanel x:Name=\"HeaderPanel\" Panel.ZIndex=\"1\" Background=\"Transparent\" IsItemsHost=\"True\" KeyboardNavigation.TabIndex=\"1\"/>\n      <Border x:Name=\"SelectedContentBorder\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\" KeyboardNavigation.DirectionalNavigation=\"Contained\" KeyboardNavigation.TabIndex=\"2\" KeyboardNavigation.TabNavigation=\"Local\">\n        <ContentPresenter x:Name=\"PART_SelectedContentHost\" ContentSource=\"SelectedContent\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n      </Border>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"TabStripPlacement\" Value=\"Top\">\n        <Setter Property=\"Height\" Value=\"Auto\" TargetName=\"Row0\"/>\n        <Setter Property=\"Height\" Value=\"*\" TargetName=\"Row1\"/>\n        <Setter Property=\"Width\" Value=\"*\" TargetName=\"Col0\"/>\n        <Setter Property=\"Width\" Value=\"0\" TargetName=\"Col1\"/>\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Row\" Value=\"1\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0.Bottom}\" TargetName=\"SelectedContentBorder\"/>\n      </Trigger>\n      <Trigger Property=\"TabStripPlacement\" Value=\"Bottom\">\n        <Setter Property=\"Height\" Value=\"*\" TargetName=\"Row0\"/>\n        <Setter Property=\"Height\" Value=\"Auto\" TargetName=\"Row1\"/>\n        <Setter Property=\"Width\" Value=\"*\" TargetName=\"Col0\"/>\n        <Setter Property=\"Width\" Value=\"0\" TargetName=\"Col1\"/>\n        <Setter Property=\"Grid.Row\" Value=\"1\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0.Top}\" TargetName=\"SelectedContentBorder\"/>\n      </Trigger>\n      <Trigger Property=\"TabStripPlacement\" Value=\"Left\">\n        <Setter Property=\"Height\" Value=\"*\" TargetName=\"Row0\"/>\n        <Setter Property=\"Height\" Value=\"0\" TargetName=\"Row1\"/>\n        <Setter Property=\"Width\" Value=\"Auto\" TargetName=\"Col0\"/>\n        <Setter Property=\"Width\" Value=\"*\" TargetName=\"Col1\"/>\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"Grid.Column\" Value=\"1\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0.Right}\" TargetName=\"SelectedContentBorder\"/>\n      </Trigger>\n      <Trigger Property=\"TabStripPlacement\" Value=\"Right\">\n        <Setter Property=\"Height\" Value=\"*\" TargetName=\"Row0\"/>\n        <Setter Property=\"Height\" Value=\"0\" TargetName=\"Row1\"/>\n        <Setter Property=\"Width\" Value=\"*\" TargetName=\"Col0\"/>\n        <Setter Property=\"Width\" Value=\"Auto\" TargetName=\"Col1\"/>\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Column\" Value=\"1\" TargetName=\"HeaderPanel\"/>\n        <Setter Property=\"Grid.Row\" Value=\"0\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"Grid.Column\" Value=\"0\" TargetName=\"SelectedContentBorder\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border0.Left}\" TargetName=\"SelectedContentBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"TabControl\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TabControl.Normal}\"/>\n    <Setter Property=\"Padding\" Value=\"12\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.TabControl}\"/>\n  </Style>\n\n  <!-- TabItem -->\n  <ControlTemplate x:Key=\"Template.TabItem\" TargetType=\"TabItem\">\n    <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding Background}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter x:Name=\"ContentHost\" ContentSource=\"Header\" TextElement.FontSize=\"{DynamicResource Font.Size.Header}\" TextElement.Foreground=\"{DynamicResource Brush.Glyph.Normal}\"/>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Panel.ZIndex\" Value=\"1\"/>\n        <Setter Property=\"TextElement.Foreground\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"ContentHost\"/>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TabControl.Over}\"/>\n      </Trigger>\n      <Trigger Property=\"IsSelected\" Value=\"True\">\n        <Setter Property=\"Panel.ZIndex\" Value=\"2\"/>\n        <Setter Property=\"TextElement.Foreground\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"ContentHost\"/>\n        <Setter Property=\"Background\" Value=\"{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.TabControl.Selected}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"TextElement.Foreground\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"ContentHost\"/>\n      </Trigger>\n      <DataTrigger Binding=\"{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}\" Value=\"Top\">\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2.Top}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"0,2,0,0\" TargetName=\"Border\"/>\n        <Setter Property=\"Margin\" Value=\"0,-2,0,0\" TargetName=\"ContentHost\"/>\n      </DataTrigger>\n      <DataTrigger Binding=\"{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}\" Value=\"Bottom\">\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2.Bottom}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"0,0,0,2\" TargetName=\"Border\"/>\n        <Setter Property=\"Margin\" Value=\"0,0,0,-2\" TargetName=\"ContentHost\"/>\n      </DataTrigger>\n      <DataTrigger Binding=\"{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}\" Value=\"Left\">\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2.Left}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"2,0,0,0\" TargetName=\"Border\"/>\n        <Setter Property=\"Margin\" Value=\"-2,0,0,0\" TargetName=\"ContentHost\"/>\n      </DataTrigger>\n      <DataTrigger Binding=\"{Binding TabStripPlacement, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}\" Value=\"Right\">\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2.Right}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"0,0,2,0\" TargetName=\"Border\"/>\n        <Setter Property=\"Margin\" Value=\"0,0,-2,0\" TargetName=\"ContentHost\"/>\n      </DataTrigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"TabItem\" BasedOn=\"{StaticResource {x:Type HeaderedContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Foreground\" Value=\"{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type TabControl}}}\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"Padding\" Value=\"12,7.5\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.TabItem}\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Inner.Uniform}\"/>\n  </Style>\n\n  <!-- TreeView -->\n  <ControlTemplate x:Key=\"Template.TreeView\" TargetType=\"TreeView\">\n    <ScrollViewer Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\" Focusable=\"False\">\n      <ItemsPresenter Tag=\"12\"/>\n    </ScrollViewer>\n  </ControlTemplate>\n  <Style TargetType=\"TreeView\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"Stretch\"/>\n    <Setter Property=\"ScrollViewer.HorizontalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.VerticalScrollBarVisibility\" Value=\"Auto\"/>\n    <Setter Property=\"ScrollViewer.CanContentScroll\" Value=\"False\"/>\n    <Setter Property=\"ScrollViewer.PanningMode\" Value=\"VerticalFirst\"/>\n    <Setter Property=\"FocusVisualStyle\" Value=\"{StaticResource Style.Focus.Outer.Uniform}\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.TreeView}\"/>\n  </Style>\n\n  <!-- TreeViewItem -->\n  <Style x:Key=\"Style.TreeViewItem.Toggle\" TargetType=\"ToggleButton\" BasedOn=\"{StaticResource Style.Expander.Toggle}\"/>\n  <Geometry x:Key=\"Geometry.TreeViewItem.Arrow\">M0,0L6,6 0,12</Geometry>\n  <ControlTemplate x:Key=\"Template.TreeViewItem.NoAnim\" TargetType=\"TreeViewItem\">\n    <Grid>\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"*\"/>\n      </Grid.RowDefinitions>\n      <Border x:Name=\"Border\" Grid.Row=\"0\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\">\n        <Grid>\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"Auto\"/>\n            <ColumnDefinition Width=\"Auto\"/>\n            <ColumnDefinition Width=\"*\"/>\n          </Grid.ColumnDefinitions>\n          <Border x:Name=\"Focus\" Grid.ColumnSpan=\"3\" BorderThickness=\"{DynamicResource Border.Focus}\" BorderBrush=\"{DynamicResource Brush.Border.Focus}\" CornerRadius=\"{DynamicResource Corner.Focus}\" Visibility=\"Collapsed\"/>\n          <Decorator x:Name=\"CurrentIndent\" Grid.Column=\"0\" Width=\"{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}, AncestorLevel=1}}\"/>\n          <Decorator x:Name=\"ChildrenIndent\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\"/>\n          <ToggleButton x:Name=\"ExpandButton\" Grid.Column=\"1\" Style=\"{StaticResource Style.TreeViewItem.Toggle}\" IsChecked=\"{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\" IsTabStop=\"False\" Width=\"32\" Margin=\"-8,0\">\n            <Path x:Name=\"Arrow\" Data=\"{StaticResource Geometry.TreeViewItem.Arrow}\" Stroke=\"{DynamicResource Brush.TreeView.Collapsed}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" IsHitTestVisible=\"False\" RenderTransformOrigin=\"0.5,0.5\"/>\n          </ToggleButton>\n          <ContentPresenter x:Name=\"PART_Header\" Grid.Column=\"2\" ContentSource=\"Header\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n        </Grid>\n      </Border>\n      <Decorator x:Name=\"ItemsBorder\" Grid.Row=\"1\" Grid.Column=\"0\" Grid.ColumnSpan=\"3\" Visibility=\"Collapsed\">\n        <ItemsPresenter x:Name=\"ItemsHost\" Tag=\"{Binding ActualWidth, ElementName=ChildrenIndent}\"/>\n      </Decorator>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"HasItems\" Value=\"False\">\n        <Setter Property=\"Visibility\" Value=\"Hidden\" TargetName=\"ExpandButton\"/>\n      </Trigger>\n      <Trigger Property=\"IsExpanded\" Value=\"True\">\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.TreeView.Expanded}\" TargetName=\"Arrow\"/>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"ItemsBorder\"/>\n        <Setter Property=\"RenderTransform\" TargetName=\"Arrow\">\n          <Setter.Value>\n            <RotateTransform Angle=\"90\"/>\n          </Setter.Value>\n        </Setter>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"Border\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ExpandButton\">\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.TreeView.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ExpandButton\"/>\n          <Condition Property=\"IsSelected\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.TreeView.SelectedOver}\" TargetName=\"Arrow\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsSelected\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Selected}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Path=(local:Element.IsFocusEngaged), RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding Path=IsKeyboardFocused, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Focus\"/>\n      </MultiDataTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.TreeViewItem\" TargetType=\"TreeViewItem\">\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Loaded\">\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"Root\" Storyboard.TargetProperty=\"Tag\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"1\"/>\n        </ObjectAnimationUsingKeyFrames>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand.Loaded\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"90\" Duration=\"0\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ItemsBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ItemsHost\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0\"/>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Expand\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"90\" Duration=\"0:0:0.15\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ItemsBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ItemsHost\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"1\" Duration=\"0:0:0.2\">\n          <DoubleAnimation.EasingFunction>\n            <BackEase EasingMode=\"EaseOut\" Amplitude=\"0.2\"/>\n          </DoubleAnimation.EasingFunction>\n        </DoubleAnimation>\n      </Storyboard>\n      <Storyboard x:Key=\"Anim.Collapse\">\n        <DoubleAnimation Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Angle\" To=\"0\" Duration=\"0:0:0.2\"/>\n        <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ItemsBorder\" Storyboard.TargetProperty=\"Visibility\">\n          <DiscreteObjectKeyFrame KeyTime=\"0:0:0.2\" Value=\"{x:Static Visibility.Collapsed}\"/>\n        </ObjectAnimationUsingKeyFrames>\n        <DoubleAnimation Storyboard.TargetName=\"ItemsHost\" Storyboard.TargetProperty=\"RenderTransform.ScaleY\" To=\"0\" Duration=\"0:0:0.2\" AccelerationRatio=\"0.5\"/>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <Grid x:Name=\"Root\" Tag=\"0\">\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"Auto\"/>\n        <RowDefinition Height=\"*\"/>\n      </Grid.RowDefinitions>\n      <Border x:Name=\"Border\" Grid.Row=\"0\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\">\n        <Grid>\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"Auto\"/>\n            <ColumnDefinition Width=\"Auto\"/>\n            <ColumnDefinition Width=\"*\"/>\n          </Grid.ColumnDefinitions>\n          <Border x:Name=\"Focus\" Grid.ColumnSpan=\"3\" BorderThickness=\"{DynamicResource Border.Focus}\" BorderBrush=\"{DynamicResource Brush.Border.Focus}\" CornerRadius=\"{DynamicResource Corner.Focus}\" Visibility=\"Collapsed\"/>\n          <Decorator x:Name=\"CurrentIndent\" Grid.Column=\"0\" Width=\"{Binding Tag, RelativeSource={RelativeSource AncestorType={x:Type ItemsPresenter}, AncestorLevel=1}}\"/>\n          <Decorator x:Name=\"ChildrenIndent\" Grid.Column=\"0\" Grid.ColumnSpan=\"2\"/>\n          <ToggleButton x:Name=\"ExpandButton\" Grid.Column=\"1\" Style=\"{StaticResource Style.TreeViewItem.Toggle}\" IsChecked=\"{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\" IsTabStop=\"False\" Width=\"32\" Margin=\"-8,0\">\n            <Path x:Name=\"Arrow\" Data=\"{StaticResource Geometry.TreeViewItem.Arrow}\" Stroke=\"{DynamicResource Brush.TreeView.Collapsed}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" IsHitTestVisible=\"False\" RenderTransformOrigin=\"0.5,0.5\">\n              <Path.RenderTransform>\n                <RotateTransform />\n              </Path.RenderTransform>\n            </Path>\n          </ToggleButton>\n          <ContentPresenter x:Name=\"PART_Header\" Grid.Column=\"2\" ContentSource=\"Header\" HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n        </Grid>\n      </Border>\n      <Decorator x:Name=\"ItemsBorder\" Grid.Row=\"1\" Grid.Column=\"0\" Grid.ColumnSpan=\"3\" Visibility=\"Collapsed\">\n        <ItemsPresenter x:Name=\"ItemsHost\" Tag=\"{Binding ActualWidth, ElementName=ChildrenIndent}\" RenderTransformOrigin=\"0.5,0\">\n          <ItemsPresenter.RenderTransform>\n            <ScaleTransform ScaleY=\"0\"/>\n          </ItemsPresenter.RenderTransform>\n        </ItemsPresenter>\n      </Decorator>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <EventTrigger RoutedEvent=\"FrameworkElement.Loaded\" SourceName=\"Root\">\n        <BeginStoryboard Storyboard=\"{StaticResource Anim.Loaded}\"/>\n      </EventTrigger>\n      <Trigger Property=\"HasItems\" Value=\"False\">\n        <Setter Property=\"Visibility\" Value=\"Hidden\" TargetName=\"ExpandButton\"/>\n      </Trigger>\n      <Trigger Property=\"IsExpanded\" Value=\"True\">\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.TreeView.Expanded}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"0\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand.Loaded}\"/>\n        </MultiDataTrigger.EnterActions>\n      </MultiDataTrigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Tag, ElementName=Root}\" Value=\"1\"/>\n          <Condition Binding=\"{Binding IsExpanded, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <MultiDataTrigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand}\"/>\n        </MultiDataTrigger.EnterActions>\n        <MultiDataTrigger.ExitActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Collapse}\"/>\n        </MultiDataTrigger.ExitActions>\n      </MultiDataTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"Border\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ExpandButton\">\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.TreeView.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ExpandButton\"/>\n          <Condition Property=\"IsSelected\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.TreeView.SelectedOver}\" TargetName=\"Arrow\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsSelected\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.Item.Selected}\" TargetName=\"Border\"/>\n      </Trigger>\n      <MultiDataTrigger>\n        <MultiDataTrigger.Conditions>\n          <Condition Binding=\"{Binding Path=(local:Element.IsFocusEngaged), RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}\" Value=\"True\"/>\n          <Condition Binding=\"{Binding Path=IsKeyboardFocused, RelativeSource={RelativeSource Self}}\" Value=\"True\"/>\n        </MultiDataTrigger.Conditions>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Focus\"/>\n      </MultiDataTrigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"TreeViewItem\" BasedOn=\"{StaticResource {x:Type HeaderedItemsControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Foreground\" Value=\"{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"Padding\" Value=\"12,7\"/>\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}\"/>\n    <Setter Property=\"VerticalContentAlignment\" Value=\"{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type TreeView}}}\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.TreeViewItem}\"/>\n  </Style>\n\n  <!-- ToolBar Controls -->\n  <ControlTemplate x:Key=\"Template.ToolBar.Separator\" TargetType=\"Separator\">\n    <Rectangle Width=\"1\" Fill=\"{DynamicResource Brush.Border.Normal}\" Margin=\"5,2\"/>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ToolBar.Separator\" TargetType=\"Separator\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolBar.Separator}\"/>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ToolBar.Button\" TargetType=\"Button\">\n    <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\" CornerRadius=\"{DynamicResource Corner.Border0}\">\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Pressed}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ToolBar.Button\" TargetType=\"Button\" BasedOn=\"{StaticResource {x:Type Button}}\">\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"BorderThickness\" Value=\"0\"/>\n    <Setter Property=\"Padding\" Value=\"5\"/>\n    <Setter Property=\"Margin\" Value=\"1\"/>\n    <Setter Property=\"MinWidth\" Value=\"28\"/>\n    <Setter Property=\"HorizontalAlignment\" Value=\"Center\"/>\n    <Setter Property=\"VerticalAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolBar.Button}\"/>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ToolBar.Toggle\" TargetType=\"ToggleButton\">\n    <Grid>\n      <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border0}\"/>\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\" Margin=\"{TemplateBinding Padding}\"/>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Over}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Pressed}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsChecked\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.ToolBar.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"BorderThickness\" Value=\"1\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border2}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ToolBar.Toggle\" TargetType=\"ToggleButton\" BasedOn=\"{StaticResource {x:Type ToggleButton}}\">\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"BorderThickness\" Value=\"0\"/>\n    <Setter Property=\"Padding\" Value=\"5\"/>\n    <Setter Property=\"Margin\" Value=\"1\"/>\n    <Setter Property=\"MinWidth\" Value=\"28\"/>\n    <Setter Property=\"HorizontalAlignment\" Value=\"Center\"/>\n    <Setter Property=\"VerticalAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolBar.Toggle}\"/>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ToolBar.ComboBox\" TargetType=\"ComboBox\">\n    <Grid>\n      <ToggleButton x:Name=\"DropDownButton\" Style=\"{StaticResource Style.ComboBox.Toggle}\" Foreground=\"{TemplateBinding Foreground}\" IsChecked=\"{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\" IsTabStop=\"False\">\n        <Grid>\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"*\"/>\n            <ColumnDefinition Width=\"Auto\"/>\n          </Grid.ColumnDefinitions>\n          <Border x:Name=\"Base\" Grid.ColumnSpan=\"2\" Background=\"{TemplateBinding Background}\" CornerRadius=\"{DynamicResource Corner.Border0}\"/>\n          <Border x:Name=\"ArrowBorder\" Grid.Column=\"1\" Background=\"{DynamicResource Brush.ComboBox.Normal}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1,0,0,0\" CornerRadius=\"{DynamicResource Corner.Border0.Right}\"/>\n          <Border x:Name=\"Border\" Grid.ColumnSpan=\"2\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border1}\" IsHitTestVisible=\"False\"/>\n          <Grid Grid.Column=\"0\" Margin=\"2,0\">\n            <ContentPresenter x:Name=\"SelectionBoxItemHost\" ContentSource=\"SelectionBoxItem\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"{TemplateBinding Padding}\"/>\n            <TextBlock x:Name=\"Placeholder\" Text=\"{Binding (local:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}\" Style=\"{DynamicResource Style.TextBox.Placeholder}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Margin=\"{TemplateBinding Padding}\" Visibility=\"Collapsed\"/>\n          </Grid>\n          <TextBox x:Name=\"PART_EditableTextBox\" Template=\"{StaticResource Template.ComboBox.Text}\" Foreground=\"{TemplateBinding Foreground}\" IsReadOnly=\"{TemplateBinding IsReadOnly}\" Padding=\"{TemplateBinding Padding}\" CaretBrush=\"{TemplateBinding Foreground}\" SelectionBrush=\"{DynamicResource Brush.Background.Checked}\" SelectionOpacity=\"0.5\" Visibility=\"Hidden\"/>\n          <Path x:Name=\"Arrow\" Grid.Column=\"1\" Data=\"{StaticResource Geometry.ComboBox.Arrow}\" Stroke=\"{DynamicResource Brush.Glyph.Normal}\" VerticalAlignment=\"Center\" Margin=\"7.5,1,7.5,0\" IsHitTestVisible=\"False\">\n            <Path.RenderTransform>\n              <TranslateTransform />\n            </Path.RenderTransform>\n          </Path>\n        </Grid>\n      </ToggleButton>\n      <Popup x:Name=\"PART_Popup\" IsOpen=\"{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}\" Focusable=\"False\" Placement=\"Bottom\" PopupAnimation=\"Slide\" AllowsTransparency=\"True\">\n        <Border x:Name=\"DropDownBorder\" Background=\"{DynamicResource Brush.Background.Popup}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1,0,1,1\" CornerRadius=\"{DynamicResource Corner.Border1.Bottom}\" MinWidth=\"{TemplateBinding ActualWidth}\" MaxHeight=\"{TemplateBinding MaxDropDownHeight}\">\n          <ScrollViewer Focusable=\"False\" Padding=\"0,6\" KeyboardNavigation.TabNavigation=\"Cycle\" KeyboardNavigation.DirectionalNavigation=\"Contained\">\n            <ItemsPresenter />\n          </ScrollViewer>\n        </Border>\n      </Popup>\n    </Grid>\n    <ControlTemplate.Resources>\n      <Storyboard x:Key=\"Anim.Expand\">\n        <DoubleAnimationUsingKeyFrames Storyboard.TargetName=\"Arrow\" Storyboard.TargetProperty=\"RenderTransform.Y\">\n          <EasingDoubleKeyFrame KeyTime=\"0:0:0.1\" Value=\"2\"/>\n          <EasingDoubleKeyFrame KeyTime=\"0:0:0.3\" Value=\"0\">\n            <EasingDoubleKeyFrame.EasingFunction>\n              <CubicEase EasingMode=\"EaseOut\"/>\n            </EasingDoubleKeyFrame.EasingFunction>\n          </EasingDoubleKeyFrame>\n        </DoubleAnimationUsingKeyFrames>\n      </Storyboard>\n    </ControlTemplate.Resources>\n    <ControlTemplate.Triggers>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEditable\" Value=\"False\"/>\n          <Condition Property=\"SelectedIndex\" Value=\"-1\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </MultiTrigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEditable\" Value=\"True\"/>\n          <Condition Property=\"Text\" Value=\"\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"Border\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Arrow\"/>\n      </Trigger>\n      <MultiTrigger>\n        <MultiTrigger.Conditions>\n          <Condition Property=\"IsEditable\" Value=\"False\"/>\n          <Condition Property=\"IsMouseOver\" Value=\"True\"/>\n        </MultiTrigger.Conditions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Over}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </MultiTrigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\" SourceName=\"ArrowBorder\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Over}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsPressed\" Value=\"True\" SourceName=\"DropDownButton\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Pressed}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsDropDownOpen\" Value=\"True\">\n        <Trigger.EnterActions>\n          <BeginStoryboard Storyboard=\"{StaticResource Anim.Expand}\"/>\n        </Trigger.EnterActions>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Focused}\" TargetName=\"Base\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n        <Setter Property=\"CornerRadius\" Value=\"{DynamicResource Corner.Border1.Top}\" TargetName=\"Border\"/>\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Pressed}\" TargetName=\"ArrowBorder\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"ArrowBorder\"/>\n      </Trigger>\n      <Trigger Property=\"IsEditable\" Value=\"True\">\n        <Setter Property=\"Visibility\" Value=\"Hidden\" TargetName=\"SelectionBoxItemHost\"/>\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"PART_EditableTextBox\"/>\n      </Trigger>\n      <Trigger Property=\"IsKeyboardFocused\" Value=\"True\" SourceName=\"PART_EditableTextBox\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Edit}\" TargetName=\"Base\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\" TargetName=\"Border\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\" TargetName=\"Border\"/>\n        <Setter Property=\"Stroke\" Value=\"{DynamicResource Brush.Glyph.Disabled}\" TargetName=\"Arrow\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ToolBar.ComboBox\" TargetType=\"ComboBox\" BasedOn=\"{StaticResource {x:Type ComboBox}}\">\n    <Style.Resources>\n      <Style TargetType=\"ComboBoxItem\" BasedOn=\"{StaticResource {x:Type ComboBoxItem}}\">\n        <Setter Property=\"Padding\" Value=\"10,7\"/>\n      </Style>\n    </Style.Resources>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ComboBox.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"1\"/>\n    <Setter Property=\"Padding\" Value=\"5,4.5\"/>\n    <Setter Property=\"Margin\" Value=\"1\"/>\n    <Setter Property=\"VerticalAlignment\" Value=\"Center\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolBar.ComboBox}\"/>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ToolBar.TextBox.Scroll\" TargetType=\"ScrollViewer\">\n    <ScrollContentPresenter Margin=\"{TemplateBinding Padding}\"/>\n  </ControlTemplate>\n  <ControlTemplate x:Key=\"Template.ToolBar.TextBox\" TargetType=\"TextBox\">\n    <Grid>\n      <Border x:Name=\"Border\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" CornerRadius=\"{DynamicResource Corner.Border1}\"/>\n      <Grid>\n        <Border x:Name=\"Placeholder\" Padding=\"{TemplateBinding Padding}\" Margin=\"2,0\" Visibility=\"Collapsed\">\n          <TextBlock Text=\"{Binding (local:Text.Placeholder), RelativeSource={RelativeSource TemplatedParent}}\" Style=\"{DynamicResource Style.TextBox.Placeholder}\"/>\n        </Border>\n        <ScrollViewer x:Name=\"PART_ContentHost\" Template=\"{StaticResource Template.ToolBar.TextBox.Scroll}\" Padding=\"{TemplateBinding Padding}\" Foreground=\"{TemplateBinding Foreground}\" Focusable=\"False\"/>\n      </Grid>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"Text\" Value=\"\">\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"Placeholder\"/>\n      </Trigger>\n      <Trigger Property=\"IsMouseOver\" Value=\"True\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Over}\"/>\n      </Trigger>\n      <Trigger Property=\"IsKeyboardFocused\" Value=\"True\">\n        <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Focused}\"/>\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Checked}\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"False\">\n        <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Disabled}\"/>\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style x:Key=\"Style.ToolBar.TextBox\" TargetType=\"TextBox\" BasedOn=\"{StaticResource {x:Type TextBox}}\">\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.TextBox.Normal}\"/>\n    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource Brush.Border.Normal}\"/>\n    <Setter Property=\"BorderThickness\" Value=\"{DynamicResource Border.Box}\"/>\n    <Setter Property=\"Padding\" Value=\"6,4.5\"/>\n    <Setter Property=\"Margin\" Value=\"1\"/>\n    <Setter Property=\"VerticalAlignment\" Value=\"Center\"/>\n    <Setter Property=\"TextAlignment\" Value=\"Left\"/>\n    <Setter Property=\"KeyboardNavigation.TabNavigation\" Value=\"None\"/>\n    <Setter Property=\"AllowDrop\" Value=\"True\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolBar.TextBox}\"/>\n  </Style>\n  <Style x:Key=\"Style.ToolBar.MenuItem\" TargetType=\"MenuItem\" BasedOn=\"{StaticResource {x:Type MenuItem}}\">\n    <Style.Triggers>\n      <Trigger Property=\"Role\" Value=\"TopLevelHeader\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Normal}\"/>\n        <Setter Property=\"Padding\" Value=\"6,5\"/>\n        <Setter Property=\"Margin\" Value=\"1,0\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.TopLevelHeader}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"TopLevelItem\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Normal}\"/>\n        <Setter Property=\"Padding\" Value=\"6,5\"/>\n        <Setter Property=\"Margin\" Value=\"1,0\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.TopLevelItem}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"SubmenuHeader\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Normal}\"/>\n        <Setter Property=\"Padding\" Value=\"0,7\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.SubmenuHeader}\"/>\n      </Trigger>\n      <Trigger Property=\"Role\" Value=\"SubmenuItem\">\n        <Setter Property=\"FontSize\" Value=\"{DynamicResource Font.Size.Normal}\"/>\n        <Setter Property=\"Padding\" Value=\"0,7\"/>\n        <Setter Property=\"Template\" Value=\"{StaticResource Template.MenuItem.SubmenuItem}\"/>\n      </Trigger>\n    </Style.Triggers>\n  </Style>\n  <Style x:Key=\"Style.ToolBar.Menu\" TargetType=\"Menu\" BasedOn=\"{StaticResource {x:Type Menu}}\">\n    <Style.Resources>\n      <Style TargetType=\"MenuItem\" BasedOn=\"{StaticResource Style.ToolBar.MenuItem}\"/>\n    </Style.Resources>\n  </Style>\n\n  <!-- ToolBar -->\n  <Geometry x:Key=\"Geometry.ToolBar.Thumb\">M2,1 C2,1.5522847 1.5522847,2 1,2 C0.44771525,2 0,1.5522847 0,1 C0,0.44771525 0.44771525,0 1,0 C1.5522847,0 2,0.44771525 2,1 z M6,1 C6,1.5522847 5.5522847,2 5,2 C4.4477153,2 4,1.5522847 4,1 C4,0.44771525 4.4477153,0 5,0 C5.5522847,0 6,0.44771525 6,1 z M2,5 C2,5.5522847 1.5522847,6 1,6 C0.44771525,6 0,5.5522847 0,5 C0,4.4477153 0.44771525,4 1,4 C1.5522847,4 2,4.4477153 2,5 z M6,5 C6,5.5522847 5.5522847,6 5,6 C4.4477153,6 4,5.5522847 4,5 C4,4.4477153 4.4477153,4 5,4 C5.5522847,4 6,4.4477153 6,5 z M2,9 C2,9.5522847 1.5522847,10 1,10 C0.44771525,10 0,9.5522847 0,9 C0,8.4477153 0.44771525,8 1,8 C1.5522847,8 2,8.4477153 2,9 z M6,9 C6,9.5522847 5.5522847,10 5,10 C4.4477153,10 4,9.5522847 4,9 C4,8.4477153 4.4477153,8 5,8 C5.5522847,8 6,8.4477153 6,9 z</Geometry>\n  <Geometry x:Key=\"Geometry.Toolbar.Overflow\">M2,1 C2,1.5522847 1.5522847,2 1,2 C0.44771525,2 0,1.5522847 0,1 C0,0.44771525 0.44771525,0 1,0 C1.5522847,0 2,0.44771525 2,1 z M8,1 C8,1.5522847 7.5522847,2 7,2 C6.4477153,2 6,1.5522847 6,1 C6,0.44771525 6.4477153,0 7,0 C7.5522847,0 8,0.44771525 8,1 z M14,1 C14,1.5522847 13.552285,2 13,2 C12.447715,2 12,1.5522847 12,1 C12,0.44771525 12.447715,0 13,0 C13.552285,0 14,0.44771525 14,1 z</Geometry>\n  <Style x:Key=\"Style.ToolBar.Thumb\" TargetType=\"Thumb\">\n    <Setter Property=\"Cursor\" Value=\"SizeAll\"/>\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"Thumb\">\n          <Grid Background=\"Transparent\">\n            <Path x:Name=\"DragThumb\" Data=\"{StaticResource Geometry.ToolBar.Thumb}\" Fill=\"{DynamicResource Brush.Border.Normal}\" Height=\"11\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Margin=\"6,1,8,1\" UseLayoutRounding=\"False\"/>\n          </Grid>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Border.Over}\" TargetName=\"DragThumb\"/>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <Style x:Key=\"Style.ToolBar.OverflowButton\" TargetType=\"ToggleButton\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"ToggleButton\">\n          <Grid x:Name=\"TemplateRoot\" Background=\"Transparent\">\n            <Path x:Name=\"Dots\" Data=\"{StaticResource Geometry.Toolbar.Overflow}\" Fill=\"{DynamicResource Brush.Glyph.Normal}\" VerticalAlignment=\"Center\" Margin=\"9,0\"/>\n          </Grid>\n          <ControlTemplate.Triggers>\n            <Trigger Property=\"IsMouseOver\" Value=\"True\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Dots\"/>\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Over}\" TargetName=\"TemplateRoot\"/>\n            </Trigger>\n            <Trigger Property=\"IsPressed\" Value=\"True\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Dots\"/>\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Pressed}\" TargetName=\"TemplateRoot\"/>\n            </Trigger>\n            <Trigger Property=\"IsChecked\" Value=\"True\">\n              <Setter Property=\"Fill\" Value=\"{DynamicResource Brush.Glyph.Over}\" TargetName=\"Dots\"/>\n              <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Pressed}\" TargetName=\"TemplateRoot\"/>\n            </Trigger>\n          </ControlTemplate.Triggers>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n  <ControlTemplate x:Key=\"Template.ToolBar\" TargetType=\"ToolBar\">\n    <Grid>\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"Auto\"/>\n        <ColumnDefinition Width=\"*\"/>\n        <ColumnDefinition Width=\"Auto\"/>\n      </Grid.ColumnDefinitions>\n      <Border Grid.ColumnSpan=\"4\" Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\"/>\n      <Thumb x:Name=\"ToolBarThumb\" Grid.Column=\"0\" Margin=\"0,2\" Style=\"{StaticResource Style.ToolBar.Thumb}\"/>\n      <ContentPresenter x:Name=\"ToolBarHeader\" Grid.Column=\"1\" ContentSource=\"Header\" VerticalAlignment=\"Center\" TextElement.Foreground=\"{DynamicResource Brush.Foreground.Placeholder}\" Margin=\"0,0,8,0\"/>\n      <ToolBarPanel x:Name=\"PART_ToolBarPanel\" Grid.Column=\"2\" IsItemsHost=\"true\" Margin=\"{TemplateBinding Padding}\"/>\n      <Grid Grid.Column=\"3\">\n        <ToggleButton x:Name=\"OverflowButton\" Style=\"{StaticResource Style.ToolBar.OverflowButton}\" Visibility=\"Collapsed\" ClickMode=\"Press\" IsChecked=\"{Binding IsOverflowOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}\"/>\n        <Popup x:Name=\"OverflowPopup\" IsOpen=\"{Binding IsOverflowOpen, RelativeSource={RelativeSource TemplatedParent}}\" Placement=\"Bottom\" StaysOpen=\"True\" Focusable=\"False\">\n          <Border Background=\"{DynamicResource Brush.Background.Popup}\" BorderBrush=\"{DynamicResource Brush.Border.Popup}\" BorderThickness=\"1\" CornerRadius=\"{DynamicResource Corner.Border1.Bottom}\" Padding=\"8\">\n            <ToolBarOverflowPanel x:Name=\"PART_ToolBarOverflowPanel\" Focusable=\"True\" KeyboardNavigation.DirectionalNavigation=\"Cycle\" KeyboardNavigation.TabNavigation=\"Cycle\"/>\n          </Border>\n        </Popup>\n      </Grid>\n    </Grid>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"Header\" Value=\"{x:Null}\">\n        <Setter Property=\"Visibility\" Value=\"Collapsed\" TargetName=\"ToolBarHeader\"/>\n      </Trigger>\n      <Trigger Property=\"ToolBarTray.IsLocked\" Value=\"True\">\n        <Setter Property=\"Visibility\" Value=\"Collapsed\" TargetName=\"ToolBarThumb\"/>\n      </Trigger>\n      <Trigger Property=\"IsOverflowOpen\" Value=\"True\">\n        <Setter Property=\"IsEnabled\" Value=\"False\" TargetName=\"ToolBarThumb\"/>\n      </Trigger>\n      <Trigger Property=\"HasOverflowItems\" Value=\"True\">\n        <Setter Property=\"Visibility\" Value=\"Visible\" TargetName=\"OverflowButton\"/>\n      </Trigger>\n      <Trigger Property=\"IsEnabled\" Value=\"false\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"ToolBar\" BasedOn=\"{StaticResource {x:Type HeaderedItemsControl}}\">\n    <Style.Resources>\n      <Style x:Key=\"{x:Static ToolBar.SeparatorStyleKey}\" TargetType=\"Separator\" BasedOn=\"{StaticResource Style.ToolBar.Separator}\"/>\n      <Style x:Key=\"{x:Static ToolBar.ButtonStyleKey}\" TargetType=\"Button\" BasedOn=\"{StaticResource Style.ToolBar.Button}\"/>\n      <Style x:Key=\"{x:Static ToolBar.ToggleButtonStyleKey}\" TargetType=\"ToggleButton\" BasedOn=\"{StaticResource Style.ToolBar.Toggle}\"/>\n      <Style x:Key=\"{x:Static ToolBar.CheckBoxStyleKey}\" TargetType=\"CheckBox\" BasedOn=\"{StaticResource Style.ToolBar.Toggle}\"/>\n      <Style x:Key=\"{x:Static ToolBar.RadioButtonStyleKey}\" TargetType=\"RadioButton\" BasedOn=\"{StaticResource Style.ToolBar.Toggle}\"/>\n      <Style x:Key=\"{x:Static ToolBar.ComboBoxStyleKey}\" TargetType=\"ComboBox\" BasedOn=\"{StaticResource Style.ToolBar.ComboBox}\"/>\n      <Style x:Key=\"{x:Static ToolBar.TextBoxStyleKey}\" TargetType=\"TextBox\" BasedOn=\"{StaticResource Style.ToolBar.TextBox}\"/>\n      <Style x:Key=\"{x:Static ToolBar.MenuStyleKey}\" TargetType=\"Menu\" BasedOn=\"{StaticResource Style.ToolBar.Menu}\"/>\n    </Style.Resources>\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Normal}\"/>\n    <Setter Property=\"Padding\" Value=\"0,1\"/>\n    <Setter Property=\"MinHeight\" Value=\"28\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.ToolBar}\"/>\n  </Style>\n\n  <!-- StatusBar Style -->\n  <ControlTemplate x:Key=\"Template.StatusBar\" TargetType=\"StatusBar\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ItemsPresenter />\n    </Border>\n    <ControlTemplate.Triggers>\n      <Trigger Property=\"IsEnabled\" Value=\"false\">\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource Brush.Foreground.Disabled}\"/>\n      </Trigger>\n    </ControlTemplate.Triggers>\n  </ControlTemplate>\n  <Style TargetType=\"StatusBar\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\n    <Style.Resources>\n      <Style x:Key=\"{x:Static StatusBar.SeparatorStyleKey}\" TargetType=\"Separator\" BasedOn=\"{StaticResource Style.ToolBar.Separator}\"/>\n    </Style.Resources>\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"{DynamicResource Brush.ToolBar.Normal}\"/>\n    <Setter Property=\"MinHeight\" Value=\"28\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.StatusBar}\"/>\n  </Style>\n\n  <!-- StatusBarItem Style -->\n  <ControlTemplate x:Key=\"Template.StatusBarItem\" TargetType=\"StatusBarItem\">\n    <Border Background=\"{TemplateBinding Background}\" BorderBrush=\"{TemplateBinding BorderBrush}\" BorderThickness=\"{TemplateBinding BorderThickness}\" Padding=\"{TemplateBinding Padding}\">\n      <ContentPresenter HorizontalAlignment=\"{TemplateBinding HorizontalContentAlignment}\" VerticalAlignment=\"{TemplateBinding VerticalContentAlignment}\"/>\n    </Border>\n  </ControlTemplate>\n  <Style TargetType=\"StatusBarItem\" BasedOn=\"{StaticResource {x:Type ContentControl}}\">\n    <Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\n    <Setter Property=\"Background\" Value=\"Transparent\"/>\n    <Setter Property=\"Padding\" Value=\"4\"/>\n    <Setter Property=\"Template\" Value=\"{StaticResource Template.StatusBarItem}\"/>\n  </Style>\n\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/TileInfo.xaml",
    "content": "<UserControl\r\n\tx:Class=\"IngnomiaGUI.TileInfo\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\tx:Name=\"TileInfoControl\">\r\n\t<UserControl.DataContext>\r\n\t\t<local:TileInfoModel />\r\n\t</UserControl.DataContext>\r\n\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" MaxHeight=\"400\" VerticalAlignment=\"Bottom\">\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"7*\" />\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\t\t<Border x:Name=\"TabButtonBorder\" Grid.Column=\"0\" Style=\"{StaticResource Panel}\" MinWidth=\"70\" MaxWidth=\"70\">\r\n\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t<ItemsControl ItemsSource=\"{Binding TabItems}\" ItemTemplate=\"{StaticResource TITabButtonsTemplate}\">\r\n\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t</ItemsControl>\r\n\t\t\t</ScrollViewer>\r\n\t\t</Border>\r\n\t\t<Border Grid.Column=\"1\" Style=\"{StaticResource Panel}\" MinWidth=\"500\" MinHeight=\"300\" MaxHeight=\"500\">\r\n\t\t\t<Grid>\r\n\t\t\t\t<Grid x:Name=\"TabTerrain\" Visibility=\"{Binding ShowTerrain}\">\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\">\r\n\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding TerrainTab}\" ItemTemplate=\"{StaticResource TITabTerrainTemplate}\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowDesignationSimple}\">\r\n\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding DesignationTitle}\" />\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\" : \" />\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding DesignationName}\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<Button Content=\"{StaticResource TileInfo_Manage}\" Margin=\"2\" Command=\"{Binding CmdManage}\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowMechanism}\">\r\n\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding ShowMechActive}\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding MechName}\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding ShowMechActive}\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding MechActive}\" />\r\n\t\t\t\t\t\t\t\t\t\t<Button Content=\"Toggle\" Margin=\"2\" Command=\"{Binding CmdMechToggleActive}\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding ShowMechInvert}\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding MechInvert}\" />\r\n\t\t\t\t\t\t\t\t\t\t<Button Content=\"Toggle\" Margin=\"2\" Command=\"{Binding CmdMechToggleInvert}\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding ShowMechFuel}\">\r\n\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding MechFuel}\" />\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowItems}\">\r\n\t\t\t\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding ItemTab}\" ItemTemplate=\"{StaticResource ItemTemplate20}\">\r\n\t\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowCreatures}\">\r\n\t\t\t\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding CreatureTab}\" ItemTemplate=\"{StaticResource TITabCreaturesTemplate}\">\r\n\t\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowAutomatons}\">\r\n\t\t\t\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding AutomatonTab}\" ItemTemplate=\"{StaticResource TITabAutomatonTemplate}\">\r\n\t\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowMiniStockPile}\">\r\n\t\t\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_Stockpile}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding MiniStockpileName}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"This tile:\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding Capacity}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding ItemCount}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding Reserved}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<Button Content=\"{StaticResource TileInfo_Manage}\" Margin=\"2\" Command=\"{Binding CmdManage }\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\">\r\n\t\t\t\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding MiniStockpileContents}\" ItemTemplate=\"{StaticResource ItemTemplate20}\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowJob}\">\r\n\t\t\t\t\t\t\t\t<Grid >\r\n\t\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_Job}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding JobName}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_WorkedBy}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding JobWorker}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_JobPriority}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding JobPriority}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_RequiredSkill}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding RequiredSkill}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_RequiredTool}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding RequiredTool}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_RequiredToolAvailable}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding RequiredToolAvailable}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_RequiredToolAccessible}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{Binding WorkablePosition}\" />\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_RequiredItems}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding RequiredItems}\" ItemTemplate=\"{StaticResource ItemTemplate16}\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t</ItemsControl>\r\n\t\t\t\t\t\t\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t<Border Style=\"{StaticResource PanelTileInfo}\" Visibility=\"{Binding ShowDesignationRoom}\">\r\n\t\t\t\t\t\t\t\t<Grid>\r\n\t\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t<StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding DesignationName}\" />\r\n\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding VisRoomAssign}\" Margin=\"2,20,2,20\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" Text=\"{StaticResource TileInfo_AssignTo}\" MinWidth=\"150\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<ComboBox x:Name=\"PrioritySelectorN\" MinWidth=\"200\" Margin=\"2\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemsSource=\"{Binding PossibleTennants}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tSelectedItem=\"{Binding Tennant, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding VisRoomValue}\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_Value}\" MinWidth=\"150\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{Binding RoomValue}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_Enclosed}\" MinWidth=\"150\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{Binding Enclosed}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_HasRoof}\" MinWidth=\"150\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{Binding Roofed}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Visibility=\"{Binding VisBeds}\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{StaticResource TileInfo_Beds}\" MinWidth=\"150\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock FontSize=\"18\" HorizontalAlignment=\"Left\" Text=\"{Binding Beds}\" />\r\n\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t<CheckBox Content=\"{StaticResource TileInfo_SoundAlarm}\" IsChecked=\"{Binding Alarm, Mode=TwoWay}\" Margin=\"2,20,2,2\" FontSize=\"18\" Visibility=\"{Binding VisAlarm}\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource TileInfo_AlarmSoundAlarm}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPadding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource TileInfo_AlarmRetreatHere}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tPadding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t\t\t\t\t</CheckBox>\r\n\t\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t\t\t</Grid>\r\n\t\t\t\t\t\t\t</Border>\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t</Grid>\r\n\t\t\t\t\r\n\t\t\t\t<Grid Visibility=\"{Binding ShowDesignation}\">\r\n\t\t\t\t\t<!-- <local:Agriculture x:Name=\"Agriculture\" Visibility=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.ShowAgriculture }\" HorizontalAlignment=\"Right\" /> -->\r\n\t\t\t\t\t<local:Agriculture x:Name=\"Agriculture\" />\r\n\t\t\t\t</Grid>\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t</Grid>\r\n\t\t</Border>\r\n\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\" Grid.Column=\"2\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"MilitaryWindow\">\r\n\t\t\t<Image Source=\"buttons/cross.png\" />\r\n\t\t</Button>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/WaitPage.xaml",
    "content": "﻿<UserControl\r\n\tx:Class=\"IngnomiaGUI.WaitPage\"\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\tx:Name=\"WaitPageControl\">\r\n\t<UserControl.Resources>\r\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\r\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\r\n\t\t</ResourceDictionary>\r\n\t</UserControl.Resources>\r\n\r\n\t<Grid x:Name=\"LayoutRoot\" RenderTransformOrigin=\"0.5,0.5\">\r\n\t\t<Grid.RenderTransform>\r\n\t\t\t<TransformGroup>\r\n\t\t\t\t<ScaleTransform ScaleX=\"1\" ScaleY=\"1\" />\r\n\t\t\t\t<SkewTransform />\r\n\t\t\t\t<RotateTransform />\r\n\t\t\t\t<TranslateTransform X=\"0\" Y=\"0\" />\r\n\t\t\t</TransformGroup>\r\n\t\t</Grid.RenderTransform>\r\n\r\n\t\t<Grid.RowDefinitions>\r\n\t\t\t<RowDefinition Height=\"2*\" />\r\n\t\t\t<RowDefinition Height=\"9*\" />\r\n\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t</Grid.RowDefinitions>\r\n\t\t<Grid.ColumnDefinitions>\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t</Grid.ColumnDefinitions>\r\n\r\n\t\t<TextBlock Grid.Row=\"0\" Grid.Column=\"1\" FontSize=\"100\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource WaitPage_CreatingGame}\" />\r\n\r\n\t\t<Viewbox Grid.Row=\"1\" Grid.Column=\"1\">\r\n\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" Text=\"{StaticResource WaitPage_PleaseWait}\" />\r\n\t\t</Viewbox>\r\n\t</Grid>\r\n</UserControl>"
  },
  {
    "path": "content/xaml/WorkshopGui.xaml",
    "content": "<UserControl\n\tx:Class=\"IngnomiaGUI.WorkshopGui\"\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"d\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\tx:Name=\"WorkshopControl\">\n\t<UserControl.DataContext>\r\n\t\t<local:WorkshopModel />\r\n\t</UserControl.DataContext>\r\n\t<UserControl.Resources>\n\t\t<ResourceDictionary>\r\n\t\t\t<ResourceDictionary.MergedDictionaries>\n\t\t\t\t<ResourceDictionary Source=\"styles/mainmenu/styles.xaml\" />\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/_.xaml\" />-->\r\n\t\t\t\t<ResourceDictionary Source=\"localization/en_US.xaml\" />\r\n\t\t\t\t<!--<ResourceDictionary Source=\"localization/fr_FR.xaml\" />-->\r\n\t\t\t</ResourceDictionary.MergedDictionaries>\n\t\t</ResourceDictionary>\n\t</UserControl.Resources>\n\r\n\t<Grid x:Name=\"LayoutRoot\" MaxHeight=\"700\">\r\n\t\t<Grid.ColumnDefinitions>\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t</Grid.ColumnDefinitions>\n\t\t<StackPanel Grid.Column=\"1\" Orientation=\"Horizontal\">\n\t\t\t<Border x:Name=\"TabBorder1\" Style=\"{StaticResource Panel}\" MinWidth=\"100\" MinHeight=\"700\" Margin=\"2\" />\n\r\n\t\t\t<!--\n\t\t\t#############################################################################################################################\n\t\t\t\tStandard GUI for normal production workshops\n\t\t\t#############################################################################################################################\n\t\t\t-->\n\r\n\t\t\t<Border x:Name=\"TabBorderN2\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding NormalGui}\">\n\t\t\t\t<StackPanel>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Name}\" />\n\t\t\t\t\t<TextBox x:Name=\"WSNameN\" Text=\"{Binding Name}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t<ComboBox x:Name=\"PrioritySelectorN\" Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t\t<CheckBox x:Name=\"CBSuspendN\" Content=\"{StaticResource WorkshopGui_SuspendWorkshop}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopSuspendWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopStopWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox x:Name=\"CBAcceptJobsN\" Content=\"{StaticResource WorkshopGui_AllowAcceptGeneratedJobs}\" IsChecked=\"{Binding AcceptGenerated, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_AcceptGeneratedJobs}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_AutoGenerateCraftJobs}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox x:Name=\"CBCraftMissingN\" Content=\"{StaticResource WorkshopGui_AutoCraftMissingComponents}\" IsChecked=\"{Binding AutoCraft, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_AllowAutoCraftMissingComponents}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_GeneratesCraftingJobsForMissingComponents}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox x:Name=\"CBConnectSPN\" Content=\"{StaticResource WorkshopGui_ConnectToStockpile}\" IsChecked=\"{Binding LinkStockpile, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ConnectStockpile}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_Connect3x3Stockpile}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ConnectAdjacentStockpile}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t</StackPanel>\n\t\t\t</Border>\n\r\n\t\t\t<Border x:Name=\"TabBorderN3\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding NormalGui}\">\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource WorkshopGui_AvailableProducts}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding Products}\" ItemTemplate=\"{StaticResource WSProductTemplate}\">\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\n\t\t\t\t\t\t</ItemsControl>\n\t\t\t\t\t</ScrollViewer>\n\t\t\t\t</Grid>\n\t\t\t</Border>\n\r\n\t\t\t<Border x:Name=\"TabBorderN4\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding NormalGui}\">\r\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource WorkshopGui_ProductionLine}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\n\t\t\t\t\t\t<ItemsControl ItemsSource=\"{Binding Jobs}\" ItemTemplate=\"{StaticResource WSJobTemplate}\">\n\t\t\t\t\t\t\t<ItemsControl.ItemsPanel>\n\t\t\t\t\t\t\t\t<ItemsPanelTemplate>\n\t\t\t\t\t\t\t\t\t<StackPanel />\r\n\t\t\t\t\t\t\t\t</ItemsPanelTemplate>\n\t\t\t\t\t\t\t</ItemsControl.ItemsPanel>\n\t\t\t\t\t\t</ItemsControl>\n\t\t\t\t\t</ScrollViewer>\n\t\t\t\t</Grid>\n\t\t\t</Border>\n\r\n\t\t\t<!--\n\t\t\t#############################################################################################################################\n\t\t\t\tButcher GUI\r\n\t\t\t#############################################################################################################################\n\t\t\t-->\n\r\n\t\t\t<Border x:Name=\"TabBorderB2\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding ButcherGui}\">\n\t\t\t\t<StackPanel>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Name}\" />\n\t\t\t\t\t<TextBox x:Name=\"WSNameB\" Text=\"{Binding Name}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t<ComboBox x:Name=\"PrioritySelector\" Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t\t<CheckBox x:Name=\"CBSuspendB\" Content=\"{StaticResource WorkshopGui_SuspendWorkshop}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopSuspendWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopStopWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox x:Name=\"CBButchExcess\" Content=\"{StaticResource WorkshopGui_ButcherExcessAnimals}\" IsChecked=\"{Binding ButcherExcess, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ButcherExcess}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ButcherTameNotOnPasture}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox x:Name=\"CBButchCorpses\" Content=\"{StaticResource WorkshopGui_ButcherCorpse}\" IsChecked=\"{Binding ButcherCorpses, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ButcherAllowCorpse}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ButcherOnlyStockpileCorpse}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox x:Name=\"CBConnectSPB\" Content=\"{StaticResource WorkshopGui_ConnectToStockpile}\" IsChecked=\"{Binding LinkStockpile, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ConnectStockpile}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_Connect3x3Stockpile}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_ConnectAdjacentStockpile}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t</StackPanel>\n\t\t\t</Border>\n\r\n\t\t\t<Border x:Name=\"TabBorder3_1\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding ButcherGui}\">\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource WorkshopGui_ButcherAnimals}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<ScrollViewer VerticalScrollBarVisibility=\"Auto\" CanContentScroll=\"True\" Grid.Row=\"1\">\n\t\t\t\t\t</ScrollViewer>\n\t\t\t\t</Grid>\n\t\t\t</Border>\n\r\n\t\t\t<!--\n\t\t\t#############################################################################################################################\n\t\t\t\tTrader GUI\r\n\t\t\t#############################################################################################################################\n\t\t\t-->\n\r\n\t\t\t<Border x:Name=\"TabBorderT2\" Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding TraderGui}\">\n\t\t\t\t<StackPanel>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Name}\" />\n\t\t\t\t\t<TextBox x:Name=\"WSNameT\" Text=\"{Binding Name}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t<ComboBox x:Name=\"PrioritySelectorT\" Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t\t<CheckBox x:Name=\"CBSuspendT\" Content=\"{StaticResource WorkshopGui_SuspendWorkshop}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopSuspendWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopStopWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\r\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t</StackPanel>\n\t\t\t</Border>\n\r\n\t\t\t<Border x:Name=\"TabBorderT4\" Style=\"{StaticResource Panel}\" MinWidth=\"800\" MaxWidth=\"800\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding TraderGui}\">\r\n\t\t\t\t<Grid>\n\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{StaticResource WorkshopGui_Trade}\" Grid.Row=\"0\" />\r\n\t\t\t\t\t<Grid Grid.Row=\"1\">\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"Auto\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB1\" Grid.Column=\"1\" Style=\"{StaticResource ButtonStyle1}\" MinWidth=\"100\" Content=\"1\" IsChecked=\"{Binding Amount1, Mode=TwoWay}\" />\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB2\" Grid.Column=\"2\" Style=\"{StaticResource ButtonStyle1}\" MinWidth=\"100\" Content=\"10\" IsChecked=\"{Binding Amount10, Mode=TwoWay}\" />\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB3\" Grid.Column=\"3\" Style=\"{StaticResource ButtonStyle1}\" MinWidth=\"100\" Content=\"100\" IsChecked=\"{Binding Amount100, Mode=TwoWay}\" />\r\n\t\t\t\t\t\t<ToggleButton x:Name=\"CB4\" Grid.Column=\"4\" Style=\"{StaticResource ButtonStyle1}\" MinWidth=\"100\" Content=\"{StaticResource WorkshopGui_Max}\" IsChecked=\"{Binding AmountAll, Mode=TwoWay}\" />\r\n\t\t\t\t\t</Grid>\n\t\t\t\t\t<Grid Grid.Row=\"2\">\n\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"Auto\" />\r\n\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t</Grid.RowDefinitions>\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"1*\" />\r\n\t\t\t\t\t\t\t<ColumnDefinition Width=\"5*\" />\r\n\t\t\t\t\t\t</Grid.ColumnDefinitions>\n\n\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{StaticResource WorkshopGui_TraderInventory}\" Grid.Row=\"0\" Grid.Column=\"0\" />\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"0\" Grid.Column=\"2\" HorizontalAlignment=\"Right\">\n\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Right\" Text=\"{StaticResource WorkshopGui_TraderValue}\" />\r\n\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Right\" Text=\"{Binding TraderValue}\" />\n\t\t\t\t\t\t</StackPanel>\n\n\t\t\t\t\t\t<ListBox x:Name=\"SVTraderStock\" Grid.Row=\"1\" Grid.Column=\"0\" Margin=\"5\" Background=\"{StaticResource PanelBackgroundGrey}\"\n\t\t\t\t\t\t\tItemTemplate=\"{StaticResource TradeItemTemplate}\"\n\t\t\t\t\t\t\tItemsSource=\"{Binding TraderStock}\"\r\n\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedTraderStock, Mode=TwoWay}\">\n\t\t\t\t\t\t</ListBox>\n\r\n\t\t\t\t\t\t<Grid Grid.Row=\"1\" Grid.Column=\"1\">\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\n\r\n\t\t\t\t\t\t\t<Button x:Name=\"BTrd2L\" Content=\"&lt;\" MaxWidth=\"30\" Command=\"{Binding CmdTransfer}\" CommandParameter=\"TraderLeft\" Grid.Row=\"1\" VerticalAlignment=\"Bottom\" />\r\n\t\t\t\t\t\t\t<Button x:Name=\"BTrd2R\" Content=\"&gt;\" MaxWidth=\"30\" Command=\"{Binding CmdTransfer}\" CommandParameter=\"TraderRight\" Grid.Row=\"2\" VerticalAlignment=\"Top\" />\r\n\t\t\t\t\t\t</Grid>\n\r\n\t\t\t\t\t\t<ListBox x:Name=\"SVTraderOffer\" Grid.Row=\"1\" Grid.Column=\"2\" Margin=\"5\" Background=\"{StaticResource PanelBackgroundGrey}\"\n\t\t\t\t\t\t\tItemTemplate=\"{StaticResource TradeItemTemplate}\"\n\t\t\t\t\t\t\tItemsSource=\"{Binding TraderOffer}\"\r\n\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedTraderOffer, Mode=TwoWay}\">\n\t\t\t\t\t\t</ListBox>\n\r\n\t\t\t\t\t\t<ListBox x:Name=\"SVPlayerStock\" Grid.Row=\"3\" Grid.Column=\"0\" Margin=\"5\" Background=\"{StaticResource PanelBackgroundGrey}\"\n\t\t\t\t\t\t\tItemTemplate=\"{StaticResource TradeItemTemplate}\"\n\t\t\t\t\t\t\tItemsSource=\"{Binding PlayerStock}\"\r\n\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPlayerStock, Mode=TwoWay}\">\n\t\t\t\t\t\t</ListBox>\n\r\n\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Left\" Text=\"{StaticResource WorkshopGui_PlayerInventory}\" Grid.Row=\"2\" Grid.Column=\"0\" />\r\n\t\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" Grid.Row=\"2\" Grid.Column=\"2\" HorizontalAlignment=\"Right\">\n\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Right\" Text=\"{StaticResource WorkshopGui_PlayerValue}\" />\r\n\t\t\t\t\t\t\t<TextBlock FontSize=\"20\" HorizontalAlignment=\"Right\" Text=\"{Binding PlayerValue}\" />\n\t\t\t\t\t\t</StackPanel>\n\r\n\t\t\t\t\t\t<Grid Grid.Row=\"3\" Grid.Column=\"1\">\n\t\t\t\t\t\t\t<Grid.RowDefinitions>\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t\t<RowDefinition Height=\"1*\" />\r\n\t\t\t\t\t\t\t</Grid.RowDefinitions>\n\r\n\t\t\t\t\t\t\t<Button x:Name=\"BPlr2L\" Content=\"&lt;\" MaxWidth=\"30\" Command=\"{Binding CmdTransfer}\" CommandParameter=\"PlayerLeft\" Grid.Row=\"1\" VerticalAlignment=\"Bottom\" />\r\n\t\t\t\t\t\t\t<Button x:Name=\"BPlr2R\" Content=\"&gt;\" MaxWidth=\"30\" Command=\"{Binding CmdTransfer}\" CommandParameter=\"PlayerRight\" Grid.Row=\"2\" VerticalAlignment=\"Top\" />\r\n\t\t\t\t\t\t</Grid>\n\r\n\t\t\t\t\t\t<ListBox x:Name=\"SVPlayerOffer\" Grid.Row=\"3\" Grid.Column=\"2\" Margin=\"5\" Background=\"{StaticResource PanelBackgroundGrey}\"\n\t\t\t\t\t\t\tItemTemplate=\"{StaticResource TradeItemTemplate}\"\n\t\t\t\t\t\t\tItemsSource=\"{Binding PlayerOffer}\"\r\n\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPlayerOffer, Mode=TwoWay}\">\n\t\t\t\t\t\t</ListBox>\n\t\t\t\t\t</Grid>\n\t\t\t\t\t<Button x:Name=\"BtradeR\" Content=\"{StaticResource WorkshopGui_TradeAction}\" Command=\"{Binding CmdTrade}\" Grid.Row=\"3\" HorizontalAlignment=\"Center\" Margin=\"4\" />\r\n\t\t\t\t</Grid>\n\t\t\t</Border>\n\t\t\t\n\t\t\t\t\t\t<!--\n\t\t\t#############################################################################################################################\n\t\t\t\tGUI for fishing workshops\n\t\t\t#############################################################################################################################\n\t\t\t-->\n\n\t\t\t<Border Style=\"{StaticResource Panel}\" MinWidth=\"300\" MaxWidth=\"300\" MinHeight=\"700\" Margin=\"2\" Visibility=\"{Binding FisherGui}\">\n\t\t\t\t<StackPanel>\n\t\t\t\t\t<TextBlock FontSize=\"20\" FontWeight=\"Bold\" HorizontalAlignment=\"Left\" Text=\"{Binding Name}\" />\n\t\t\t\t\t<TextBox  Text=\"{Binding Name}\" Margin=\"10,5,10,5\" />\n\t\t\t\t\t<ComboBox Margin=\"10,5,10,5\"\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Priorities}\"\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedPrio, Mode=TwoWay}\"\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate}\" />\n\t\t\t\t\t<CheckBox Content=\"{StaticResource WorkshopGui_SuspendWorkshop}\" IsChecked=\"{Binding Suspended, Mode=TwoWay}\" Margin=\"10,5,10,5\">\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopSuspendWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\n\t\t\t\t\t\t\t\t<TextBlock Text=\"{StaticResource WorkshopGui_WorkshopStopWork}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox Content=\"Catch Fish\" IsChecked=\"{Binding CatchFish, Mode=TwoWay}\" Margin=\"10,5,10,5\">\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"Gnomes will try to catch fish.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t\t<CheckBox Content=\"Process Fish\" IsChecked=\"{Binding ProcessFish, Mode=TwoWay}\" Margin=\"10,5,10,5\">\n\t\t\t\t\t\t<CheckBox.ToolTip>\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\n\t\t\t\t\t\t\t\t<TextBlock Text=\"Gnomes will cut and gut fish.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\n\t\t\t\t\t\t\t\t<TextBlock Text=\"Smelly business.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\" />\n\t\t\t\t\t\t\t</StackPanel>\n\t\t\t\t\t\t</CheckBox.ToolTip>\n\t\t\t\t\t</CheckBox>\n\t\t\t\t</StackPanel>\n\t\t\t</Border>\n\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" VerticalAlignment=\"Top\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CloseWindowCmd }\"\r\n\t\t\t\tCommandParameter=\"WorkshopWindow\">\n\t\t\t\t<Image Source=\"buttons/cross.png\" />\n\t\t\t</Button>\n\t\t</StackPanel>\n\t</Grid>\n</UserControl>"
  },
  {
    "path": "content/xaml/localization/_.xaml",
    "content": "<ResourceDictionary\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:system=\"clr-namespace:System;assembly=mscorlib\">\r\n\r\n\t<!-- String resource that can be localized -->\r\n\t<!--{StaticResource MainPage_}-->\r\n\t<system:String x:Key=\"MainPage_\">MainPage_</system:String>\r\n\t<system:String x:Key=\"MainPage_Ingnomia\">MainPage_Ingnomia</system:String>\r\n\t<system:String x:Key=\"MainPage_Continue\">MainPage_Continue</system:String>\r\n\t<system:String x:Key=\"MainPage_NewGame\">MainPage_NewGame</system:String>\r\n\t<system:String x:Key=\"MainPage_SetUpGame\">MainPage_SetUpGame</system:String>\r\n\t<system:String x:Key=\"MainPage_LoadGame\">MainPage_LoadGame</system:String>\r\n\t<system:String x:Key=\"MainPage_Settings\">MainPage_Settings</system:String>\r\n\t<system:String x:Key=\"MainPage_Exit\">MainPage_Exit</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMContinue\">MainPage_Hint_MMContinue</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMNewGame\">MainPage_Hint_MMNewGame</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSetupGame\">MainPage_Hint_MMSetupGame</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMLoadGame\">MainPage_Hint_MMLoadGame</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSettings\">MainPage_Hint_MMSettings</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMExit\">MainPage_Hint_MMExit</system:String>\r\n\r\n\t<!--{StaticResource Agriculture_}-->\r\n\t<system:String x:Key=\"Agriculture_\">Agriculture_</system:String>\r\n\t<system:String x:Key=\"Agriculture_TilledPlots\">Agriculture_TilledPlots</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantsPlanted\">Agriculture_PlantsPlanted</system:String>\r\n\t<system:String x:Key=\"Agriculture_CropsReady\">Agriculture_CropsReady</system:String>\r\n\t<system:String x:Key=\"Agriculture_Suspend\">Agriculture_Suspend</system:String>\r\n\t<system:String x:Key=\"Agriculture_Harvest\">Agriculture_Harvest</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectCrop\">Agriculture_SelectCrop</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfSeeds\">Agriculture_NumberOfSeeds</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfItems\">Agriculture_NumberOfItems</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfPlants\">Agriculture_NumberOfPlants</system:String>\r\n\t<system:String x:Key=\"Agriculture_Manage\">Agriculture_Manage</system:String>\r\n\t<system:String x:Key=\"Agriculture_Animals\">Agriculture_Animals</system:String>\r\n\t<system:String x:Key=\"Agriculture_Male\">Agriculture_Male</system:String>\r\n\t<system:String x:Key=\"Agriculture_Female\">Agriculture_Female</system:String>\r\n\t<system:String x:Key=\"Agriculture_TameWildAnimals\">Agriculture_TameWildAnimals</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestAnimals\">Agriculture_HarvestAnimals</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestHay\">Agriculture_HarvestHay</system:String>\r\n\t<system:String x:Key=\"Agriculture_StoredFood\">Agriculture_StoredFood</system:String>\r\n\t<system:String x:Key=\"Agriculture_Settings\">Agriculture_Settings</system:String>\r\n\t<system:String x:Key=\"Agriculture_Back\">Agriculture_Back</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectFoodForTroughs\">Agriculture_SelectFoodForTroughs</system:String>\r\n\t<system:String x:Key=\"Agriculture_ManageAnimals\">Agriculture_ManageAnimals</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectAnimalType\">Agriculture_SelectAnimalType</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfAnimals\">Agriculture_NumberOfAnimals</system:String>\r\n\t<system:String x:Key=\"Agriculture_Trees\">Agriculture_Trees</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantTrees\">Agriculture_PlantTrees</system:String>\r\n\t<system:String x:Key=\"Agriculture_PickFruit\">Agriculture_PickFruit</system:String>\r\n\t<system:String x:Key=\"Agriculture_FellTrees\">Agriculture_FellTrees</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectTreeType\">Agriculture_SelectTreeType</system:String>\r\n\r\n\t<!--{StaticResource CreatureInfo_}-->\r\n\t<system:String x:Key=\"CreatureInfo_\">CreatureInfo_</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Happiness\">CreatureInfo_Happiness</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Sleep\">CreatureInfo_Sleep</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Thirst\">CreatureInfo_Thirst</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Hunger\">CreatureInfo_Hunger</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Cha\">CreatureInfo_Cha</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Wis\">CreatureInfo_Wis</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Int\">CreatureInfo_Int</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Con\">CreatureInfo_Con</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Dex\">CreatureInfo_Dex</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Str\">CreatureInfo_Str</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Inventory\">CreatureInfo_Inventory</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Equipment\">CreatureInfo_Equipment</system:String>\r\n\r\n\t<!--{StaticResource DebugPage_}-->\r\n\t<system:String x:Key=\"DebugPage_\">DebugPage_</system:String>\r\n\t<system:String x:Key=\"DebugPage_Misc\">DebugPage_Misc</system:String>\r\n\t<system:String x:Key=\"DebugPage_Stuff\">DebugPage_Stuff</system:String>\r\n\t<system:String x:Key=\"DebugPage_More\">DebugPage_More</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugFirstPage\">DebugPage_DebugFirstPage</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGnome\">DebugPage_SpawnGnome</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnTrader\">DebugPage_SpawnTrader</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGoblin\">DebugPage_SpawnGoblin</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugSecondPage\">DebugPage_DebugSecondPage</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugThirdPage\">DebugPage_DebugThirdPage</system:String>\r\n\r\n\t<!--{StaticResource GameGui_}-->\r\n\t<system:String x:Key=\"GameGui_\">GameGui_</system:String>\r\n\t<system:String x:Key=\"GameGui_KingdomName\">GameGui_KingdomName</system:String>\r\n\t<system:String x:Key=\"GameGui_Something1\">GameGui_Something1</system:String>\r\n\t<system:String x:Key=\"GameGui_Something2\">GameGui_Something2</system:String>\r\n\t<system:String x:Key=\"GameGui_D\">GameGui_D</system:String>\r\n\t<system:String x:Key=\"GameGui_Yes\">GameGui_Yes</system:String>\r\n\t<system:String x:Key=\"GameGui_Ok\">GameGui_Ok</system:String>\r\n\t<system:String x:Key=\"GameGui_No\">GameGui_No</system:String>\r\n\t<system:String x:Key=\"GameGui_Build\">GameGui_Build</system:String>\r\n\t<system:String x:Key=\"GameGui_Mine\">GameGui_Mine</system:String>\r\n\t<system:String x:Key=\"GameGui_Agriculture\">GameGui_Agriculture</system:String>\r\n\t<system:String x:Key=\"GameGui_Designations\">GameGui_Designations</system:String>\r\n\t<system:String x:Key=\"GameGui_Job\">GameGui_Job</system:String>\r\n\t<system:String x:Key=\"GameGui_Magic\">GameGui_Magic</system:String>\r\n\t<system:String x:Key=\"GameGui_Kingdom\">GameGui_Kingdom</system:String>\r\n\t<system:String x:Key=\"GameGui_Stockpiles\">GameGui_Stockpiles</system:String>\r\n\t<system:String x:Key=\"GameGui_Military\">GameGui_Military</system:String>\r\n\t<system:String x:Key=\"GameGui_Population\">GameGui_Population</system:String>\r\n\t<system:String x:Key=\"GameGui_Missions\">GameGui_Missions</system:String>\r\n\r\n\t<!--{StaticResource InGamePage_}-->\r\n\t<system:String x:Key=\"InGamePage_\">InGamePage_</system:String>\r\n\t<system:String x:Key=\"InGamePage_Ingnomia\">InGamePage_Ingnomia</system:String>\r\n\t<system:String x:Key=\"InGamePage_Resume\">InGamePage_Resume</system:String>\r\n\t<system:String x:Key=\"InGamePage_LoadGame\">InGamePage_LoadGame</system:String>\r\n\t<system:String x:Key=\"InGamePage_SaveGame\">InGamePage_SaveGame</system:String>\r\n\t<system:String x:Key=\"InGamePage_Settings\">InGamePage_Settings</system:String>\r\n\t<system:String x:Key=\"InGamePage_QuitGame\">InGamePage_QuitGame</system:String>\r\n\r\n\t<!--{StaticResource LoadGamePage_}-->\r\n\t<system:String x:Key=\"LoadGamePage_\">LoadGamePage_</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_LoadGame\">LoadGamePage_LoadGame</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_HereSelectedGameInfo\">LoadGamePage_HereSelectedGameInfo</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Load\">LoadGamePage_Load</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Back\">LoadGamePage_Back</system:String>\r\n\r\n\t<!--{StaticResource MilitaryGui_}-->\r\n\t<system:String x:Key=\"MilitaryGui_\">MilitaryGui_</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Squads\">MilitaryGui_Squads</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Roles\">MilitaryGui_Roles</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_More\">MilitaryGui_More</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitarySquads\">MilitaryGui_MilitarySquads</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryRoles\">MilitaryGui_MilitaryRoles</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryPriorities\">MilitaryGui_MilitaryPriorities</system:String>\r\n\r\n\t<!--{StaticResource Neighbors_}-->\r\n\t<system:String x:Key=\"Neighbors_\">Neighbors_</system:String>\r\n\t<system:String x:Key=\"Neighbors_Neighbors\">Neighbors_Neighbors</system:String>\r\n\t<system:String x:Key=\"Neighbors_Missions\">Neighbors_Missions</system:String>\r\n\t<system:String x:Key=\"Neighbors_More\">Neighbors_More</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsPage\">Neighbors_NeighborsPage</system:String>\r\n\t<system:String x:Key=\"Neighbors_MissionsPage\">Neighbors_MissionsPage</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsThirdPage\">Neighbors_NeighborsThirdPage</system:String>\r\n\r\n\t<!--{StaticResource NewGamePage_}-->\r\n\t<system:String x:Key=\"NewGamePage_\">NewGamePage_</system:String>\r\n\t<system:String x:Key=\"NewGamePage_SetUpNewGame\">NewGamePage_SetUpNewGame</system:String>\r\n\t<system:String x:Key=\"NewGamePage_World\">NewGamePage_World</system:String>\r\n\t<system:String x:Key=\"NewGamePage_KingdomName\">NewGamePage_KingdomName</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Seed\">NewGamePage_Seed</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Random\">NewGamePage_Random</system:String>\r\n\t<system:String x:Key=\"NewGamePage_WorldSize\">NewGamePage_WorldSize</system:String>\r\n\t<system:String x:Key=\"NewGamePage_LargerSizePerformance\">NewGamePage_LargerSizePerformance</system:String>\r\n\t<system:String x:Key=\"NewGamePage_ZLevels\">NewGamePage_ZLevels</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Ground\">NewGamePage_Ground</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flatness\">NewGamePage_Flatness</system:String>\r\n\t<system:String x:Key=\"NewGamePage_OceanSize\">NewGamePage_OceanSize</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Rivers\">NewGamePage_Rivers</system:String>\r\n\t<system:String x:Key=\"NewGamePage_RiverSize\">NewGamePage_RiverSize</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartArea\">NewGamePage_StartArea</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartingItems\">NewGamePage_StartingItems</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Presets\">NewGamePage_Presets</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NewPreset\">NewGamePage_NewPreset</system:String>\r\n\t<system:String x:Key=\"NewGamePage_DeletePreset\">NewGamePage_DeletePreset</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Gnomes\">NewGamePage_Gnomes</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Items\">NewGamePage_Items</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Animals\">NewGamePage_Animals</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Add\">NewGamePage_Add</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Enemies\">NewGamePage_Enemies</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulMode\">NewGamePage_PeacefulMode</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NoEnemyKingdoms\">NewGamePage_NoEnemyKingdoms</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulAnimalsMayStillAttack\">NewGamePage_PeacefulAnimalsMayStillAttack</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flora\">NewGamePage_Flora</system:String>\r\n\t<system:String x:Key=\"NewGamePage_TreeDensity\">NewGamePage_TreeDensity</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PlantDensity\">NewGamePage_PlantDensity</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Fauna\">NewGamePage_Fauna</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsPage\">NewGamePage_NumberMaxWildAnimalsPage</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimals\">NewGamePage_NumberWildAnimals</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsAtStart\">NewGamePage_NumberWildAtStart</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsPage\">NewGamePage_NumberMaxAnimalsPage</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimals\">NewGamePage_NumberMaxAnimals</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsIncludesDomesticated\">NewGamePage_NumberMaxAnimalsIncludesDomesticated</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Back\">NewGamePage_Back</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Embark\">NewGamePage_Embark</system:String>\r\n\r\n\t<!--{StaticResource PopulationWindow_}-->\r\n\t<system:String x:Key=\"PopulationWindow_\">PopulationWindow_</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Skills\">PopulationWindow_Skills</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Schedule\">PopulationWindow_Schedule</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProf\">PopulationWindow_EditProf</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Name\">PopulationWindow_Name</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Professions\">PopulationWindow_Professions</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_None\">PopulationWindow_None</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Eat\">PopulationWindow_Eat</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Sleep\">PopulationWindow_Sleep</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Train\">PopulationWindow_Train</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProfessions\">PopulationWindow_EditProfessions</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_New\">PopulationWindow_New</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Delete\">PopulationWindow_Delete</system:String>\r\n\r\n\t<!--{StaticResource SettingsPage_}-->\r\n\t<system:String x:Key=\"SettingsPage_\">SettingsPage_</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Settings\">SettingsPage_Settings</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Game\">SettingsPage_Game</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Video\">SettingsPage_Video</system:String>\r\n\t<system:String x:Key=\"SettingsPage_VideoContent\">SettingsPage_VideoContent</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Audio\">SettingsPage_Audio</system:String>\r\n\t<system:String x:Key=\"SettingsPage_AudioContent\">SettingsPage_AudioContent</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Controls\">SettingsPage_Controls</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Back\">SettingsPage_Back</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Accept\">SettingsPage_Accept</system:String>\r\n\t<system:String x:Key=\"SettingsPage_UiScale\">SettingsPage_UiScale</system:String>\r\n\t<system:String x:Key=\"SettingsPage_FullScreen\">SettingsPage_FullScreen</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Language\">SettingsPage_Language</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeyboardSpeed\">SettingsPage_KeyboardSpeed</system:String>\r\n\t<system:String x:Key=\"SettingsPage_LightMin\">SettingsPage_LightMin</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeybindingsPlaceholder\">SettingsPage_KeybindingsPlaceholder</system:String>\r\n\r\n\t<!--{StaticResource StockpileGui_}-->\r\n\t<system:String x:Key=\"StockpileGui_\">StockpileGui_</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stockpile\">StockpileGui_Stockpile</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Suspend\">StockpileGui_Suspend</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpileSuspend\">StockpileGui_StockpileSuspend</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePushable\">StockpileGui_StockpilePushable</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullable\">StockpileGui_StockpilePullable</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHere\">StockpileGui_StockpilePullFromHere</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHigher\">StockpileGui_StockpilePullFromHigher</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromOther\">StockpileGui_PullFromOther</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromOther\">StockpileGui_StockpilePullFromOther</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromLower\">StockpileGui_StockpilePullFromLower</system:String>\r\n\t<system:String x:Key=\"StockpileGui_CopySetup\">StockpileGui_CopySetup</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PasteSetup\">StockpileGui_PasteSetup</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Filters\">StockpileGui_Filters</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stock\">StockpileGui_Stock</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Limits\">StockpileGui_Limits</system:String>\r\n\t<system:String x:Key=\"StockpileGui_LimitsImplementedLater\">StockpileGui_LimitsImplementedLater</system:String>\r\n\r\n\t<!--{StaticResource TileInfo_}-->\r\n\t<system:String x:Key=\"TileInfo_\">TileInfo_</system:String>\r\n\t<system:String x:Key=\"TileInfo_Stockpile\">TileInfo_Stockpile</system:String>\r\n\t<system:String x:Key=\"TileInfo_Manage\">TileInfo_Manage</system:String>\r\n\t<system:String x:Key=\"TileInfo_AssignTo\">TileInfo_AssignTo</system:String>\r\n\t<system:String x:Key=\"TileInfo_Value\">TileInfo_Value</system:String>\r\n\t<system:String x:Key=\"TileInfo_Enclosed\">TileInfo_Enclosed</system:String>\r\n\t<system:String x:Key=\"TileInfo_HasRoof\">TileInfo_HasRoof</system:String>\r\n\t<system:String x:Key=\"TileInfo_Beds\">TileInfo_Beds</system:String>\r\n\t<system:String x:Key=\"TileInfo_SoundAlarm\">TileInfo_SoundAlarm</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmSoundAlarm\">TileInfo_AlarmSoundAlarm</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmRetreatHere\">TileInfo_AlarmRetreatHere</system:String>\r\n\t<system:String x:Key=\"TileInfo_Job\">TileInfo_Job</system:String>\r\n\t<system:String x:Key=\"TileInfo_WorkedBy\">TileInfo_WorkedBy</system:String>\r\n\t<system:String x:Key=\"TileInfo_JobPriority\">TileInfo_JobPriority</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredSkill\">TileInfo_RequiredSkill</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredTool\">TileInfo_RequiredTool</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAvailable\">TileInfo_RequiredToolAvailable</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAccessible\">TileInfo_RequiredToolAccessible</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredItems\">TileInfo_RequiredItems</system:String>\r\n\r\n\t<!--{StaticResource WaitPage_}-->\r\n\t<system:String x:Key=\"WaitPage_\">WaitPage_</system:String>\r\n\t<system:String x:Key=\"WaitPage_CreatingGame\">WaitPage_CreatingGame</system:String>\r\n\t<system:String x:Key=\"WaitPage_PleaseWait\">WaitPage_PleaseWait</system:String>\r\n\r\n\t<!--{StaticResource WorkshopGui_}-->\r\n\t<system:String x:Key=\"WorkshopGui_\">WorkshopGui_</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAcceptGeneratedJobs\">WorkshopGui_AllowAcceptGeneratedJobs</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AcceptGeneratedJobs\">WorkshopGui_AcceptGeneratedJobs</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoGenerateCraftJobs\">WorkshopGui_AutoGenerateCraftJobs</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoCraftMissingComponents\">WorkshopGui_AutoCraftMissingComponents</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAutoCraftMissingComponents\">WorkshopGui_AllowAutoCraftMissingComponents</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_GeneratesCraftingJobsForMissingComponents\">WorkshopGui_GeneratesCraftingJobsForMissingComponents</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AvailableProducts\">WorkshopGui_AvailableProducts</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ProductionLine\">WorkshopGui_ProductionLine</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcessAnimals\">WorkshopGui_ButcherExcessAnimals</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcess\">WorkshopGui_ButcherExcess</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherTameNotOnPasture\">WorkshopGui_ButcherTameNotOnPasture</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherCorpse\">WorkshopGui_ButcherCorpse</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAllowCorpse\">WorkshopGui_ButcherAllowCorpse</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherOnlyStockpileCorpse\">WorkshopGui_ButcherOnlyStockpileCorpse</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectToStockpile\">WorkshopGui_ConnectToStockpile</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectStockpile\">WorkshopGui_ConnectStockpile</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Connect3x3Stockpile\">WorkshopGui_Connect3x3Stockpile</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectAdjacentStockpile\">WorkshopGui_ConnectAdjacentStockpile</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAnimals\">WorkshopGui_ButcherAnimals</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_SuspendWorkshop\">WorkshopGui_SuspendWorkshop</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopSuspendWork\">WorkshopGui_WorkshopSuspendWork</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopStopWork\">WorkshopGui_WorkshopStopWork</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Trade\">WorkshopGui_Trade</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Max\">WorkshopGui_Max</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderInventory\">WorkshopGui_TraderInventory</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderValue\">WorkshopGui_TraderValue</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerInventory\">WorkshopGui_PlayerInventory</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerValue\">WorkshopGui_PlayerValue</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TradeAction\">WorkshopGui_TradeAction</system:String>\r\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/localization/en_US.xaml",
    "content": "<ResourceDictionary\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:system=\"clr-namespace:System;assembly=mscorlib\">\r\n\r\n\t<!-- String resource that can be localized -->\r\n\t<!--{StaticResource MainPage_}-->\r\n\t<system:String x:Key=\"MainPage_\">MainPage_</system:String>\r\n\t<system:String x:Key=\"MainPage_Ingnomia\">Ingnomia</system:String>\r\n\t<system:String x:Key=\"MainPage_Continue\">Continue</system:String>\r\n\t<system:String x:Key=\"MainPage_NewGame\">New Game</system:String>\r\n\t<system:String x:Key=\"MainPage_SetUpGame\">Set up Game</system:String>\r\n\t<system:String x:Key=\"MainPage_LoadGame\">Load Game</system:String>\r\n\t<system:String x:Key=\"MainPage_Settings\">Settings</system:String>\r\n\t<system:String x:Key=\"MainPage_Exit\">Exit</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMContinue\">Continue the last saved game.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMNewGame\">Start a new game with previous settings.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSetupGame\">Start a new game with new settings.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMLoadGame\">Load a previously saved game.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSettings\">Configure the settings for the game.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMExit\">Exit the game.</system:String>\r\n\r\n\t<!--{StaticResource Agriculture_}-->\r\n\t<system:String x:Key=\"Agriculture_\">Agriculture_</system:String>\r\n\t<system:String x:Key=\"Agriculture_TilledPlots\">Tilled plots</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantsPlanted\">Plants planted</system:String>\r\n\t<system:String x:Key=\"Agriculture_CropsReady\">Crops ready</system:String>\r\n\t<system:String x:Key=\"Agriculture_Suspend\">Suspend</system:String>\r\n\t<system:String x:Key=\"Agriculture_Harvest\">Harvest</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectCrop\">Select crop</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfSeeds\">Number of seeds</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfItems\">Number of items</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfPlants\">Number of plants</system:String>\r\n\t<system:String x:Key=\"Agriculture_Manage\">Manage</system:String>\r\n\t<system:String x:Key=\"Agriculture_Animals\">Animals</system:String>\r\n\t<system:String x:Key=\"Agriculture_Male\">Male</system:String>\r\n\t<system:String x:Key=\"Agriculture_Female\">Female</system:String>\r\n\t<system:String x:Key=\"Agriculture_TameWildAnimals\">Tame wild animals</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestAnimals\">Harvest animals</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestHay\">Harvest hay</system:String>\r\n\t<system:String x:Key=\"Agriculture_StoredFood\">Stored Food</system:String>\r\n\t<system:String x:Key=\"Agriculture_Settings\">Settings</system:String>\r\n\t<system:String x:Key=\"Agriculture_Back\">Back</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectFoodForTroughs\">Select food for troughs</system:String>\r\n\t<system:String x:Key=\"Agriculture_ManageAnimals\">Manage Animals</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectAnimalType\">Select animal type</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfAnimals\">Number of animals</system:String>\r\n\t<system:String x:Key=\"Agriculture_Trees\">Trees</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantTrees\">Plant trees</system:String>\r\n\t<system:String x:Key=\"Agriculture_PickFruit\">Pick fruit</system:String>\r\n\t<system:String x:Key=\"Agriculture_FellTrees\">Fell trees</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectTreeType\">Select tree type</system:String>\r\n\r\n\t<!--{StaticResource CreatureInfo_}-->\r\n\t<system:String x:Key=\"CreatureInfo_\">CreatureInfo_</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Happiness\">Happiness</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Sleep\">Sleep</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Thirst\">Thirst</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Hunger\">Hunger</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Cha\">CHA</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Wis\">WIS</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Int\">INT</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Con\">CON</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Dex\">Dex</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Str\">STR</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Inventory\">Inventory</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Equipment\">Equipment</system:String>\r\n\r\n\t<!--{StaticResource DebugPage_}-->\r\n\t<system:String x:Key=\"DebugPage_\">DebugPage_</system:String>\r\n\t<system:String x:Key=\"DebugPage_Misc\">Misc</system:String>\r\n\t<system:String x:Key=\"DebugPage_Stuff\">Stuff</system:String>\r\n\t<system:String x:Key=\"DebugPage_More\">More</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugFirstPage\">Debug first page</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGnome\">Spawn Gnome</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnTrader\">Spawn Trader</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGoblin\">Spawn Goblin</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugSecondPage\">Debug second page</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugThirdPage\">Debug third page</system:String>\r\n\r\n\t<!--{StaticResource GameGui_}-->\r\n\t<system:String x:Key=\"GameGui_\">GameGui_</system:String>\r\n\t<system:String x:Key=\"GameGui_KingdomName\">Kingdom name</system:String>\r\n\t<system:String x:Key=\"GameGui_Something1\">something</system:String>\r\n\t<system:String x:Key=\"GameGui_Something2\">something</system:String>\r\n\t<system:String x:Key=\"GameGui_D\">D</system:String>\r\n\t<system:String x:Key=\"GameGui_Yes\">Yes</system:String>\r\n\t<system:String x:Key=\"GameGui_Ok\">OK</system:String>\r\n\t<system:String x:Key=\"GameGui_No\">No</system:String>\r\n\t<system:String x:Key=\"GameGui_Build\">Build</system:String>\r\n\t<system:String x:Key=\"GameGui_Mine\">Mine</system:String>\r\n\t<system:String x:Key=\"GameGui_Agriculture\">Agriculture</system:String>\r\n\t<system:String x:Key=\"GameGui_Designations\">Designations</system:String>\r\n\t<system:String x:Key=\"GameGui_Job\">Job</system:String>\r\n\t<system:String x:Key=\"GameGui_Magic\">Magic</system:String>\r\n\t<system:String x:Key=\"GameGui_Kingdom\">Kingdom</system:String>\r\n\t<system:String x:Key=\"GameGui_Stockpiles\">Stockpiles</system:String>\r\n\t<system:String x:Key=\"GameGui_Military\">Military</system:String>\r\n\t<system:String x:Key=\"GameGui_Population\">Population</system:String>\r\n\t<system:String x:Key=\"GameGui_Missions\">Missions</system:String>\r\n\r\n\t<!--{StaticResource InGamePage_}-->\r\n\t<system:String x:Key=\"InGamePage_\">InGamePage_</system:String>\r\n\t<system:String x:Key=\"InGamePage_Ingnomia\">Ingnomia</system:String>\r\n\t<system:String x:Key=\"InGamePage_Resume\">Resume</system:String>\r\n\t<system:String x:Key=\"InGamePage_LoadGame\">Load Game</system:String>\r\n\t<system:String x:Key=\"InGamePage_SaveGame\">Save Game</system:String>\r\n\t<system:String x:Key=\"InGamePage_Settings\">Settings</system:String>\r\n\t<system:String x:Key=\"InGamePage_QuitGame\">Quit game</system:String>\r\n\r\n\t<!--{StaticResource LoadGamePage_}-->\r\n\t<system:String x:Key=\"LoadGamePage_\">LoadGamePage_</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_LoadGame\">Load Game</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_HereSelectedGameInfo\">Here will be info about the selected game.</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Load\">Load</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Back\">Back</system:String>\r\n\r\n\t<!--{StaticResource MilitaryGui_}-->\r\n\t<system:String x:Key=\"MilitaryGui_\">MilitaryGui_</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Squads\">Squads</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Roles\">Roles</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_More\">More</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitarySquads\">Military - Squads</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryRoles\">Military - Roles</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryPriorities\">Military - Priorities</system:String>\r\n\r\n\t<!--{StaticResource Neighbors_}-->\r\n\t<system:String x:Key=\"Neighbors_\">Neighbors_</system:String>\r\n\t<system:String x:Key=\"Neighbors_Neighbors\">Neighbors</system:String>\r\n\t<system:String x:Key=\"Neighbors_Missions\">Missions</system:String>\r\n\t<system:String x:Key=\"Neighbors_More\">More</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsPage\">Neighbors</system:String>\r\n\t<system:String x:Key=\"Neighbors_MissionsPage\">Missions</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsThirdPage\">Neighbors third page</system:String>\r\n\r\n\t<!--{StaticResource NewGamePage_}-->\r\n\t<system:String x:Key=\"NewGamePage_\">NewGamePage_</system:String>\r\n\t<system:String x:Key=\"NewGamePage_SetUpNewGame\">Set up new game</system:String>\r\n\t<system:String x:Key=\"NewGamePage_World\">World</system:String>\r\n\t<system:String x:Key=\"NewGamePage_KingdomName\">Kingdom name:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Seed\">Seed:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Random\">Random</system:String>\r\n\t<system:String x:Key=\"NewGamePage_WorldSize\">World size:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_LargerSizePerformance\">Larger size will impact performance.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_ZLevels\">Z-Levels:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Ground\">Ground:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flatness\">Flatness:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_OceanSize\">Ocean size:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Rivers\">Rivers:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_RiverSize\">River size:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartArea\">Start area:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartingItems\">Starting items</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Presets\">Presets:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NewPreset\">New Preset</system:String>\r\n\t<system:String x:Key=\"NewGamePage_DeletePreset\">Delete Preset</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Gnomes\">Gnomes:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Items\">Items</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Animals\">Animals</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Add\">Add</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Enemies\">Enemies</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulMode\">Peaceful mode.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NoEnemyKingdoms\">No enemy kingdoms.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulAnimalsMayStillAttack\">Aggressive animals still may attack.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flora\">Flora</system:String>\r\n\t<system:String x:Key=\"NewGamePage_TreeDensity\">Tree Density:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PlantDensity\">Plant Density:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Fauna\">Fauna</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsPage\">Wild Animals:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimals\">Maximum number of wild animals</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsAtStart\">at start.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsPage\">Max animals per type:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimals\">Maximum number animals per type.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsIncludesDomesticated\">This also influences domesticated animals.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Back\">Back</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Embark\">Embark</system:String>\r\n\r\n\t<!--{StaticResource PopulationWindow_}-->\r\n\t<system:String x:Key=\"PopulationWindow_\">PopulationWindow_</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Skills\">Skills</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Schedule\">Schedule</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProf\">Edit Prof</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Name\">Name</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Professions\">Professions</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_None\">None</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Eat\">Eat</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Sleep\">Sleep</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Train\">Train</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProfessions\">Edit Professions</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_New\">new</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Delete\">delete</system:String>\r\n\r\n\t<!--{StaticResource SettingsPage_}-->\r\n\t<system:String x:Key=\"SettingsPage_\">SettingsPage_</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Settings\">Settings</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Game\">Game</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Video\">Video</system:String>\r\n\t<system:String x:Key=\"SettingsPage_VideoContent\">Video Settings</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Audio\">Audio</system:String>\r\n\t<system:String x:Key=\"SettingsPage_AudioContent\">There is no audio yet.</system:String>\r\n\t<system:String x:Key=\"SettingsPage_AudioMasterVolume\">Master Volume</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Controls\">Controls</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Back\">Back</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Accept\">Accept</system:String>\r\n\t<system:String x:Key=\"SettingsPage_UiScale\">UI Scale</system:String>\r\n\t<system:String x:Key=\"SettingsPage_FullScreen\">Full Screen</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Language\">Language</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeyboardSpeed\">Keyboard speed</system:String>\r\n\t<system:String x:Key=\"SettingsPage_LightMin\">minimum light level</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeybindingsPlaceholder\">This page is a placeholder. Keybindings are not implemented yet.</system:String>\r\n\t\r\n\r\n\t<!--{StaticResource StockpileGui_}-->\r\n\t<system:String x:Key=\"StockpileGui_\">StockpileGui_</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stockpile\">Stockpile</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Suspend\">Suspend</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpileSuspend\">Suspend stockpile.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePushable\">Stockpile will stop accepting items.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullable\">Items can still be taken out of the stockpile.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromHere\">Pull from here</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHere\">Pull from here.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHigher\">Stockpiles with higher priority may pull items from here.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromOther\">Pull from other</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromOther\">Pull from other.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromLower\">Stockpile may pull from other stockpiles with lower priority.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_CopySetup\">Copy setup</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PasteSetup\">Paste setup</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Filters\">Filters</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stock\">Stock</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Limits\">Limits</system:String>\r\n\t<system:String x:Key=\"StockpileGui_LimitsImplementedLater\">Will be implemented later.</system:String>\r\n\r\n\t<!--{StaticResource TileInfo_}-->\r\n\t<system:String x:Key=\"TileInfo_\">TileInfo_</system:String>\r\n\t<system:String x:Key=\"TileInfo_Stockpile\">Stockpile:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Manage\">Manage</system:String>\r\n\t<system:String x:Key=\"TileInfo_AssignTo\">Assign to:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Value\">Value:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Enclosed\">Enclosed:</system:String>\r\n\t<system:String x:Key=\"TileInfo_HasRoof\">Has Roof:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Beds\">Beds:</system:String>\r\n\t<system:String x:Key=\"TileInfo_SoundAlarm\">Sound the Alarm!</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmSoundAlarm\">Sound the Alarm!</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmRetreatHere\">Civilian gnomes will retreat here.</system:String>\r\n\t<system:String x:Key=\"TileInfo_Job\">Job:</system:String>\r\n\t<system:String x:Key=\"TileInfo_WorkedBy\">Worked by:</system:String>\r\n\t<system:String x:Key=\"TileInfo_JobPriority\">Job priority:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredSkill\">Required skill:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredTool\">Required tool:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAvailable\">Required tool available:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAccessible\">Accessible:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredItems\">Required Items:</system:String>\r\n\r\n\t<!--{StaticResource WaitPage_}-->\r\n\t<system:String x:Key=\"WaitPage_\">WaitPage_</system:String>\r\n\t<system:String x:Key=\"WaitPage_CreatingGame\">Creating Game</system:String>\r\n\t<system:String x:Key=\"WaitPage_PleaseWait\">Please Wait</system:String>\r\n\r\n\t<!--{StaticResource WorkshopGui_}-->\r\n\t<system:String x:Key=\"WorkshopGui_\">WorkshopGui_</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAcceptGeneratedJobs\">Accept generated jobs</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AcceptGeneratedJobs\">Accept generated jobs.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoGenerateCraftJobs\">Will auto generate craft jobs for items in constructions and other workshops.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoCraftMissingComponents\">Auto craft missing components</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAutoCraftMissingComponents\">Auto craft missing components.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_GeneratesCraftingJobsForMissingComponents\">Generates crafting jobs in workshops for missing components.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AvailableProducts\">Available products</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ProductionLine\">Production line</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcessAnimals\">Butcher excess animals</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcess\">Butcher excess.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherTameNotOnPasture\">Butcher any tame animal not on a pasture.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherCorpse\">Butcher corpses</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAllowCorpse\">Butcher corpses.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherOnlyStockpileCorpse\">Corpses must be in stockpiles to be considered.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectToStockpile\">Connect to stockpile</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectStockpile\">Connect stockpile.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Connect3x3Stockpile\">Connect to a stockpile of maximum size 3x3.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectAdjacentStockpile\">That stockpile must be adjacent to the input tile .</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAnimals\">Butcher Animals</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_SuspendWorkshop\">Suspend</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopSuspendWork\">Suspend workshop.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopStopWork\">Workshop will stop working.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Trade\">Trade</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Max\">max</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderInventory\">Trader inventory:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderValue\">Trader value:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerInventory\">Player inventory:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerValue\">Player value:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TradeAction\">Trade</system:String>\r\n\t\r\n\t\r\n\t<system:String x:Key=\"TestItemName_RawWood\">-raw wood-</system:String>\r\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/localization/fr_FR.xaml",
    "content": "<ResourceDictionary\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:system=\"clr-namespace:System;assembly=mscorlib\">\r\n\r\n\t<!-- String resource that can be localized -->\r\n\t<!--{StaticResource MainPage_}-->\r\n\t<system:String x:Key=\"MainPage_\">MainPage_</system:String>\r\n\t<system:String x:Key=\"MainPage_Ingnomia\">Ingnomia</system:String>\r\n\t<system:String x:Key=\"MainPage_Continue\">Reprendre</system:String>\r\n\t<system:String x:Key=\"MainPage_NewGame\">Recommencer</system:String>\r\n\t<system:String x:Key=\"MainPage_SetUpGame\">Nouvelle partie</system:String>\r\n\t<system:String x:Key=\"MainPage_LoadGame\">Charger</system:String>\r\n\t<system:String x:Key=\"MainPage_Settings\">Paramètres</system:String>\r\n\t<system:String x:Key=\"MainPage_Exit\">Quitter</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMContinue\">Reprendre la dernière partie sauvegardée.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMNewGame\">Démarrer une nouvelle partie avec la configuration précédente.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSetupGame\">Démarrer une nouvelle partie en choisissant la configuration.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMLoadGame\">Charger une sauvegarde.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSettings\">Afficher les options.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMExit\">Quitter le jeu.</system:String>\r\n\r\n\t<!--{StaticResource Agriculture_}-->\r\n\t<system:String x:Key=\"Agriculture_\">Agriculture_</system:String>\r\n\t<system:String x:Key=\"Agriculture_TilledPlots\">Labours</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantsPlanted\">Plants</system:String>\r\n\t<system:String x:Key=\"Agriculture_CropsReady\">Récoltes</system:String>\r\n\t<system:String x:Key=\"Agriculture_Suspend\">Jachère</system:String>\r\n\t<system:String x:Key=\"Agriculture_Harvest\">Récolte</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectCrop\">Semis</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfSeeds\">Graines</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfItems\">Récoltes</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfPlants\">Plants</system:String>\r\n\t<system:String x:Key=\"Agriculture_Manage\">Nourriture</system:String>\r\n\t<system:String x:Key=\"Agriculture_Animals\">Bêtes</system:String>\r\n\t<system:String x:Key=\"Agriculture_Male\">Mâles</system:String>\r\n\t<system:String x:Key=\"Agriculture_Female\">Femelles</system:String>\r\n\t<system:String x:Key=\"Agriculture_TameWildAnimals\">Domestiquer les animaux sauvages</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestAnimals\">Entretenir</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestHay\">Désherber</system:String>\r\n\t<system:String x:Key=\"Agriculture_StoredFood\">Fourrages</system:String>\r\n\t<system:String x:Key=\"Agriculture_Settings\">Paramètres</system:String>\r\n\t<system:String x:Key=\"Agriculture_Back\">Retour</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectFoodForTroughs\">Fourrages</system:String>\r\n\t<system:String x:Key=\"Agriculture_ManageAnimals\">Gérer</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectAnimalType\">Type d'animaux</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfAnimals\">Quantité</system:String>\r\n\t<system:String x:Key=\"Agriculture_Trees\">Arbres</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantTrees\">Replanter</system:String>\r\n\t<system:String x:Key=\"Agriculture_PickFruit\">Récolter</system:String>\r\n\t<system:String x:Key=\"Agriculture_FellTrees\">Abattre</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectTreeType\">Plantation</system:String>\r\n\r\n\t<!--{StaticResource CreatureInfo_}-->\r\n\t<system:String x:Key=\"CreatureInfo_\">CreatureInfo_</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Happiness\">Joie</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Sleep\">Énergie</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Thirst\">Eau</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Hunger\">Nourriture</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Cha\">Char</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Wis\">Sag</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Int\">Int</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Con\">Cons</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Dex\">Dex</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Str\">For</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Inventory\">Inventaire</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Equipment\">Équipement</system:String>\r\n\r\n\t<!--{StaticResource DebugPage_}-->\r\n\t<system:String x:Key=\"DebugPage_\">DebugPage_</system:String>\r\n\t<system:String x:Key=\"DebugPage_Misc\">Invocations</system:String>\r\n\t<system:String x:Key=\"DebugPage_Stuff\">Équipements</system:String>\r\n\t<system:String x:Key=\"DebugPage_More\">Autres</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugFirstPage\">Invoquer</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGnome\">Gnome</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnTrader\">Marchand</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGoblin\">Goblin</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugSecondPage\">Équipements</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugThirdPage\">Autres</system:String>\r\n\r\n\t<!--{StaticResource GameGui_}-->\r\n\t<system:String x:Key=\"GameGui_\">GameGui_</system:String>\r\n\t<system:String x:Key=\"GameGui_KingdomName\">Royaume :</system:String>\r\n\t<system:String x:Key=\"GameGui_Something1\">truc</system:String>\r\n\t<system:String x:Key=\"GameGui_Something2\">truc</system:String>\r\n\t<system:String x:Key=\"GameGui_D\">D</system:String>\r\n\t<system:String x:Key=\"GameGui_Yes\">Oui</system:String>\r\n\t<system:String x:Key=\"GameGui_Ok\">Ok</system:String>\r\n\t<system:String x:Key=\"GameGui_No\">Non</system:String>\r\n\t<system:String x:Key=\"GameGui_Build\">Construction</system:String>\r\n\t<system:String x:Key=\"GameGui_Mine\">Mine</system:String>\r\n\t<system:String x:Key=\"GameGui_Agriculture\">Agriculture</system:String>\r\n\t<system:String x:Key=\"GameGui_Designations\">Zones</system:String>\r\n\t<system:String x:Key=\"GameGui_Job\">Tâches</system:String>\r\n\t<system:String x:Key=\"GameGui_Magic\">Magie</system:String>\r\n\t<system:String x:Key=\"GameGui_Kingdom\">Royaumes</system:String>\r\n\t<system:String x:Key=\"GameGui_Stockpiles\">Réserves</system:String>\r\n\t<system:String x:Key=\"GameGui_Military\">Armée</system:String>\r\n\t<system:String x:Key=\"GameGui_Population\">Démographie</system:String>\r\n\t<system:String x:Key=\"GameGui_Missions\">Quêtes</system:String>\r\n\r\n\t<!--{StaticResource InGamePage_}-->\r\n\t<system:String x:Key=\"InGamePage_\">InGamePage_</system:String>\r\n\t<system:String x:Key=\"InGamePage_Ingnomia\">Ingnomia</system:String>\r\n\t<system:String x:Key=\"InGamePage_Resume\">Reprendre</system:String>\r\n\t<system:String x:Key=\"InGamePage_LoadGame\">Charger</system:String>\r\n\t<system:String x:Key=\"InGamePage_SaveGame\">Sauvegarder</system:String>\r\n\t<system:String x:Key=\"InGamePage_Settings\">Paramètres</system:String>\r\n\t<system:String x:Key=\"InGamePage_QuitGame\">Quitter</system:String>\r\n\r\n\t<!--{StaticResource LoadGamePage_}-->\r\n\t<system:String x:Key=\"LoadGamePage_\">LoadGamePage_</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_LoadGame\">Choisir la partie à charger</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_HereSelectedGameInfo\">Informations sur la partie choisie à venir.</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Load\">Charger</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Back\">Annuler</system:String>\r\n\r\n\t<!--{StaticResource MilitaryGui_}-->\r\n\t<system:String x:Key=\"MilitaryGui_\">MilitaryGui_</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Squads\">Affectations</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Roles\">Équipes</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_More\">Autre</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitarySquads\">Affectations</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryRoles\">Équipes</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryPriorities\">Priorités</system:String>\r\n\r\n\t<!--{StaticResource Neighbors_}-->\r\n\t<system:String x:Key=\"Neighbors_\">Neighbors_</system:String>\r\n\t<system:String x:Key=\"Neighbors_Neighbors\">Ambassades</system:String>\r\n\t<system:String x:Key=\"Neighbors_Missions\">Requêtes</system:String>\r\n\t<system:String x:Key=\"Neighbors_More\">Autre</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsPage\">Ambassades</system:String>\r\n\t<system:String x:Key=\"Neighbors_MissionsPage\">Requêtes</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsThirdPage\">Autre</system:String>\r\n\r\n\t<!--{StaticResource NewGamePage_}-->\r\n\t<system:String x:Key=\"NewGamePage_\">NewGamePage_</system:String>\r\n\t<system:String x:Key=\"NewGamePage_SetUpNewGame\">Paramètres de la partie</system:String>\r\n\t<system:String x:Key=\"NewGamePage_World\">Carte</system:String>\r\n\t<system:String x:Key=\"NewGamePage_KingdomName\">Nom du royaume :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Seed\">Graine :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Random\">Au hasard</system:String>\r\n\t<system:String x:Key=\"NewGamePage_WorldSize\">Taille de la carte :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_LargerSizePerformance\">Une grande taille réduit les performances.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_ZLevels\">Profondeurs :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Ground\">Sol :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flatness\">Dénivelé :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_OceanSize\">Taille de l'océan :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Rivers\">Rivières :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_RiverSize\">Largeur :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartArea\">Zone de départ :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartingItems\">Objets préparés</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Presets\">Préconfigurations :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NewPreset\">Nouvelle</system:String>\r\n\t<system:String x:Key=\"NewGamePage_DeletePreset\">Effacer</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Gnomes\">Gnomes :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Items\">Objets</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Animals\">Animaux</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Add\">Ajouter</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Enemies\">Ennemis</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulMode\">Mode pacifique.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NoEnemyKingdoms\">Pas de royaumes rivaux.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulAnimalsMayStillAttack\">Les animaux sauvages restent agressifs.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flora\">Flore</system:String>\r\n\t<system:String x:Key=\"NewGamePage_TreeDensity\">Arbres :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PlantDensity\">Buissons :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Fauna\">Faune</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsPage\">Animaux sauvages :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimals\">Nombre d'animaux sauvages maximum</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsAtStart\">en début de partie.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsPage\">Par race :</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimals\">Nombre d'animaux maximum par types.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsIncludesDomesticated\">Inclue les animaux domestiques.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Back\">Annuler</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Embark\">En route !</system:String>\r\n\r\n\t<!--{StaticResource PopulationWindow_}-->\r\n\t<system:String x:Key=\"PopulationWindow_\">PopulationWindow_</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Skills\">Compétences</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Schedule\">Planning</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProf\">Assignations</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Name\">Gnome</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Professions\">Assignation</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_None\">Libre</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Eat\">Manger</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Sleep\">Dormir</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Train\">Travailler</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProfessions\">Modifier les assignations</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_New\">Nouvelle</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Delete\">Supprimer</system:String>\r\n\r\n\t<!--{StaticResource SettingsPage_}-->\r\n\t<system:String x:Key=\"SettingsPage_\">SettingsPage_</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Settings\">Paramètres</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Game\">Jeu</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Video\">Vidéo</system:String>\r\n\t<system:String x:Key=\"SettingsPage_VideoContent\">Paramètres vidéo</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Audio\">Audio</system:String>\r\n\t<system:String x:Key=\"SettingsPage_AudioContent\">Pas de son pour le moment.</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Controls\">Contrôles</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Back\">Annuler</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Accept\">Valider</system:String>\r\n\t<system:String x:Key=\"SettingsPage_UiScale\">Échelle de l'interface</system:String>\r\n\t<system:String x:Key=\"SettingsPage_FullScreen\">Plein écran</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Language\">Langue</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeyboardSpeed\">Défilement au clavier</system:String>\r\n\t<system:String x:Key=\"SettingsPage_LightMin\">Luminosité minimale</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeybindingsPlaceholder\">Cette page est un espace réservé. Les associations de touches ne sont pas encore implémentées.</system:String>\r\n\r\n\t<!--{StaticResource StockpileGui_}-->\r\n\t<system:String x:Key=\"StockpileGui_\">StockpileGui_</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stockpile\">Réserve</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Suspend\">Arrêter</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpileSuspend\">Arrêter le stockage.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePushable\">Cette réserve arrêtera le stockage d'objets.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullable\">Les objets pourront néanmoins être sortis.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromHere\">Envoyer</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHere\">Envoyer vers d'autres endroits.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHigher\">Les réserves avec une priorité plus élevée se serviront dans celle-ci.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromOther\">Recevoir</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromOther\">Prendre d'autres endroits.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromLower\">Cette réserve peut se remplir à partir de réserves à priorité plus faible.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_CopySetup\">Copier</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PasteSetup\">Coller</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Filters\">Accepter</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stock\">Stock</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Limits\">Limites</system:String>\r\n\t<system:String x:Key=\"StockpileGui_LimitsImplementedLater\">Implémentation à venir.</system:String>\r\n\r\n\t<!--{StaticResource TileInfo_}-->\r\n\t<system:String x:Key=\"TileInfo_\">TileInfo_</system:String>\r\n\t<system:String x:Key=\"TileInfo_Stockpile\">Réserve :</system:String>\r\n\t<system:String x:Key=\"TileInfo_Manage\">Gérer</system:String>\r\n\t<system:String x:Key=\"TileInfo_AssignTo\">Assignation :</system:String>\r\n\t<system:String x:Key=\"TileInfo_Value\">Valeur :</system:String>\r\n\t<system:String x:Key=\"TileInfo_Enclosed\">Clos :</system:String>\r\n\t<system:String x:Key=\"TileInfo_HasRoof\">Toiture :</system:String>\r\n\t<system:String x:Key=\"TileInfo_Beds\">Lits :</system:String>\r\n\t<system:String x:Key=\"TileInfo_SoundAlarm\">Alarme !</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmSoundAlarm\">Sonner l'alarme.</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmRetreatHere\">Point de rassemblement des gnomes civils.</system:String>\r\n\t<system:String x:Key=\"TileInfo_Job\">Tâche :</system:String>\r\n\t<system:String x:Key=\"TileInfo_WorkedBy\">Travailleur :</system:String>\r\n\t<system:String x:Key=\"TileInfo_JobPriority\">Priorité :</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredSkill\">Compétence requise :</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredTool\">Outils nécessaires :</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAvailable\">Outils disponibles :</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAccessible\">Accessible :</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredItems\">Objets requis :</system:String>\r\n\r\n\t<!--{StaticResource WaitPage_}-->\r\n\t<system:String x:Key=\"WaitPage_\">WaitPage_</system:String>\r\n\t<system:String x:Key=\"WaitPage_CreatingGame\">Préparation du jeu</system:String>\r\n\t<system:String x:Key=\"WaitPage_PleaseWait\">Veuillez patienter...</system:String>\r\n\r\n\t<!--{StaticResource WorkshopGui_}-->\r\n\t<system:String x:Key=\"WorkshopGui_\">WorkshopGui_</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAcceptGeneratedJobs\">Accepte les tâches générées</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AcceptGeneratedJobs\">Autorise les tâches générées.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoGenerateCraftJobs\">Génèrera automatiquement les prérequis pour les ateliers le nécessitant.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoCraftMissingComponents\">Auto-craft des objets manquants</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAutoCraftMissingComponents\">Préparation automatique des objets manquants.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_GeneratesCraftingJobsForMissingComponents\">Génèrera automatiquement les prérequis dans les ateliers autorisés.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AvailableProducts\">Recettes</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ProductionLine\">Production</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcessAnimals\">Abattre les animaux en surnombre</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcess\">Abattre le surnombre du troupeau.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherTameNotOnPasture\">Abattra tout animal domestique hors pâturage.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherCorpse\">Préparer les carcasses</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAllowCorpse\">Préparation de carcasses.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherOnlyStockpileCorpse\">Elles doivent être dans une réserve pour être prises en compte.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectToStockpile\">Lier à une réserve</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectStockpile\">Liaison vers une réserve.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Connect3x3Stockpile\">Liaison vers une zone de 3x3 réserves max.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectAdjacentStockpile\">La zone prise en compte entoure la réserve liée.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAnimals\">Abattre les animaux</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_SuspendWorkshop\">Arrêter</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopSuspendWork\">Arrêter l'atelier.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopStopWork\">L'atelier va être mis à l'arrêt.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Trade\">Marchander</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Max\">max</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderInventory\">Vendeur :</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderValue\">Demande :</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerInventory\">Joueur :</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerValue\">Offre :</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TradeAction\">Valider</system:String>\r\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/localization/pt_BR.xaml",
    "content": "<ResourceDictionary\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:system=\"clr-namespace:System;assembly=mscorlib\">\r\n\r\n\t<!-- String resource that can be localized -->\r\n\t<!--{StaticResource MainPage_}-->\r\n\t<system:String x:Key=\"MainPage_\">MainPage_</system:String>\r\n\t<system:String x:Key=\"MainPage_Ingnomia\">Ingnomia</system:String>\r\n\t<system:String x:Key=\"MainPage_Continue\">Continuar</system:String>\r\n\t<system:String x:Key=\"MainPage_NewGame\">Novo Jogo</system:String>\r\n\t<system:String x:Key=\"MainPage_SetUpGame\">Preparar Jogo</system:String>\r\n\t<system:String x:Key=\"MainPage_LoadGame\">Carregar Jogo</system:String>\r\n\t<system:String x:Key=\"MainPage_Settings\">Configurações</system:String>\r\n\t<system:String x:Key=\"MainPage_Exit\">Sair</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMContinue\">Continua o último jogo salvo.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMNewGame\">Inicia um novo jogo com as configurações anteriores.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSetupGame\">Inicia um novo jogo com novas configurações.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMLoadGame\">Carrega um jogo salvo anteriormente.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMSettings\">Configura as opções do jogo.</system:String>\r\n\t<system:String x:Key=\"MainPage_Hint_MMExit\">Sai do jogo.</system:String>\r\n\r\n\t<!--{StaticResource Agriculture_}-->\r\n\t<system:String x:Key=\"Agriculture_\">Agriculture_</system:String>\r\n\t<system:String x:Key=\"Agriculture_TilledPlots\">Lotes arados</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantsPlanted\">Plantas plantadas</system:String>\r\n\t<system:String x:Key=\"Agriculture_CropsReady\">Safra pronta</system:String>\r\n\t<system:String x:Key=\"Agriculture_Suspend\">Suspender</system:String>\r\n\t<system:String x:Key=\"Agriculture_Harvest\">Colher</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectCrop\">Selecionar colheita</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfSeeds\">Número de sementes</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfItems\">Número de itens</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfPlants\">Número de plantas</system:String>\r\n\t<system:String x:Key=\"Agriculture_Manage\">Gerenciar</system:String>\r\n\t<system:String x:Key=\"Agriculture_Animals\">Animais</system:String>\r\n\t<system:String x:Key=\"Agriculture_Male\">Macho</system:String>\r\n\t<system:String x:Key=\"Agriculture_Female\">Fêmea</system:String>\r\n\t<system:String x:Key=\"Agriculture_TameWildAnimals\">Domesticar animais</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestAnimals\">Colher animais</system:String>\r\n\t<system:String x:Key=\"Agriculture_HarvestHay\">Colher feno</system:String>\r\n\t<system:String x:Key=\"Agriculture_StoredFood\">Comida armazenada</system:String>\r\n\t<system:String x:Key=\"Agriculture_Settings\">Opções</system:String>\r\n\t<system:String x:Key=\"Agriculture_Back\">Voltar</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectFoodForTroughs\">Selecionar comida para pensamentos</system:String>\r\n\t<system:String x:Key=\"Agriculture_ManageAnimals\">Gerenciar animais</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectAnimalType\">Selecione o tipo de animal</system:String>\r\n\t<system:String x:Key=\"Agriculture_NumberOfAnimals\">Número de animais</system:String>\r\n\t<system:String x:Key=\"Agriculture_Trees\">Árvores</system:String>\r\n\t<system:String x:Key=\"Agriculture_PlantTrees\">Plantar árvores</system:String>\r\n\t<system:String x:Key=\"Agriculture_PickFruit\">Colher frutas</system:String>\r\n\t<system:String x:Key=\"Agriculture_FellTrees\">Derrubar árvores</system:String>\r\n\t<system:String x:Key=\"Agriculture_SelectTreeType\">Selecione o tipo de árvore</system:String>\r\n\r\n\t<!--{StaticResource CreatureInfo_}-->\r\n\t<system:String x:Key=\"CreatureInfo_\">CreatureInfo_</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Happiness\">Felicidade</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Sleep\">Sono</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Thirst\">Sede</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Hunger\">Fome</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Cha\">CAR</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Wis\">SAB</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Int\">INT</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Con\">CON</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Dex\">DES</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Str\">FOR</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Inventory\">Inventário</system:String>\r\n\t<system:String x:Key=\"CreatureInfo_Equipment\">Equipamentos</system:String>\r\n\r\n\t<!--{StaticResource DebugPage_}-->\r\n\t<system:String x:Key=\"DebugPage_\">DebugPage_</system:String>\r\n\t<system:String x:Key=\"DebugPage_Misc\">Misc</system:String>\r\n\t<system:String x:Key=\"DebugPage_Stuff\">Coisas</system:String>\r\n\t<system:String x:Key=\"DebugPage_More\">Mais</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugFirstPage\">Primeira página de depuração</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGnome\">Gerar Gnomo</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnTrader\">Gerar Vendedor</system:String>\r\n\t<system:String x:Key=\"DebugPage_SpawnGoblin\">Gerar Goblin</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugSecondPage\">Segunda página de depuração</system:String>\r\n\t<system:String x:Key=\"DebugPage_DebugThirdPage\">Terceira página de depuração</system:String>\r\n\r\n\t<!--{StaticResource GameGui_}-->\r\n\t<system:String x:Key=\"GameGui_\">GameGui_</system:String>\r\n\t<system:String x:Key=\"GameGui_KingdomName\">Nome do Reino</system:String>\r\n\t<system:String x:Key=\"GameGui_Something1\">algo</system:String>\r\n\t<system:String x:Key=\"GameGui_Something2\">algo</system:String>\r\n\t<system:String x:Key=\"GameGui_D\">D</system:String>\r\n\t<system:String x:Key=\"GameGui_Yes\">Sim</system:String>\r\n\t<system:String x:Key=\"GameGui_Ok\">OK</system:String>\r\n\t<system:String x:Key=\"GameGui_No\">Não</system:String>\r\n\t<system:String x:Key=\"GameGui_Build\">Construir</system:String>\r\n\t<system:String x:Key=\"GameGui_Mine\">Minerar</system:String>\r\n\t<system:String x:Key=\"GameGui_Agriculture\">Agricultura</system:String>\r\n\t<system:String x:Key=\"GameGui_Designations\">Áreas</system:String>\r\n\t<system:String x:Key=\"GameGui_Job\">Tarefas</system:String>\r\n\t<system:String x:Key=\"GameGui_Magic\">Magia</system:String>\r\n\t<system:String x:Key=\"GameGui_Kingdom\">Reino</system:String>\r\n\t<system:String x:Key=\"GameGui_Stockpiles\">Estoque</system:String>\r\n\t<system:String x:Key=\"GameGui_Military\">Militar</system:String>\r\n\t<system:String x:Key=\"GameGui_Population\">População</system:String>\r\n\t<system:String x:Key=\"GameGui_Missions\">Missões</system:String>\r\n\r\n\t<!--{StaticResource InGamePage_}-->\r\n\t<system:String x:Key=\"InGamePage_\">InGamePage_</system:String>\r\n\t<system:String x:Key=\"InGamePage_Ingnomia\">Ingnomia</system:String>\r\n\t<system:String x:Key=\"InGamePage_Resume\">Continuar</system:String>\r\n\t<system:String x:Key=\"InGamePage_LoadGame\">Carregar Jogo</system:String>\r\n\t<system:String x:Key=\"InGamePage_SaveGame\">Salvar Jogo</system:String>\r\n\t<system:String x:Key=\"InGamePage_Settings\">Configurações</system:String>\r\n\t<system:String x:Key=\"InGamePage_QuitGame\">Sair do Jogo</system:String>\r\n\r\n\t<!--{StaticResource LoadGamePage_}-->\r\n\t<system:String x:Key=\"LoadGamePage_\">LoadGamePage_</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_LoadGame\">Carregar Jogo</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_HereSelectedGameInfo\">Aqui vai ter informações sobre o jogo selecionado.</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Load\">Carregar</system:String>\r\n\t<system:String x:Key=\"LoadGamePage_Back\">Voltar</system:String>\r\n\r\n\t<!--{StaticResource MilitaryGui_}-->\r\n\t<system:String x:Key=\"MilitaryGui_\">MilitaryGui_</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Squads\">Esquadrões</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_Roles\">Papéis</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_More\">Mais</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitarySquads\">Militar - Esquadrões</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryRoles\">Militar - Papéis</system:String>\r\n\t<system:String x:Key=\"MilitaryGui_MilitaryPriorities\">Militar - Prioridades</system:String>\r\n\r\n\t<!--{StaticResource Neighbors_}-->\r\n\t<system:String x:Key=\"Neighbors_\">Neighbors_</system:String>\r\n\t<system:String x:Key=\"Neighbors_Neighbors\">Vizinhos</system:String>\r\n\t<system:String x:Key=\"Neighbors_Missions\">Missões</system:String>\r\n\t<system:String x:Key=\"Neighbors_More\">Mais</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsPage\">Vizinhos</system:String>\r\n\t<system:String x:Key=\"Neighbors_MissionsPage\">Missões</system:String>\r\n\t<system:String x:Key=\"Neighbors_NeighborsThirdPage\">Vizinhos terceira página</system:String>\r\n\r\n\t<!--{StaticResource NewGamePage_}-->\r\n\t<system:String x:Key=\"NewGamePage_\">NewGamePage_</system:String>\r\n\t<system:String x:Key=\"NewGamePage_SetUpNewGame\">Preparar novo jogo</system:String>\r\n\t<system:String x:Key=\"NewGamePage_World\">Mundo</system:String>\r\n\t<system:String x:Key=\"NewGamePage_KingdomName\">Nome do reino:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Seed\">Seed:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Random\">Aleatório</system:String>\r\n\t<system:String x:Key=\"NewGamePage_WorldSize\">Tamanho:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_LargerSizePerformance\">Tamanhos maiores terão impacto na performance.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flatness\">Rugosidade:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_OceanSize\">Oceano (tamanho):</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Rivers\">Rios:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_RiverSize\">Rios (tamanho):</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartArea\">Área inicial:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_StartingItems\">Itens iniciais</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Presets\">Pré-ajuste:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NewPreset\">Novo pré-ajuste</system:String>\r\n\t<system:String x:Key=\"NewGamePage_DeletePreset\">Remover pré-ajuste</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Gnomes\">Gnomos:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Items\">Itens</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Animals\">Animais</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Add\">Adicionar</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Enemies\">Inimigos</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulMode\">Modo pacífico.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NoEnemyKingdoms\">Sem reinos inimigos.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PeacefulAnimalsMayStillAttack\">Animais agressivos ainda podem atacar.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Flora\">Flora</system:String>\r\n\t<system:String x:Key=\"NewGamePage_TreeDensity\">Árvores (%):</system:String>\r\n\t<system:String x:Key=\"NewGamePage_PlantDensity\">Plantas (%):</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Fauna\">Fauna</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsPage\">Animais selvagens:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimals\">Número máximo de animais</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxWildAnimalsAtStart\">selvagens no início do jogo.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsPage\">Máx por tipo:</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimals\">Número máximo de animais de cada tipo,</system:String>\r\n\t<system:String x:Key=\"NewGamePage_NumberMaxAnimalsIncludesDomesticated\">também influencia os animais domesticados.</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Back\">Voltar</system:String>\r\n\t<system:String x:Key=\"NewGamePage_Embark\">Embarcar</system:String>\r\n\r\n\t<!--{StaticResource PopulationWindow_}-->\r\n\t<system:String x:Key=\"PopulationWindow_\">PopulationWindow_</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Skills\">Proficiências</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Schedule\">Agenda</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProf\">Edit Prof</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Name\">Nome</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Professions\">Profissões</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_None\">Nada</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Eat\">Comer</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Sleep\">Dormir</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Train\">Treinar</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_EditProfessions\">Editar Profissões</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_New\">Nova</system:String>\r\n\t<system:String x:Key=\"PopulationWindow_Delete\">Remover</system:String>\r\n\r\n\t<!--{StaticResource SettingsPage_}-->\r\n\t<system:String x:Key=\"SettingsPage_\">SettingsPage_</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Settings\">Configurações</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Game\">Jogo</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Video\">Vídeo</system:String>\r\n\t<system:String x:Key=\"SettingsPage_VideoContent\">Configurações do Vídeo</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Audio\">Áudio</system:String>\r\n\t<system:String x:Key=\"SettingsPage_AudioContent\">Ainda não tem áudio.</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Controls\">Controles</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Back\">Voltar</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Accept\">Aceitar</system:String>\r\n\t<system:String x:Key=\"SettingsPage_UiScale\">Escala da Interface</system:String>\r\n\t<system:String x:Key=\"SettingsPage_FullScreen\">Tela Cheia</system:String>\r\n\t<system:String x:Key=\"SettingsPage_Language\">Idioma</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeyboardSpeed\">Velocidade do teclado</system:String>\r\n\t<system:String x:Key=\"SettingsPage_LightMin\">Nível mínimo de luz</system:String>\r\n\t<system:String x:Key=\"SettingsPage_KeybindingsPlaceholder\">Esta página é um espaço reservado. As combinações de teclas ainda não foram implementadas.</system:String>\r\n\t\r\n\r\n\t<!--{StaticResource StockpileGui_}-->\r\n\t<system:String x:Key=\"StockpileGui_\">StockpileGui_</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stockpile\">Estoque</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Suspend\">Suspender</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpileSuspend\">Suspender estoque.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePushable\">O estoque parará de aceitar itens.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullable\">Itens ainda podem ser retirados do estoque.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromHere\">Pegar daqui</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHere\">Pegar daqui.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromHigher\">Estoques com maior prioridade podem pedir itens daqui.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PullFromOther\">Pedir de outro</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromOther\">Pedir de outro.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_StockpilePullFromLower\">Estoques podem pedir de outros estoques com menor prioridade.</system:String>\r\n\t<system:String x:Key=\"StockpileGui_CopySetup\">Copiar opções</system:String>\r\n\t<system:String x:Key=\"StockpileGui_PasteSetup\">Colar opções</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Filters\">Filtros</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Stock\">Estoque</system:String>\r\n\t<system:String x:Key=\"StockpileGui_Limits\">Limites</system:String>\r\n\t<system:String x:Key=\"StockpileGui_LimitsImplementedLater\">Será implementado mais tarde.</system:String>\r\n\r\n\t<!--{StaticResource TileInfo_}-->\r\n\t<system:String x:Key=\"TileInfo_\">TileInfo_</system:String>\r\n\t<system:String x:Key=\"TileInfo_Stockpile\">Estoque:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Manage\">Gerenciar</system:String>\r\n\t<system:String x:Key=\"TileInfo_AssignTo\">Atribuir para:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Value\">Valor:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Enclosed\">Fechado:</system:String>\r\n\t<system:String x:Key=\"TileInfo_HasRoof\">Têm telhado:</system:String>\r\n\t<system:String x:Key=\"TileInfo_Beds\">Camas:</system:String>\r\n\t<system:String x:Key=\"TileInfo_SoundAlarm\">Soar o alarme!</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmSoundAlarm\">Soar o alarme!</system:String>\r\n\t<system:String x:Key=\"TileInfo_AlarmRetreatHere\">Gnomos civís fugiram para cá.</system:String>\r\n\t<system:String x:Key=\"TileInfo_Job\">Tarefa:</system:String>\r\n\t<system:String x:Key=\"TileInfo_WorkedBy\">Feito por:</system:String>\r\n\t<system:String x:Key=\"TileInfo_JobPriority\">Prioridade da tarefa:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredSkill\">Proficiência necessária:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredTool\">Ferramenta necessária:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAvailable\">Ferramenta necessária disponível:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredToolAccessible\">Acessível:</system:String>\r\n\t<system:String x:Key=\"TileInfo_RequiredItems\">Itens necessários:</system:String>\r\n\r\n\t<!--{StaticResource WaitPage_}-->\r\n\t<system:String x:Key=\"WaitPage_\">WaitPage_</system:String>\r\n\t<system:String x:Key=\"WaitPage_CreatingGame\">Criando jogo</system:String>\r\n\t<system:String x:Key=\"WaitPage_PleaseWait\">Por favor aguarde</system:String>\r\n\r\n\t<!--{StaticResource WorkshopGui_}-->\r\n\t<system:String x:Key=\"WorkshopGui_\">WorkshopGui_</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAcceptGeneratedJobs\">Aceitar tarefas geradas</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AcceptGeneratedJobs\">Aceita tarefas geradas.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoGenerateCraftJobs\">Irá gerar automaticamente as tarefas para fazer os itens de construção e outras oficinas.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AutoCraftMissingComponents\">Auto gerar componentes em falta</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AllowAutoCraftMissingComponents\">Irá gerar componentes em falta.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_GeneratesCraftingJobsForMissingComponents\">Gera tarefas para fazer os componentes em falta nas oficinas.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_AvailableProducts\">Produtos disponíveis</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ProductionLine\">Linha de produção</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcessAnimals\">Abater animais excedentes</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherExcess\">Irá abater os animais que excederem.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherTameNotOnPasture\">Abater qualquer animal domesticado que não esteja num pasto.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherCorpse\">Abater corpos</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAllowCorpse\">Abater carniças.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherOnlyStockpileCorpse\">Carniças devem estar em estoques para serem consideradas.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectToStockpile\">Conectar ao estoque</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectStockpile\">Conecta estoque.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Connect3x3Stockpile\">Conecta a um estoque de tamanho máximo de 3x3.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ConnectAdjacentStockpile\">O estoque precisa estar adjacente ao bloco de entrada.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_ButcherAnimals\">Abater animais</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_SuspendWorkshop\">Suspender</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopSuspendWork\">Suspende a oficina.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_WorkshopStopWork\">A oficina parará de trabalhar.</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Trade\">Comércio</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_Max\">max</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderInventory\">Inventário do Comerciante:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TraderValue\">Valor do Comerciante:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerInventory\">Inventário do Jogador:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_PlayerValue\">Valor do jogador:</system:String>\r\n\t<system:String x:Key=\"WorkshopGui_TradeAction\">Trocar</system:String>\r\n\t\r\n\t\r\n\t<system:String x:Key=\"TestItemName_RawWood\">-madeira pura-</system:String>\r\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/styles/colors.xaml",
    "content": "<ResourceDictionary\r\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \r\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n    xmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n    xmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n    xmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\">\r\n\t\r\n\t<Color x:Key=\"TransparentWhiteColor5\">#0CFFFFFF</Color>\r\n    <Color x:Key=\"TransparentWhiteColor30\">#7FFFFFFF</Color>\r\n    <Color x:Key=\"TransparentWhiteColor75\">#BFFFFFFF</Color>\r\n    <Color x:Key=\"TransparentWhiteColor95\">#F2FFFFFF</Color>\r\n    <Color x:Key=\"TransparentOrangeColor4\">#0A00E1FF</Color>\r\n    <Color x:Key=\"TransparentOrangeColor15\">#2600E6FF</Color>\r\n    <Color x:Key=\"TransparentOrangeColor70\">#B200E6FF</Color>\r\n    <Color x:Key=\"GlowOrangeColor0\">#0000F7FF</Color>\r\n    <Color x:Key=\"GlowOrangeColor30\">#4C00F7FF</Color>\r\n    <Color x:Key=\"SolidOrangeColor\">#FF00BBFF</Color>\r\n    <Color x:Key=\"BadgeDarkColor90\">#CC132A39</Color>\r\n    <Color x:Key=\"BadgeDarkColor80\">#804D6B80</Color>\r\n    <Color x:Key=\"ForegroundColor\">#FFFFFFFF</Color>\r\n    <Color x:Key=\"PanelBackgroundColorBlack\">#FF000000</Color>\r\n\t<Color x:Key=\"PanelBackgroundColorGrey\">#FF404040</Color>\r\n\t\r\n\t<Color x:Key=\"ButtonNormalColor\">#FF2B333B</Color>\r\n\t<SolidColorBrush x:Key=\"ButtonNormalBrush\" Color=\"{StaticResource ButtonNormalColor}\"/>\r\n\r\n    <SolidColorBrush x:Key=\"NormalFgBrush\" Color=\"{StaticResource ForegroundColor}\"/>\r\n    <SolidColorBrush x:Key=\"NormalBgBrush\" Color=\"{StaticResource ButtonNormalColor}\"/>\r\n\r\n    <Color x:Key=\"TileInfoTabSelectedColor\">#FF414E58</Color>\r\n\t<SolidColorBrush x:Key=\"TileInfoTabSelectedBrush\" Color=\"{StaticResource TileInfoTabSelectedColor}\"/>\r\n\t\r\n\t\r\n\t\r\n    <SolidColorBrush x:Key=\"TransparentWhiteBrush50\" Color=\"{StaticResource TransparentWhiteColor30}\"/>\r\n    <SolidColorBrush x:Key=\"TransparentWhiteBrush75\" Color=\"{StaticResource TransparentWhiteColor75}\"/>\r\n    <SolidColorBrush x:Key=\"TransparentWhiteBrush95\" Color=\"{StaticResource TransparentWhiteColor95}\"/>\r\n    <SolidColorBrush x:Key=\"NoesisLogoBlue\" Color=\"#FF2AA6E2\"/>\r\n\t<SolidColorBrush x:Key=\"PanelBackground\" Color=\"{StaticResource PanelBackgroundColorBlack}\"/>\r\n\t<SolidColorBrush x:Key=\"PanelBackgroundGrey\" Color=\"{StaticResource PanelBackgroundColorGrey}\"/>\r\n    <LinearGradientBrush x:Key=\"HorizontalLineBg\" EndPoint=\"1,0\" StartPoint=\"0,0\">\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor5}\" Offset=\"0\"/>\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor30}\" Offset=\"0.01\"/>\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor30}\" Offset=\"0.99\"/>\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor5}\" Offset=\"1\"/>\r\n    </LinearGradientBrush>\r\n    <LinearGradientBrush x:Key=\"DiagonalLinesBg\" EndPoint=\"6,0\" MappingMode=\"Absolute\" SpreadMethod=\"Repeat\">\r\n        <LinearGradientBrush.RelativeTransform>\r\n            <TransformGroup>\r\n                <ScaleTransform CenterY=\"0.5\" CenterX=\"0.5\"/>\r\n                <SkewTransform CenterY=\"0.5\" CenterX=\"0.5\"/>\r\n                <RotateTransform Angle=\"0.3\" CenterY=\"0.5\" CenterX=\"0.5\"/>\r\n                <TranslateTransform/>\r\n            </TransformGroup>\r\n        </LinearGradientBrush.RelativeTransform>\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor30}\" Offset=\"0\"/>\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor30}\" Offset=\"0.5\"/>\r\n        <GradientStop Color=\"{StaticResource TransparentWhiteColor5}\" Offset=\"0.51\"/>\r\n    </LinearGradientBrush>\r\n\t\r\n\t<!-- colors for population overview  -->\r\n\t<Color x:Key=\"SkillGroupStoneColor\">#FFA0A0A0</Color>\r\n\t<Color x:Key=\"SkillGroupWoodColor\">#FFB07256</Color> \r\n\t<Color x:Key=\"SkillGroupMetalColor\">#FF787878</Color>\r\n\t<Color x:Key=\"SkillGroupGemColor\">#FF709BAF</Color>\r\n\t<Color x:Key=\"SkillGroupClothColor\">#FF87AF96</Color>\r\n\t<Color x:Key=\"SkillGroupMiscCraftColor\">#FFA569AF</Color>\r\n\t<Color x:Key=\"SkillGroupEngineerColor\">#FFAF2C7B</Color>\r\n\t<Color x:Key=\"SkillGroupRancherColor\">#FF86AF69</Color>\r\n\t<Color x:Key=\"SkillGroupAgricultureColor\">#FFFF6A00</Color>\r\n\t<Color x:Key=\"SkillGroupDoctorColor\">#FFFF6A</Color>\r\n\t<Color x:Key=\"SkillGroupMiscColor\">#FFA0A0A0</Color>\r\n\t<Color x:Key=\"SkillGroupMagicColor\">#FFAFAFC8</Color>\r\n\t<Color x:Key=\"SkillGroupCombatColor\">#FF8C8C8C</Color>\r\n\t<Color x:Key=\"SkillGroupDefenseColor\">#FFAD8E70</Color>\r\n\t\r\n\t<SolidColorBrush x:Key=\"SkillGroupStoneBrush\" \t\tColor=\"{StaticResource SkillGroupStoneColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupWoodBrush\" \t\tColor=\"{StaticResource SkillGroupWoodColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupMetalBrush\" \t\tColor=\"{StaticResource SkillGroupMetalColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupGemBrush\" \t\tColor=\"{StaticResource SkillGroupGemColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupClothBrush\" \t\tColor=\"{StaticResource SkillGroupClothColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupMiscCraftBrush\" \tColor=\"{StaticResource SkillGroupMiscCraftColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupEngineerBrush\" \tColor=\"{StaticResource SkillGroupEngineerColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupRancherBrush\" \tColor=\"{StaticResource SkillGroupRancherColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupAgricultureBrush\" Color=\"{StaticResource SkillGroupAgricultureColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupDoctorBrush\" \t\tColor=\"{StaticResource SkillGroupDoctorColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupMiscBrush\" \t\tColor=\"{StaticResource SkillGroupMiscColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupMagicBrush\" \t\tColor=\"{StaticResource SkillGroupMagicColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupCombatBrush\" \t\tColor=\"{StaticResource SkillGroupCombatColor}\"/>\r\n\t<SolidColorBrush x:Key=\"SkillGroupDefenseBrush\" \tColor=\"{StaticResource SkillGroupDefenseColor}\"/>\r\n\t\r\n\t<!-- colors for schedules  -->\r\n\t<Color x:Key=\"ActivityNoneColor\">#FFA0A0A0</Color>\r\n\t<Color x:Key=\"ActivityEatColor\">#FFB07256</Color> \r\n\t<Color x:Key=\"ActivitySleepColor\">#FFB8B838</Color>\r\n\t<Color x:Key=\"ActivityTrainColor\">#FF709BAF</Color>\r\n\t\r\n\t<SolidColorBrush x:Key=\"ActivityNoneBrush\" \t\tColor=\"{StaticResource ActivityNoneColor}\"/>\r\n\t<SolidColorBrush x:Key=\"ActivityEatBrush\" \t\tColor=\"{StaticResource ActivityEatColor}\"/>\r\n\t<SolidColorBrush x:Key=\"ActivitySleepBrush\" \t\tColor=\"{StaticResource ActivitySleepColor}\"/>\r\n\t<SolidColorBrush x:Key=\"ActivityTrainBrush\" \t\tColor=\"{StaticResource ActivityTrainColor}\"/>\r\n\t\r\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/styles/mainmenu/pageswap.xaml",
    "content": "<ResourceDictionary\r\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" \r\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n    xmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n    xmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n    xmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\">\r\n\t\r\n\t\r\n\t<Storyboard x:Key=\"FadeInNewGame\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"NewGamePage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"NewGamePage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"True\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\r\n\t<Storyboard x:Key=\"FadeOutNewGame\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"NewGamePage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0:0:0.1\" Value=\"{x:Static Visibility.Collapsed}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"NewGamePage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"False\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t<Storyboard x:Key=\"FadeInLoadGame\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"LoadGamePage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"LoadGamePage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"True\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\r\n\t<Storyboard x:Key=\"FadeOutLoadGame\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"LoadGamePage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0:0:0.1\" Value=\"{x:Static Visibility.Collapsed}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"LoadGamePage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"False\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t<Storyboard x:Key=\"FadeInSettings\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"SettingsPage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"SettingsPage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"True\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t<Storyboard x:Key=\"FadeInWait\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"WaitPage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"WaitPage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"True\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\r\n\t<Storyboard x:Key=\"FadeOutSettings\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"SettingsPage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0:0:0.1\" Value=\"{x:Static Visibility.Collapsed}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"SettingsPage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"False\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t<Storyboard x:Key=\"FadeOutWait\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"WaitPage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0:0:0.1\" Value=\"{x:Static Visibility.Collapsed}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"WaitPage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"False\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t\r\n\t<Storyboard x:Key=\"FadeInMain\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"MainPage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"MainPage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"True\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\r\n\t<Storyboard x:Key=\"FadeOutMain\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"MainPage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0:0:0.1\" Value=\"{x:Static Visibility.Collapsed}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"MainPage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"False\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t<Storyboard x:Key=\"FadeInIngame\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"IngamePage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{x:Static Visibility.Visible}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"IngamePage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"True\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\r\n\t<Storyboard x:Key=\"FadeOutIngame\">\r\n\t\t<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.Visibility)\" Storyboard.TargetName=\"IngamePage\">\r\n\t\t\t<DiscreteObjectKeyFrame KeyTime=\"0:0:0.1\" Value=\"{x:Static Visibility.Collapsed}\"/>\r\n\t\t</ObjectAnimationUsingKeyFrames>\r\n\t\t<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty=\"(UIElement.IsEnabled)\" Storyboard.TargetName=\"IngamePage\">\r\n\t\t\t<DiscreteBooleanKeyFrame KeyTime=\"0\" Value=\"False\"/>\r\n\t\t</BooleanAnimationUsingKeyFrames>\r\n\t</Storyboard>\r\n\t\r\n\t\r\n</ResourceDictionary>"
  },
  {
    "path": "content/xaml/styles/mainmenu/styles.xaml",
    "content": "﻿<ResourceDictionary\r\n\txmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\r\n\txmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\r\n\txmlns:i=\"http://schemas.microsoft.com/expression/2010/interactivity\" xmlns:ei=\"http://schemas.microsoft.com/expression/2010/interactions\"\r\n\txmlns:local=\"clr-namespace:IngnomiaGUI\"\r\n\txmlns:noesis=\"clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions\">\r\n\r\n\r\n\t<ResourceDictionary.MergedDictionaries>\r\n\t\t<!--NoesisTheme is only for providing remotely similar experience to ingame when using Blend or alike-->\r\n\t\t<ResourceDictionary Source=\"../../Theme/NoesisTheme.DarkBlue.xaml\" />\r\n\t\t<ResourceDictionary Source=\"../colors.xaml\" />\r\n\t</ResourceDictionary.MergedDictionaries>\r\n\t\r\n\t<local:ColorToBrushConverter x:Key=\"ColorToBrushConverter\"/>\r\n\t<local:ColorToBrushConverterDark x:Key=\"ColorToBrushConverterDark\"/>\r\n\r\n\t<Style TargetType=\"Button\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"Control.Foreground\" Value=\"{StaticResource NormalFgBrush}\"/>\r\n\t\t<Setter Property=\"Control.Background\" Value=\"{StaticResource NormalBgBrush}\"/>\r\n\t</Style>\r\n\r\n\t<Style TargetType=\"ToggleButton\" BasedOn=\"{StaticResource {x:Type ToggleButton}}\">\r\n\t\t<Setter Property=\"Control.Foreground\" Value=\"{StaticResource NormalFgBrush}\"/>\r\n\t\t<Setter Property=\"Control.Background\" Value=\"{StaticResource NormalBgBrush}\"/>\r\n\t</Style>\r\n\r\n\t<Style TargetType=\"Border\">\r\n\t\t<Setter Property=\"Control.Foreground\" Value=\"{StaticResource NormalFgBrush}\"/>\r\n\t\t<Setter Property=\"Control.Background\" Value=\"{StaticResource NormalBgBrush}\"/>\r\n\t</Style>\r\n\r\n\t<Style TargetType=\"TextBlock\" >\r\n\t\t<Setter Property=\"Foreground\" Value=\"{StaticResource NormalFgBrush}\"/>\r\n\t</Style>\r\n\r\n\t<Style x:Key=\"MenuButtonStyle\" TargetType=\"{x:Type Button}\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"FontSize\" Value=\"26\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"300\"/>\r\n\t\t<Setter Property=\"MinHeight\" Value=\"30\"/>\r\n\t\t<Setter Property=\"Margin\" Value=\"5\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Center\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Center\" />\r\n\t</Style>\r\n\r\n\t<Style x:Key=\"ButtonStyle1\" TargetType=\"{x:Type ToggleButton}\" BasedOn=\"{StaticResource {x:Type ToggleButton}}\">\r\n\t\t<Setter Property=\"FontSize\" Value=\"20\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"30\"/>\r\n\t\t<Setter Property=\"MinHeight\" Value=\"30\"/>\r\n\t\t<Setter Property=\"Margin\" Value=\"3\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Center\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Center\" />\r\n\t</Style>\r\n\r\n\t<ControlTemplate x:Key=\"MenuToolTipTemplate\" TargetType=\"{x:Type ContentControl}\">\r\n\t\t<ControlTemplate.Resources>\r\n\t\t\t<Storyboard x:Key=\"OnEnabled\">\r\n\t\t\t\t<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=\"(TextElement.Foreground).(Brush.Opacity)\" Storyboard.TargetName=\"ContentHost\">\r\n\t\t\t\t\t<EasingDoubleKeyFrame KeyTime=\"0:0:0.2\" Value=\"1\"/>\r\n\t\t\t\t</DoubleAnimationUsingKeyFrames>\r\n\t\t\t</Storyboard>\r\n\t\t\t<Storyboard x:Key=\"OnDisabled\">\r\n\t\t\t\t<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty=\"(TextElement.Foreground).(Brush.Opacity)\" Storyboard.TargetName=\"ContentHost\">\r\n\t\t\t\t\t<EasingDoubleKeyFrame KeyTime=\"0:0:0.1\" Value=\"0\"/>\r\n\t\t\t\t</DoubleAnimationUsingKeyFrames>\r\n\t\t\t</Storyboard>\r\n\t\t</ControlTemplate.Resources>\r\n\t\t<ContentPresenter x:Name=\"ContentHost\">\r\n\t\t\t<TextElement.Foreground>\r\n\t\t\t\t<SolidColorBrush Color=\"{StaticResource TransparentWhiteColor95}\" Opacity=\"0\"/>\r\n\t\t\t</TextElement.Foreground>\r\n\t\t</ContentPresenter>\r\n\t\t<ControlTemplate.Triggers>\r\n\t\t\t<Trigger Property=\"IsEnabled\" Value=\"True\">\r\n\t\t\t\t<Trigger.ExitActions>\r\n\t\t\t\t\t<BeginStoryboard Storyboard=\"{StaticResource OnDisabled}\"/>\r\n\t\t\t\t</Trigger.ExitActions>\r\n\t\t\t\t<Trigger.EnterActions>\r\n\t\t\t\t\t<BeginStoryboard Storyboard=\"{StaticResource OnEnabled}\"/>\r\n\t\t\t\t</Trigger.EnterActions>\r\n\t\t\t</Trigger>\r\n\t\t</ControlTemplate.Triggers>\r\n\t</ControlTemplate>\r\n\r\n\r\n\t<Style x:Key=\"HintStyle\" TargetType=\"{x:Type ContentControl}\">\r\n\t\t<Setter Property=\"OverridesDefaultStyle\" Value=\"True\"/>\r\n\t\t<Setter Property=\"FontSize\" Value=\"24\"/>\r\n\t\t<Setter Property=\"Template\" Value=\"{StaticResource MenuToolTipTemplate}\"/>\r\n\t\t<Setter Property=\"Focusable\" Value=\"False\"/>\r\n\t\t<Setter Property=\"FocusVisualStyle\" Value=\"{x:Null}\"/>\r\n\t\t<Setter Property=\"Visibility\" Value=\"Visible\"/>\r\n\t\t<Style.Triggers>\r\n\t\t\t<Trigger Property=\"IsEnabled\" Value=\"False\">\r\n\t\t\t\t<Setter Property=\"Visibility\" Value=\"Hidden\"/>\r\n\t\t\t</Trigger>\r\n\t\t\t<Trigger Property=\"IsEnabled\" Value=\"True\">\r\n\t\t\t\t<Setter Property=\"Visibility\" Value=\"Visible\"/>\r\n\t\t\t</Trigger>\r\n\t\t</Style.Triggers>\r\n\t</Style>\r\n\t<Style x:Key=\"MainMenuTabControlStyle\" TargetType=\"{x:Type TabControl}\" BasedOn=\"{StaticResource {x:Type TabControl}}\">\r\n\t\t<Setter Property=\"Width\" Value=\"600\"/>\r\n\t\t<Setter Property=\"Height\" Value=\"400\"/>\r\n\t</Style>\r\n\r\n\t<DataTemplate x:Key=\"ItemTemplate20\">\r\n\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\"/>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"ItemTemplate16\">\r\n\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"16\" Margin=\"1\"/>\r\n\t</DataTemplate>\r\n\t\r\n\t<DataTemplate x:Key=\"ItemTemplate16B\">\r\n\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"16\" FontWeight=\"Bold\" Margin=\"1\"/>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"ItemTemplate\">\r\n\t\t<TextBlock Text=\"{Binding Name}\" VerticalAlignment=\"Center\"/>\r\n\t</DataTemplate>\r\n\t\r\n\t<DataTemplate x:Key=\"ItemTemplate12\">\r\n\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"12\" Margin=\"1\" />\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"StartItemTemplate\">\r\n\t\t<Grid x:Name=\"StartItemRow\" RenderTransformOrigin=\"0.5,0.5\" Margin=\"2\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"6*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<TextBlock Text=\"{Binding Amount}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"0\"/>\r\n\t\t\t<TextBlock x:Name=\"ItemName\" Text=\"{Binding Name}\" Tag=\"{Binding Tag}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"1\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Material1}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"2\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Material2}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"3\"/>\r\n\t\t\t<Button  x:Name=\"RemoveSI\"  Content=\"Remove\" Command=\"{Binding ElementName=ICStartingItems, Path=DataContext.RemoveItem}\" CommandParameter=\"{Binding ElementName=ItemName, Path=Tag}\" Grid.Column=\"4\" />\r\n\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"StartAnimalTemplate\">\r\n\t\t<Grid x:Name=\"StartAnimalRow\" RenderTransformOrigin=\"0.5,0.5\" Margin=\"2\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"6*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<TextBlock Text=\"{Binding Amount}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"0\"/>\r\n\t\t\t<TextBlock x:Name=\"AnimalName\" Text=\"{Binding Name}\" Tag=\"{Binding Tag}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"1\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Gender}\" HorizontalAlignment=\"Center\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Column=\"2\"/>\r\n\t\t\t<Button  x:Name=\"RemoveSA\"  Content=\"Remove\" Command=\"{Binding ElementName=ICStartingAnimals, Path=DataContext.RemoveAnimal}\" CommandParameter=\"{Binding ElementName=AnimalName, Path=Tag}\" Grid.Column=\"4\" />\r\n\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"ListCheckBoxTemplate\">\r\n\t\t<StackPanel Margin=\"3\">\r\n\t\t\t<CheckBox Content=\"{Binding Name}\" IsChecked=\"{Binding IsChecked}\"/>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"AnimalCheckBoxTemplate\">\r\n\t\t<StackPanel Margin=\"3\" Orientation=\"Horizontal\">\r\n\t\t\t<CheckBox Content=\"{Binding Name}\" IsChecked=\"{Binding IsChecked}\" MinWidth=\"250\"/>\r\n\t\t\t<TextBox  MinWidth=\"50\" MaxLength=\"3\" Text=\"{Binding Amount, Mode=TwoWay}\"/>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"SavedKingdomTemplate\">\r\n\t\t<Grid RenderTransformOrigin=\"0.5,0.5\" Margin=\"2\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t<RowDefinition Height=\"1*\"/>\r\n\t\t\t\t<RowDefinition Height=\"1*\"/>\r\n\t\t\t</Grid.RowDefinitions>\r\n\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Row=\"0\" Grid.ColumnSpan=\"2\" Grid.Column=\"0\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Dir}\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Row=\"0\" Grid.ColumnSpan=\"2\" Grid.Column=\"0\"/>\r\n\t\t\t<!--<Button  x:Name=\"RemoveSI\"  Content=\"Remove\" Command=\"{Binding ElementName=ICStartingItems, Path=DataContext.RemoveItem}\" CommandParameter=\"{Binding ElementName=ItemName, Path=Tag}\" Grid.Column=\"4\" /> -->\r\n\t\t\t<TextBlock Text=\"{Binding Version}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Row=\"1\" Grid.Column=\"0\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Date}\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" FontSize=\"16\" Grid.Row=\"1\" Grid.Column=\"1\"/>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\t<Style TargetType=\"Button\" x:Key=\"SquareButton\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"Margin\" Value=\"3\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"3\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"FontSize\" Value=\"16\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"{Binding ActualHeight, RelativeSource={RelativeSource Self}}\"/>\r\n\t\t<Setter Property=\"MaxWidth\" Value=\"{Binding ActualHeight, RelativeSource={RelativeSource Self}}\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Top\"/>\r\n\t</Style>\r\n\t\r\n\t<Style TargetType=\"Button\" x:Key=\"CommandButton\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"Margin\" Value=\"3\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"3\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"FontSize\" Value=\"12\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"100\"/>\r\n\t\t<Setter Property=\"MaxWidth\" Value=\"100\"/>\r\n\t\t<Setter Property=\"MinHeight\" Value=\"100\"/>\r\n\t\t<Setter Property=\"MaxHeight\" Value=\"100\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Top\"/>\r\n\t</Style>\r\n\r\n\t<Style TargetType=\"Button\" x:Key=\"BuildButton\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"MinWidth\" Value=\"100\"/>\r\n\t\t<Setter Property=\"Margin\" Value=\"3\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"3\"/>\r\n\t\t<Setter Property=\"FontSize\" Value=\"20\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t</Style>\r\n\r\n\t<Style TargetType=\"Border\" x:Key=\"Panel\" BasedOn=\"{StaticResource {x:Type Border}}\">\r\n\t\t<Setter Property=\"BorderBrush\" Value=\"Black\" />\r\n\t\t<Setter Property=\"BorderThickness\" Value=\"1\"/>\r\n\t\t<Setter Property=\"CornerRadius\" Value=\"0\" />\r\n\t\t<Setter Property=\"Margin\" Value=\"4\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"2\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"Background\" Value=\"{StaticResource PanelBackground}\"/>\r\n\t</Style>\r\n\t\r\n\t<Style TargetType=\"Border\" x:Key=\"PanelTileInfo\" BasedOn=\"{StaticResource {x:Type Border}}\">\r\n\t\t<Setter Property=\"BorderBrush\" Value=\"Black\" />\r\n\t\t<Setter Property=\"BorderThickness\" Value=\"1\"/>\r\n\t\t<Setter Property=\"CornerRadius\" Value=\"5\" />\r\n\t\t<Setter Property=\"Margin\" Value=\"2\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"2\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"Background\" Value=\"{StaticResource PanelBackgroundGrey}\"/>\r\n\t</Style>\r\n\r\n\t<Style TargetType=\"Border\" x:Key=\"PanelCreatureInfo\" BasedOn=\"{StaticResource {x:Type Border}}\">\r\n\t\t<Setter Property=\"BorderBrush\" Value=\"Black\" />\r\n\t\t<Setter Property=\"BorderThickness\" Value=\"1\"/>\r\n\t\t<Setter Property=\"CornerRadius\" Value=\"0\" />\r\n\t\t<Setter Property=\"Margin\" Value=\"4\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"2\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"Background\" Value=\"{StaticResource PanelBackgroundGrey}\"/>\r\n\t</Style>\r\n\r\n\r\n\t<Style TargetType=\"Border\" x:Key=\"JobPanel\" BasedOn=\"{StaticResource {x:Type Border}}\">\r\n\t\t<Setter Property=\"BorderBrush\" Value=\"Black\" />\r\n\t\t<Setter Property=\"BorderThickness\" Value=\"1\"/>\r\n\t\t<Setter Property=\"CornerRadius\" Value=\"0\" />\r\n\t\t<Setter Property=\"Margin\" Value=\"4\"/>\r\n\t\t<Setter Property=\"Padding\" Value=\"2\"/>\r\n\t\t<Setter Property=\"VerticalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"HorizontalAlignment\" Value=\"Stretch\" />\r\n\t\t<Setter Property=\"Background\" Value=\"{StaticResource ButtonNormalBrush}\"/>\r\n\t</Style>\r\n\r\n\t<DataTemplate x:Key=\"CommandButtonTemplate\">\r\n\t\t<Button Content=\"{Binding Name}\" Style=\"{StaticResource BuildButton}\"\r\n\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CmdButtonCommand }\"\r\n\t\t\tCommandParameter=\"{Binding ID}\"/>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"BuildButtonsItemTemplate\">\r\n\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"16\"\r\n\t\t\tMinHeight=\"100\"\r\n\t\t\tMargin=\"8\"\r\n\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.CmdCategory }\"\r\n\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Image Source=\"{Binding Image}\" Stretch=\"None\" />\r\n\t\t\t\t<TextBlock Text=\"{Binding Name}\"/>\r\n\t\t\t</StackPanel>\r\n\r\n\t\t</Button>\r\n\t</DataTemplate>\r\n<!--\t\r\n\t<DataTemplate x:Key=\"InvCategoryButtonTemplate\">\r\n\t\t<Button \r\n\t\t\tFontSize=\"16\"\r\n\t\t\tWidth=\"100\"\r\n\t\t\tHeight=\"50\"\r\n\t\t\tMargin=\"2\"\r\n\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:InventoryGui}}, Path=DataContext.CmdCategory }\"\r\n\t\t\tCommandParameter=\"{Binding ID}\"\r\n\t\t\tContent=\"{Binding Name}\">\r\n\t\t</Button>\r\n\t</DataTemplate>\r\n\t\r\n\t<DataTemplate x:Key=\"InvGroupButtonTemplate\">\r\n\t\t<Button \r\n\t\t\tFontSize=\"16\"\r\n\t\t\tHeight=\"50\"\r\n\t\t\tWidth=\"120\"\r\n\t\t\tMargin=\"8\"\r\n\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:InventoryGui}}, Path=DataContext.CmdGroup }\"\r\n\t\t\tCommandParameter=\"{Binding ID}\"\r\n\t\t\tContent=\"{Binding Name}\">\r\n\t\t</Button>\r\n\t</DataTemplate>\r\n\t\r\n\t<DataTemplate x:Key=\"InvItemTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<TextBlock Text=\"{Binding Item}\"     FontSize=\"16\" Margin=\"2\" Width=\"200\" TextAlignment=\"Center\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Material}\" FontSize=\"16\" Margin=\"2\" Width=\"200\" TextAlignment=\"Center\"/>\r\n\t\t\t<TextBlock Text=\"{Binding InStock}\"  FontSize=\"16\" Margin=\"2\" Width=\"150\" TextAlignment=\"Center\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Total}\"    FontSize=\"16\" Margin=\"2\" Width=\"150\" TextAlignment=\"Center\"/>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n-->\r\n\t<Style x:Key=\"TabButton\" TargetType=\"{x:Type ToggleButton}\" BasedOn=\"{StaticResource {x:Type ToggleButton}}\">\r\n\t\t<Setter Property=\"OverridesDefaultStyle\" Value=\"False\"/>\r\n\t\t<Setter Property=\"Template\">\r\n\t\t\t<Setter.Value>\r\n\t\t\t\t<ControlTemplate TargetType=\"ToggleButton\">\r\n\t\t\t\t\t<Border BorderBrush=\"{TemplateBinding BorderBrush}\"\r\n\t\t\t\t\t\t\tBackground=\"{TemplateBinding Background}\">\r\n\t\t\t\t\t\t<ContentPresenter HorizontalAlignment=\"Center\"\r\n\t\t\t\t\t\t\t\t\t\t  VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t</Border>\r\n\t\t\t\t</ControlTemplate>\r\n\t\t\t</Setter.Value>\r\n\t\t</Setter>\r\n\t\t<Style.Triggers>\r\n\t\t\t<Trigger Property=\"IsChecked\" Value=\"True\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{StaticResource TileInfoTabSelectedBrush}\" />\r\n\t\t\t</Trigger>\r\n\t\t</Style.Triggers>\r\n\t</Style>\r\n\r\n\t<Style x:Key=\"VirtualList\" TargetType=\"{x:Type ItemsControl}\" BasedOn=\"{StaticResource {x:Type ItemsControl}}\">\r\n\t\t<Setter Property=\"OverridesDefaultStyle\" Value=\"False\"/>\r\n\t\t<Setter Property=\"Template\">\r\n\t\t\t<Setter.Value>\r\n\t\t\t\t<ControlTemplate>\r\n\t\t\t\t\t<Border\r\n\t\t\t\t\t\tBorderThickness=\"{TemplateBinding Border.BorderThickness}\"\r\n\t\t\t\t\t\tPadding=\"{TemplateBinding Control.Padding}\"\r\n\t\t\t\t\t\tBorderBrush=\"{TemplateBinding Border.BorderBrush}\"\r\n\t\t\t\t\t\tBackground=\"{TemplateBinding Panel.Background}\">\r\n\t\t\t\t\t\t<ScrollViewer x:Name=\"PART_Scroll\"\r\n\t\t\t\t\t\t\tPadding=\"{TemplateBinding Control.Padding}\"\r\n\t\t\t\t\t\t\tFocusable=\"False\">\r\n\t\t\t\t\t\t\t<ItemsPresenter />\r\n\t\t\t\t\t\t</ScrollViewer>\r\n\t\t\t\t\t</Border>\r\n\t\t\t\t</ControlTemplate>\r\n\t\t\t</Setter.Value>\r\n\t\t</Setter>\r\n\t\t<Setter Property=\"ItemsPanel\">\r\n\t\t\t<Setter.Value>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<VirtualizingStackPanel ScrollViewer.CanContentScroll=\"True\" />\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</Setter.Value>\r\n\t\t</Setter>\r\n\t\t<Setter Property=\"ScrollViewer.CanContentScroll\" Value=\"True\"/>\r\n\t\t<Setter Property=\"VirtualizingPanel.IsVirtualizing\" Value=\"True\"/>\r\n\t\t<Setter Property=\"VirtualizingPanel.VirtualizationMode\" Value=\"Recycling\"/>\r\n\t\t<Setter Property=\"VirtualizingPanel.ScrollUnit\" Value=\"Pixel\"/>\r\n\t</Style>\r\n\r\n\t<DataTemplate x:Key=\"TITabButtonsTemplate\">\r\n\t\t<ToggleButton x:Name=\"TITBT_Button\" Content=\"{Binding Name}\" FontSize=\"12\"\r\n\t\t\tIsChecked=\"{Binding Checked}\"\r\n\t\t\tMinWidth=\"60\" MinHeight=\"60\"\r\n\t\t\tMaxWidth=\"60\" MaxHeight=\"60\"\r\n\t\t\tMargin=\"2\"\r\n\t\t\tStyle=\"{StaticResource TabButton}\"\r\n\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:TileInfo}}, Path=DataContext.CmdTab }\"\r\n\t\t\tCommandParameter=\"{Binding ID}\"/>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"TITabTerrainTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" />\r\n\t\t\t<Button x:Name=\"TITTT_Button1\" Visibility=\"{Binding Action1Visible}\" Content=\"{Binding Action1Text}\" Margin=\"2\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:TileInfo}}, Path=DataContext.CmdTerrain }\" CommandParameter=\"{Binding Action1Text}\"/>\r\n\t\t\t<Button x:Name=\"TITTT_Button2\" Visibility=\"{Binding Action2Visible}\" Content=\"{Binding Action2Text}\" Margin=\"2\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:TileInfo}}, Path=DataContext.CmdTerrain }\"  CommandParameter=\"{Binding Action2Text}\" />\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\t\r\n\t<DataTemplate x:Key=\"AvailableMaterialTemplate\">\r\n\t\t<!--TODO Isn't working nicely with the currently selected item of a ComboBox yet-->\r\n\t\t<Grid>\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" Grid.Column=\"0\" HorizontalAlignment=\"Left\" />\r\n\t\t\t<TextBlock Grid.Column=\"1\" HorizontalAlignment=\"Right\" Margin=\"8,0,0,0\">\r\n\t\t\t\t(<Run Text=\"{Binding Amount}\"/>)\r\n\t\t\t</TextBlock>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"TITabCreaturesTemplate\">\r\n\t\t<Grid>\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" Grid.Column=\"0\" />\r\n\t\t\t<Button Style=\"{StaticResource SquareButton}\" FontSize=\"16\" Content=\"Inspect\" Grid.Column=\"1\" HorizontalAlignment=\"Right\"\r\n\t\t\t\tMinWidth=\"100\"\r\n\t\t\t\tMaxHeight= \"28\"\r\n\t\t\t\tMargin=\"2\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.OpenCreatureDetailsCmd }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t</Button>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\t\r\n\t<DataTemplate x:Key=\"TITabAutomatonTemplate\">\r\n\t\t<Grid>\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" Grid.Column=\"0\" />\r\n\t\t\t\t<CheckBox Content=\"Refuel\" IsChecked=\"{Binding Refuel}\" HorizontalAlignment=\"Left\" Width=\"150\" Margin=\"2\" FontSize=\"16\"/>\r\n\t\t\t\t<ComboBox Grid.Column=\"1\" VerticalAlignment=\"Center\" Margin=\"2\" HorizontalAlignment=\"Stretch\"\r\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Cores}\"\r\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedCore, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate16}\" />\r\n\t\t\t</StackPanel>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\r\n\r\n\t<DataTemplate x:Key=\"RequiredItemTemplate\">\r\n\t\t<Grid Margin=\"0,0,0,4\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"*\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<TextBlock Text=\"{Binding Amount}\" HorizontalAlignment=\"Right\" VerticalAlignment=\"Center\" FontSize=\"12\"  Grid.Column=\"0\"/>\r\n\r\n\t\t\t<ComboBox x:Name=\"MaterialSelector\" Grid.Column=\"1\" VerticalAlignment=\"Center\" Margin=\"8,0,0,0\" HorizontalAlignment=\"Stretch\"\r\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Materials}\"\r\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding SelectedMaterial, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource AvailableMaterialTemplate}\" />\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\t<DataTemplate x:Key=\"BuildItemTemplate\">\r\n\t\t<Grid Margin=\"8\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"*\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<Button Grid.Column=\"0\" Command=\"{Binding Build}\" Style=\"{StaticResource SquareButton}\" MinHeight=\"128\" >\r\n\t\t\t\t<StackPanel>\r\n\t\t\t\t\t<Image Source=\"{Binding Image}\" Stretch=\"None\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Button>\r\n\r\n\t\t\t<StackPanel Grid.Column=\"1\"  Margin=\"8,0\" KeyboardNavigation.TabNavigation=\"Local\" Width=\"250\">\r\n\t\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" FontWeight=\"Bold\" FontSize=\"16\" Grid.Row=\"0\" Grid.Column=\"0\" Margin=\"0,0,0,4\"/>\r\n\t\t\t\t<ItemsControl  ItemsSource=\"{Binding RequiredItems}\" ItemTemplate=\"{StaticResource RequiredItemTemplate}\">\r\n\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t</ItemsControl>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\" HorizontalAlignment=\"Right\">\r\n\t\t\t\t\t<Button Content=\"Fill Hole\" HorizontalAlignment=\"Right\" Margin=\"2\" Padding=\"2\" Visibility=\"{Binding ShowFillHoleButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding Build}\" CommandParameter=\"FillHole\"/>\r\n\t\t\t\t\t<Button Content=\"Replace\" HorizontalAlignment=\"Right\" Margin=\"2\" Padding=\"2\" Visibility=\"{Binding ShowReplaceButton}\"\r\n\t\t\t\t\t\tCommand=\"{Binding Build}\" CommandParameter=\"Replace\"/>\r\n\t\t\t\t\t<Button Content=\"Build\" HorizontalAlignment=\"Right\" Margin=\"2\" Padding=\"2\" Command=\"{Binding Build}\" CommandParameter=\"Build\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</StackPanel>\r\n\t\t</Grid>\r\n\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FilterMaterialTemplate\">\r\n\t\t<CheckBox Content=\"{Binding Name}\" IsChecked=\"{Binding Checked}\" Margin=\"4\" FontSize=\"16\"/>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FilterItemTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\" IsExpanded=\"{Binding Expanded, Mode=OneWay}\">\r\n\t\t\t<Expander.Header>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<CheckBox IsChecked=\"{Binding Checked}\" IsThreeState=\"True\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"16\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Expander.Header>\r\n\t\t\t<ItemsControl x:Name=\"ICMaterials\" ItemsSource=\"{Binding Children}\" ItemTemplate=\"{StaticResource FilterMaterialTemplate}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FilterGroupTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\"  IsExpanded=\"{Binding Expanded, Mode=OneWay}\">\r\n\t\t\t<Expander.Header>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<CheckBox IsChecked=\"{Binding Checked}\" IsThreeState=\"True\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"16\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Expander.Header>\r\n\t\t\t<ItemsControl x:Name=\"ICItems\" ItemsSource=\"{Binding Children}\" ItemTemplate=\"{StaticResource FilterItemTemplate}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FilterCategoryTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\" IsExpanded=\"{Binding Expanded, Mode=OneWay}\">\r\n\t\t\t<Expander.Header>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<CheckBox  x:Name=\"ICCB\" IsChecked=\"{Binding Checked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" IsThreeState=\"True\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"16\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Expander.Header>\r\n\t\t\t<ItemsControl x:Name=\"ICGroups\" ItemsSource=\"{Binding Children}\" ItemTemplate=\"{StaticResource FilterGroupTemplate}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FilterUnrollStop\">\r\n\t\t<TextBlock Text=\"{Binding Name, StringFormat='Any \\{0\\}'}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" />\r\n\t</DataTemplate>\r\n\t<DataTemplate x:Key=\"FilterUnrollRecurse\">\r\n\t\t<ItemsControl ItemsSource=\"{Binding Children, UpdateSourceTrigger=PropertyChanged}\" ItemTemplate=\"{DynamicResource FilterUnrollTemplate}\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FilterUnrollTemplate\">\r\n\t\t<ContentControl Content=\"{Binding}\">\r\n\t\t\t<ContentControl.Style>\r\n\t\t\t\t<Style TargetType=\"ContentControl\">\r\n\t\t\t\t\t<Style.Triggers>\r\n\t\t\t\t\t\t<DataTrigger Binding=\"{Binding Checked}\" Value=\"True\">\r\n\t\t\t\t\t\t\t<Setter Property=\"ContentTemplate\" Value=\"{DynamicResource FilterUnrollStop}\"></Setter>\r\n\t\t\t\t\t\t</DataTrigger>\r\n\t\t\t\t\t\t<DataTrigger Binding=\"{Binding Checked}\" Value=\"{x:Null}\">\r\n\t\t\t\t\t\t\t<Setter Property=\"ContentTemplate\" Value=\"{DynamicResource FilterUnrollRecurse}\"></Setter>\r\n\t\t\t\t\t\t</DataTrigger>\r\n\t\t\t\t\t\t<DataTrigger Binding=\"{Binding Checked}\" Value=\"False\">\r\n\t\t\t\t\t\t\t<Setter Property=\"Visibility\" Value=\"Collapsed\"></Setter>\r\n\t\t\t\t\t\t</DataTrigger>\r\n\t\t\t\t\t</Style.Triggers>\r\n\t\t\t\t</Style>\r\n\t\t\t</ContentControl.Style>\r\n\t\t</ContentControl>\r\n\t</DataTemplate>\r\n\r\n\r\n\r\n\r\n\t<DataTemplate x:Key=\"WSProductTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\" IsExpanded=\"{Binding Expanded, Mode=OneWay}\" Header=\"{Binding Name}\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Grid >\r\n\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t<ComboBox MinWidth=\"100\" Grid.Column=\"0\" Margin=\"3\"  SelectedIndex=\"{Binding Mode}\">\r\n\t\t\t\t\t\t<ComboBoxItem IsSelected=\"True\">Craft number</ComboBoxItem>\r\n\t\t\t\t\t\t<ComboBoxItem>Craft to</ComboBoxItem>\r\n\t\t\t\t\t\t<ComboBoxItem>Repeat</ComboBoxItem>\r\n\t\t\t\t\t</ComboBox>\r\n\t\t\t\t\t<TextBox x:Name=\"CraftNum\" Grid.Column=\"1\" MinWidth=\"50\" MaxLength=\"3\" Text=\"{Binding CraftNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" HorizontalAlignment=\"Right\" Margin=\"3\"/>\r\n\t\t\t\t</Grid>\r\n\t\t\t\t<ItemsControl  ItemsSource=\"{Binding RequiredItems}\" ItemTemplate=\"{StaticResource RequiredItemTemplate}\">\r\n\t\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t\t</ItemsControl>\r\n\t\t\t\t<Button Content=\"Craft\" HorizontalAlignment=\"Right\" Padding=\"2\" Command=\"{Binding Craft}\"/>\r\n\t\t\t</StackPanel>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"WSJobTemplate\">\r\n\t\t<Grid>\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t<Border x:Name=\"WsJobBorder1\" Style=\"{StaticResource JobPanel}\" MinWidth=\"50\" MaxWidth=\"50\" Margin=\"2\" Grid.Column=\"0\" >\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Button x:Name=\"WSJT_Button1\" Content=\"Top\" Margin=\"2\"    Command=\"{Binding ButtonCmd}\" CommandParameter=\"Top\"/>\r\n\t\t\t\t<Button x:Name=\"WSJT_Button2\" Content=\"Up\" Margin=\"2\"     Command=\"{Binding ButtonCmd}\" CommandParameter=\"Up\"/>\r\n\t\t\t\t<Button x:Name=\"WSJT_Button3\" Content=\"Down\" Margin=\"2\"   Command=\"{Binding ButtonCmd}\" CommandParameter=\"Down\"/>\r\n\t\t\t\t<Button x:Name=\"WSJT_Button4\" Content=\"Bottom\" Margin=\"2\" Command=\"{Binding ButtonCmd}\" CommandParameter=\"Bottom\"/>\r\n\t\t\t</StackPanel>\r\n\t\t</Border>\r\n\t\t<Border x:Name=\"WsJobBorder2\" Style=\"{StaticResource JobPanel}\" MinWidth=\"225\" MaxWidth=\"225\" Margin=\"2\" Grid.Column=\"1\" >\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"14\" FontWeight=\"Bold\" Margin=\"2\" />\r\n\t\t\t\t\t<Grid >\r\n\t\t\t\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"3*\"/>\r\n\t\t\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t\t\t<ComboBox MinWidth=\"100\" Grid.Column=\"0\" Margin=\"3\"  SelectedIndex=\"{Binding Mode}\">\r\n\t\t\t\t\t\t<ComboBoxItem IsSelected=\"True\">Craft number</ComboBoxItem>\r\n\t\t\t\t\t\t<ComboBoxItem>Craft to</ComboBoxItem>\r\n\t\t\t\t\t\t<ComboBoxItem>Repeat</ComboBoxItem>\r\n\t\t\t\t\t</ComboBox>\r\n\t\t\t\t\t<TextBox x:Name=\"CraftNum\" Grid.Column=\"1\" MinWidth=\"50\" MaxLength=\"3\" Text=\"{Binding CraftNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" HorizontalAlignment=\"Right\" Margin=\"3\"/>\r\n\t\t\t\t</Grid>\r\n\t\t\t\t<CheckBox  x:Name=\"CBSuspend\" IsChecked=\"{Binding Suspended, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" Content=\"Suspend\"/>\r\n\t\t\t\t<CheckBox  x:Name=\"CBMBWD\" IsChecked=\"{Binding MoveBack, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" Content=\"Move back when done\"/>\r\n\t\t\t\t<Button Content=\"Cancel\" HorizontalAlignment=\"Right\" Padding=\"2\" Margin=\"3\" Command=\"{Binding ButtonCmd}\" CommandParameter=\"Cancel\"/>\r\n\t\t\t</StackPanel>\r\n\t\t</Border>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"PlantEntryTemplate\">\r\n\t\t<Button x:Name=\"PET_Button\" Style=\"{StaticResource SquareButton}\" Height=\"50\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Agriculture}}, Path=DataContext.SelectProduct }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\" Grid.Column=\"0\" Margin=\"3\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Image Source=\"{Binding Image}\" />\r\n\t\t\t</StackPanel>\r\n\t\t\t<Button.ToolTip>\r\n\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Button.ToolTip>\r\n\t\t</Button>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"PlantRowTemplate\">\r\n\t\t<ItemsControl  ItemsSource=\"{Binding Plants}\" ItemTemplate=\"{StaticResource PlantEntryTemplate}\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\"/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\r\n\t<DataTemplate x:Key=\"FoodEntryTemplate\">\r\n\t\t<ToggleButton Style=\"{StaticResource ButtonStyle1}\" IsChecked=\"{Binding Checked}\" >\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Image Source=\"{Binding Image}\" />\r\n\t\t\t</StackPanel>\r\n\t\t\t<ToggleButton.ToolTip>\r\n\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</ToggleButton.ToolTip>\r\n\t\t</ToggleButton>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"FoodRowTemplate\">\r\n\t\t<ItemsControl  ItemsSource=\"{Binding Foods}\" ItemTemplate=\"{StaticResource FoodEntryTemplate}\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\"/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\r\n\t<DataTemplate x:Key=\"AnimalEntryTemplate\">\r\n\t\t<Button x:Name=\"AET_Button\" Style=\"{StaticResource SquareButton}\" Height=\"50\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Agriculture}}, Path=DataContext.SelectProduct }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\" Grid.Column=\"0\" Margin=\"3\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Image Source=\"{Binding Image}\" />\r\n\t\t\t</StackPanel>\r\n\t\t\t<Button.ToolTip>\r\n\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Button.ToolTip>\r\n\t\t</Button>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"AnimalRowTemplate\">\r\n\t\t<ItemsControl  ItemsSource=\"{Binding Animals}\" ItemTemplate=\"{StaticResource AnimalEntryTemplate}\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\"/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"TreeEntryTemplate\">\r\n\t\t<Button x:Name=\"TET_Button\" Style=\"{StaticResource SquareButton}\" Height=\"50\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Agriculture}}, Path=DataContext.SelectProduct }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\" Grid.Column=\"0\" Margin=\"3\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<Image Source=\"{Binding Image}\" />\r\n\t\t\t</StackPanel>\r\n\t\t\t<Button.ToolTip>\r\n\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Button.ToolTip>\r\n\t\t</Button>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"TreeRowTemplate\">\r\n\t\t<ItemsControl  ItemsSource=\"{Binding Trees}\" ItemTemplate=\"{StaticResource TreeEntryTemplate}\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\"/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"PastureAnimalTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<CheckBox Content=\"\" IsChecked=\"{Binding ToButcher}\">\r\n\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Mark this animal\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t\t<TextBlock Text=\"for butchering.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t</CheckBox>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" />\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\r\n\r\n\r\n\t<Style x:Key=\"GnomeSkillButtonStyle\" TargetType=\"{x:Type ToggleButton}\" BasedOn=\"{StaticResource {x:Type ToggleButton}}\">\r\n\t\t<Setter Property=\"OverridesDefaultStyle\" Value=\"False\"/>\r\n\t\t<Setter Property=\"FontSize\" Value=\"12\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MinHeight\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MaxWidth\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MaxHeight\" Value=\"28\"/>\r\n\t\t<Setter Property=\"Margin\" Value=\"2\"/>\r\n\r\n\t\t<Setter Property=\"Template\">\r\n\t\t\t<Setter.Value>\r\n\t\t\t\t<ControlTemplate TargetType=\"ToggleButton\">\r\n\t\t\t\t\t<Border BorderBrush=\"{TemplateBinding BorderBrush}\" Background=\"{TemplateBinding Background}\">\r\n\t\t\t\t\t\t<ContentPresenter HorizontalAlignment=\"Center\"  VerticalAlignment=\"Center\"/>\r\n\t\t\t\t\t</Border>\r\n\t\t\t\t</ControlTemplate>\r\n\t\t\t</Setter.Value>\r\n\t\t</Setter>\r\n\t\t\r\n\t\t<Style.Triggers>\r\n\t\t\t<Trigger Property=\"IsChecked\" Value=\"False\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{Binding Color, Converter={StaticResource ColorToBrushConverterDark}}\" />\r\n\t\t\t</Trigger>\r\n\t\t\t<Trigger Property=\"IsChecked\" Value=\"True\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{Binding Color, Converter={StaticResource ColorToBrushConverter}}\" />\r\n\t\t\t</Trigger>\r\n\t\t</Style.Triggers>\r\n\r\n\t</Style>\r\n\r\n\t<Style x:Key=\"GnomeSkillAllButtonStyle\" TargetType=\"{x:Type Button}\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"OverridesDefaultStyle\" Value=\"False\"/>\r\n\t\t<Setter Property=\"FontSize\" Value=\"12\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MinHeight\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MaxWidth\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MaxHeight\" Value=\"28\"/>\r\n\t\t<Setter Property=\"Margin\" Value=\"2\"/>\r\n\t</Style>\r\n\r\n\r\n\r\n\t<DataTemplate x:Key=\"PopGnomeSkillHeaderTemplate\">\r\n\t\t<StackPanel>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" Background=\"{Binding Color, Converter={StaticResource ColorToBrushConverter}}\" HorizontalAlignment=\"Left\" MinWidth=\"180\" MaxWidth=\"180\" FontSize=\"20\" Margin=\"2\" >\r\n\t\t\t\t<TextBlock.LayoutTransform>\r\n\t\t\t\t\t<RotateTransform Angle=\"270\" />\r\n\t\t\t\t</TextBlock.LayoutTransform>\r\n\t\t\t\t<i:Interaction.Triggers>\r\n\t\t\t\t\t<i:EventTrigger EventName=\"MouseLeftButtonDown\">\r\n\t\t\t\t\t\t<i:InvokeCommandAction Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdSort }\"\r\n\t\t\t\t\t\t\t\t\t\t\t   CommandParameter=\"{Binding SkillID}\"/>\r\n\t\t\t\t\t</i:EventTrigger>\r\n\t\t\t\t</i:Interaction.Triggers>\r\n\t\t\t</TextBlock>\r\n\t\t\t<Button Style=\"{StaticResource GnomeSkillAllButtonStyle}\" Content=\"A\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdAllGnomes }\"\r\n\t\t\t\tCommandParameter=\"{Binding SkillID}\"/>\r\n\t\t\t\t<i:Interaction.Triggers>\r\n\t\t\t\t\t<i:EventTrigger EventName=\"MouseRightButtonDown\">\r\n\t\t\t\t\t\t<i:InvokeCommandAction Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdRemoveAllGnomes }\"\r\n\t\t\t\t\t\t\t\t\t\t\t   CommandParameter=\"{Binding SkillID}\"/>\r\n\t\t\t\t\t</i:EventTrigger>\r\n\t\t\t\t</i:Interaction.Triggers>\r\n\t\t\t<!--\r\n\t\t\t\t<Button.ToolTip>\r\n\t\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Left click to enable all skills in this column.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t\t<TextBlock Text=\"Right click to disable all skills in this column.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</Button.ToolTip>\r\n\t\t\t\t\r\n\t\t\t\tBackground=\"{Binding SkillID, Converter={StaticResource SkillToColorConverter}}\"\r\n\t\t\t\t\r\n\t\t\t-->\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\r\n\r\n\t<DataTemplate x:Key=\"GnomeSkillButtonTemplate\">\r\n\t\t<ToggleButton x:Name=\"GSBT_Button\" Content=\"{Binding Level}\"\r\n\t\t\tIsChecked=\"{Binding Checked}\"\r\n\t\t\tStyle=\"{StaticResource GnomeSkillButtonStyle}\"\r\n\t\t\t/>\r\n\t\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"PopProfessionTemplate\">\r\n\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" VerticalAlignment=\"Center\" MaxHeight=\"18\" FontSize=\"12\" />\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"PopGnomeNameTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\" Height=\"35\">\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" MinWidth=\"180\" MaxWidth=\"180\" FontSize=\"20\" Margin=\"2\">\r\n\t\t\t\t<i:Interaction.Triggers>\r\n\t\t\t\t\t<i:EventTrigger EventName=\"MouseLeftButtonDown\">\r\n\t\t\t\t\t\t<i:InvokeCommandAction Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:GameGui}}, Path=DataContext.OpenCreatureDetailsCmd }\"\r\n\t\t\t\t\t\t\t\t\t\t\t   CommandParameter=\"{Binding GnomeID}\"/>\r\n\t\t\t\t\t</i:EventTrigger>\r\n\t\t\t\t</i:Interaction.Triggers>\r\n\t\t\t</TextBlock>\r\n\r\n\t\t\t<ComboBox x:Name=\"ProfessionSelector\" Grid.Column=\"1\" VerticalAlignment=\"Center\" Margin=\"8,0,0,0\" MaxHeight=\"28\" HorizontalAlignment=\"Stretch\"  MinWidth=\"180\" MaxWidth=\"180\"\r\n\t\t\t\t\t\t\t\tItemsSource=\"{Binding Professions}\"\r\n\t\t\t\t\t\t\t\tSelectedItem=\"{Binding Profession, Mode=TwoWay}\"\r\n\t\t\t\t\t\t\t\tItemTemplate=\"{StaticResource PopProfessionTemplate}\" />\r\n\t\t\t<Button Style=\"{StaticResource GnomeSkillAllButtonStyle}\" Content=\"A\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdAllSkills }\"\r\n\t\t\t\tCommandParameter=\"{Binding GnomeID}\">\r\n\t\t\t\t<i:Interaction.Triggers>\r\n\t\t\t\t\t<i:EventTrigger EventName=\"MouseRightButtonDown\">\r\n\t\t\t\t\t\t<i:InvokeCommandAction Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdRemoveAllSkills }\"\r\n\t\t\t\t\t\t\t\t\t\t\t   CommandParameter=\"{Binding GnomeID}\"/>\r\n\t\t\t\t\t</i:EventTrigger>\r\n\t\t\t\t</i:Interaction.Triggers>\r\n\t\t\t\t<Button.ToolTip>\r\n\t\t\t\t\t<StackPanel Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Left click to enable all skills in this row.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t\t<TextBlock Text=\"Right click to disable all skills in this row.\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</Button.ToolTip>\r\n\t\t\t</Button>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\r\n\t<DataTemplate x:Key=\"PopGnomeSkillRowTemplate\">\r\n\t\t<ItemsControl  ItemsSource=\"{Binding Skills}\" ItemTemplate=\"{StaticResource GnomeSkillButtonTemplate}\" Height=\"35\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\"/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\t<Style x:Key=\"GnomeScheduleButtonStyle\" TargetType=\"{x:Type Button}\" BasedOn=\"{StaticResource {x:Type Button}}\">\r\n\t\t<Setter Property=\"OverridesDefaultStyle\" Value=\"False\"/>\r\n\t\t<Setter Property=\"FontSize\" Value=\"12\"/>\r\n\t\t<Setter Property=\"MinWidth\" Value=\"32\"/>\r\n\t\t<Setter Property=\"MinHeight\" Value=\"28\"/>\r\n\t\t<Setter Property=\"MaxWidth\" Value=\"32\"/>\r\n\t\t<Setter Property=\"MaxHeight\" Value=\"28\"/>\r\n\t\t<Setter Property=\"Margin\" Value=\"2\"/>\r\n\t\t<Style.Triggers>\r\n\t\t\t<DataTrigger Binding=\"{Binding Activity}\" Value=\"N\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{StaticResource ActivityNoneBrush}\"/>\r\n\t\t\t</DataTrigger>\r\n\t\t\t<DataTrigger Binding=\"{Binding Activity}\" Value=\"E\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{StaticResource ActivityEatBrush}\"/>\r\n\t\t\t</DataTrigger>\r\n\t\t\t<DataTrigger Binding=\"{Binding Activity}\" Value=\"S\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{StaticResource ActivitySleepBrush}\"/>\r\n\t\t\t</DataTrigger>\r\n\t\t\t<DataTrigger Binding=\"{Binding Activity}\" Value=\"T\">\r\n\t\t\t\t<Setter Property=\"Background\" Value=\"{StaticResource ActivityTrainBrush}\"/>\r\n\t\t\t</DataTrigger>\r\n\t\t</Style.Triggers>\r\n\t</Style>\r\n\r\n\t<DataTemplate x:Key=\"GnomeScheduleButtonTemplate\">\r\n\t\t<Button x:Name=\"Sched_Button\"\r\n\t\t\tContent=\"{Binding Activity}\"\r\n\t\t\tStyle=\"{StaticResource GnomeScheduleButtonStyle}\"\r\n\t\t\tCommand=\"{Binding CmdSetHour}\" />\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"PopGnomeSchedRowTemplate\">\r\n\t\t<ItemsControl  ItemsSource=\"{Binding Schedule}\" ItemTemplate=\"{StaticResource GnomeScheduleButtonTemplate}\" Height=\"35\">\r\n\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\"/>\r\n\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t</ItemsControl>\r\n\t</DataTemplate>\r\n\r\n\r\n\t<DataTemplate x:Key=\"PopScheduleNameTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\" Height=\"35\">\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" MinWidth=\"180\" MaxWidth=\"180\" FontSize=\"20\" Margin=\"2\"/>\r\n\r\n\t\t\t<Button Style=\"{StaticResource GnomeSkillAllButtonStyle}\" Content=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.ScheduleActivity }\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdAllHours }\"\r\n\t\t\t\tCommandParameter=\"{Binding GnomeID}\">\r\n\t\t\t\t<!--\r\n\t\t\t\t<i:Interaction.Triggers>\r\n\t\t\t\t\t<i:EventTrigger EventName=\"MouseRightButtonDown\">\r\n\t\t\t\t\t\t<i:InvokeCommandAction Command=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdRemoveAllHours }\"\r\n\t\t\t\t\t\t\t\t\t\t\t   CommandParameter=\"{Binding GnomeID}\"/>\r\n\t\t\t\t\t</i:EventTrigger>\r\n\t\t\t\t</i:Interaction.Triggers>\r\n\t\t\t\t-->\r\n\t\t\t</Button>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"ProfSkillTemplate\">\r\n\t\t<Grid>\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"1*\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" Grid.Column=\"0\" />\r\n\t\t\t<Button Content=\"up\" MinWidth=\"50\" MaxWidth=\"50\" Margin=\"2\" Grid.Column=\"1\" HorizontalAlignment=\"Right\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdSkillUp }\"\r\n\t\t\t\tCommandParameter=\"{Binding SkillID}\"/>\r\n\t\t\t<Button Content=\"down\" MinWidth=\"50\"  MaxWidth=\"50\" Margin=\"2\" Grid.Column=\"2\" HorizontalAlignment=\"Right\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdSkillDown }\"\r\n\t\t\t\tCommandParameter=\"{Binding SkillID}\"/>\r\n\t\t\t<Button Content=\"&gt;\" MinWidth=\"50\" MaxWidth=\"50\" Margin=\"2\"  Grid.Column=\"3\" HorizontalAlignment=\"Right\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdSkillRemove }\"\r\n\t\t\t\tCommandParameter=\"{Binding SkillID}\"/>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"ProfSkillTemplate2\">\r\n\t\t<Grid>\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<Button Content=\"&lt;\" MinWidth=\"50\" MaxWidth=\"50\" Margin=\"2\" Grid.Column=\"0\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PopulationWindow}}, Path=DataContext.CmdSkillAdd }\"\r\n\t\t\t\tCommandParameter=\"{Binding SkillID}\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" Grid.Column=\"1\" />\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\r\n\t<DataTemplate x:Key=\"TradeItemTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<TextBlock Text=\"{Binding Count}\" FontSize=\"20\" Margin=\"0,0,5,0\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"20\"/>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"NeighborKingdomTemplate\">\r\n\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"600\" CornerRadius=\"8\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontWeight=\"Bold\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Distance}\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Wealth}\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Economy}\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Military}\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Attitude}\" FontSize=\"20\"/>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<Button Content=\"Send Ambassador\" Visibility=\"{Binding ShowDiploButton}\" FontSize=\"20\" Margin=\"2\"\r\n\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:NeighborsGui}}, Path=DataContext.CmdDiploMission }\"\r\n\t\t\t\t\t\tCommandParameter=\"{Binding ID}\" BorderBrush=\"Black\" BorderThickness=\"2,2,2,2\" />\r\n\t\t\t\t\t<Button Content=\"Spy\" Command=\"{Binding SpyCmd}\"\tCommandParameter=\"{Binding ID}\" Visibility=\"{Binding ShowSpyButton}\" FontSize=\"20\" Margin=\"2\"\r\n\t\t\t\t\t\tBorderBrush=\"Black\" BorderThickness=\"2,2,2,2\"/>\r\n\t\t\t\t\t<Button Content=\"Sabotage\" Command=\"{Binding SabotageCmd}\"\tCommandParameter=\"{Binding ID}\" Visibility=\"{Binding ShowSabotageButton}\" FontSize=\"20\" Margin=\"2\"\r\n\t\t\t\t\t\tBorderBrush=\"Black\" BorderThickness=\"2,2,2,2\"/>\r\n\t\t\t\t\t<Button Content=\"Raid\" Command=\"{Binding RaidCmd}\"\tCommandParameter=\"{Binding ID}\" Visibility=\"{Binding ShowRaidButton}\" FontSize=\"20\" Margin=\"2\"\r\n\t\t\t\t\t\tBorderBrush=\"Black\" BorderThickness=\"2,2,2,2\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</StackPanel>\r\n\t\t</Border>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"MissionTemplate\">\r\n\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"600\" CornerRadius=\"8\">\r\n\t\t\t<StackPanel>\r\n\t\t\t\t<TextBlock Text=\"{Binding Title}\" FontWeight=\"Bold\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Action}\" FontSize=\"20\"/>\r\n\t\t\t\t<TextBlock Text=\"{Binding Time}\" FontSize=\"20\"/>\r\n\t\t\t\t<!--\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<Button Content=\"Abort\"\r\n\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:NeighborsGui}}, Path=DataContext.CmdAbortMission }\"\r\n\t\t\t\t\t\tCommandParameter=\"{Binding ID}\"  />\r\n\t\t\t\t</StackPanel>\r\n\t\t\t\t-->\r\n\t\t\t</StackPanel>\r\n\t\t</Border>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"SquadPriorityTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<Button Content=\"^\" MaxWidth=\"50\" FontSize=\"20\" HorizontalAlignment=\"Left\" Margin=\"2\"\r\n\t\t\t\tCommand=\"{Binding MoveUpCmd }\"\tCommandParameter=\"{Binding ID}\"/>\r\n\t\t\t<Button Content=\"v\" MaxWidth=\"50\" FontSize=\"20\" HorizontalAlignment=\"Left\" Margin=\"2\"\r\n\t\t\t\tCommand=\"{Binding MoveDownCmd }\"\tCommandParameter=\"{Binding ID}\"/>\r\n\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" MinWidth=\"180\" />\r\n\t\t\t<CheckBox Content=\"\" IsChecked=\"{Binding Flee, Mode=TwoWay}\" Margin=\"2\">\r\n\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t<StackPanel Width=\"100\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Flee (Avoid combat)\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t</CheckBox>\r\n\t\t\t<CheckBox Content=\"\" IsChecked=\"{Binding Defend, Mode=TwoWay}\" Margin=\"2\">\r\n\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t<StackPanel Width=\"100\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Defend (Hold position)\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t</CheckBox>\r\n\t\t\t<CheckBox Content=\"\" IsChecked=\"{Binding Attack, Mode=TwoWay}\" Margin=\"2\">\r\n\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t<StackPanel Width=\"100\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Attack on sight\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t</CheckBox>\r\n\t\t\t<CheckBox Content=\"\" IsChecked=\"{Binding Hunt, Mode=TwoWay}\" Margin=\"2\">\r\n\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t<StackPanel Width=\"100\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t<TextBlock Text=\"Hunt\" FontSize=\"18\" FontWeight=\"Bold\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\" Padding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t</CheckBox>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"SquadGnomeTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" HorizontalAlignment=\"Right\" Visibility=\"{Binding ShowLeftArrow}\" Margin=\"1\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.MoveGnomeLeftCmd }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t\t<Image Source=\"../../buttons/arrow_left.png\" />\r\n\t\t\t</Button>\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" MinWidth=\"100\" MaxWidth=\"100\" FontSize=\"16\" Margin=\"2\" />\r\n\t\t\t<ComboBox Margin=\"1\" HorizontalAlignment=\"Stretch\" MinWidth=\"100\" MaxWidth=\"100\"\r\n\t\t\t\tItemsSource=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.RoleList }\"\r\n\t\t\t\tSelectedItem=\"{Binding Role, Mode=TwoWay}\"\r\n\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate16}\" />\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" HorizontalAlignment=\"Right\" Visibility=\"{Binding ShowX}\" Margin=\"1\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.RemoveGnomeFromSquadCmd }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t\t<Image Source=\"../../buttons/cross.png\" />\r\n\t\t\t</Button>\r\n\t\t\t<Button MinWidth=\"32\" MaxWidth=\"32\" MinHeight=\"32\" MaxHeight=\"32\" HorizontalAlignment=\"Right\" Visibility=\"{Binding ShowRightArrow}\" Margin=\"1\"\r\n\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.MoveGnomeRightCmd }\"\r\n\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t\t<Image Source=\"../../buttons/arrow_right.png\" />\r\n\t\t\t</Button>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"SquadTemplate\">\r\n\t\t<Grid MaxHeight=\"650\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"330\" MaxWidth=\"330\" Grid.Column=\"0\"\r\n\t\t\t\t\tCornerRadius=\"8\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\"/>\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\"/>\r\n\t\t\t\t\t\t<RowDefinition Height=\"13*\"/>\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<Button Content=\"Configure\" MaxHeight=\"50\" FontSize=\"18\" Margin=\"2\" VerticalAlignment=\"Top\" Command=\"{Binding ConfigureSquadCmd }\" Grid.Row=\"0\"/>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" VerticalAlignment=\"Top\"  Grid.Row=\"1\" Margin=\"2\">\r\n\t\t\t\t\t\t<Button MaxWidth=\"50\" MaxHeight=\"50\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Margin=\"2\" Visibility=\"{Binding ShowLeftArrow}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.MoveSquadLeftCmd }\"\r\n\t\t\t\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t\t\t\t\t<Image Source=\"../../buttons/arrow_left.png\" />\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<TextBox x:Name=\"TBSquadName\" Text=\"{Binding Name}\" MinWidth=\"180\" FontSize=\"18\" MinHeight=\"50\" MaxHeight=\"50\" Margin=\"2\"/>\r\n\t\t\t\t\t\t<Button  MaxWidth=\"50\" MaxHeight=\"50\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Margin=\"2\" Visibility=\"{Binding ShowX}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.RemoveSquadCmd }\"\r\n\t\t\t\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t\t\t\t\t<Image Source=\"../../buttons/cross.png\" />\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t<Button MaxWidth=\"50\" MaxHeight=\"50\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Margin=\"2\" Visibility=\"{Binding ShowRightArrow}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.MoveSquadRightCmd }\"\r\n\t\t\t\t\t\t\tCommandParameter=\"{Binding ID}\">\r\n\t\t\t\t\t\t\t<Image Source=\"../../buttons/arrow_right.png\" />\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t<ListBox ItemsSource=\"{Binding Gnomes}\" ItemTemplate=\"{StaticResource SquadGnomeTemplate}\" Grid.Row=\"2\" MinHeight=\"570\" MaxHeight=\"570\"\r\n\t\t\t\t\t\tBorderBrush=\"Black\" BorderThickness=\"2,2,2,2\"/>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"330\" MaxWidth=\"400\" Visibility=\"{Binding ShowConfig}\" Grid.Column=\"1\"\r\n\t\t\t\t\tCornerRadius=\"8\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<ListBox ItemsSource=\"{Binding Priorities}\" ItemTemplate=\"{StaticResource SquadPriorityTemplate}\" MinHeight=\"300\" />\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\r\n\r\n\t<DataTemplate x:Key=\"UniformItemTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<TextBlock Text=\"{Binding Name}\" HorizontalAlignment=\"Left\" FontSize=\"20\" Margin=\"2\" MinWidth=\"150\"/>\r\n\t\t\t<ComboBox Margin=\"8,0,0,0\" HorizontalAlignment=\"Stretch\" MinWidth=\"150\"\r\n\t\t\t\tItemsSource=\"{Binding AvailableTypes}\"\r\n\t\t\t\tSelectedItem=\"{Binding SelectedType, Mode=TwoWay}\"\r\n\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate16}\" />\r\n\t\t\t<ComboBox Margin=\"8,0,0,0\" HorizontalAlignment=\"Stretch\" MinWidth=\"150\"\r\n\t\t\t\tItemsSource=\"{Binding AvailableMaterials}\"\r\n\t\t\t\tSelectedItem=\"{Binding SelectedMaterial, Mode=TwoWay}\"\r\n\t\t\t\tItemTemplate=\"{StaticResource ItemTemplate16}\" />\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\r\n\r\n\t<DataTemplate x:Key=\"MilRoleTemplate\">\r\n\t\t<Grid MaxHeight=\"650\">\r\n\t\t\t<Grid.ColumnDefinitions>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t\t<ColumnDefinition Width=\"Auto\"/>\r\n\t\t\t</Grid.ColumnDefinitions>\r\n\t\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"310\" MaxWidth=\"310\" Grid.Column=\"0\"\r\n\t\t\t\t\tCornerRadius=\"8\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<Grid.RowDefinitions>\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\"/>\r\n\t\t\t\t\t\t<RowDefinition Height=\"1*\"/>\r\n\t\t\t\t\t\t<RowDefinition Height=\"Auto\"/>\r\n\t\t\t\t\t\t<RowDefinition Height=\"12*\"/>\r\n\t\t\t\t\t</Grid.RowDefinitions>\r\n\t\t\t\t\t<Button Content=\"Uniform\" MaxHeight=\"50\" FontSize=\"18\" Margin=\"2\" VerticalAlignment=\"Top\" Command=\"{Binding ConfigureUniformCmd }\" Grid.Row=\"0\"/>\r\n\t\t\t\t\t<StackPanel Orientation=\"Horizontal\" VerticalAlignment=\"Top\"  Grid.Row=\"1\" Margin=\"2\">\r\n\t\t\t\t\t\t<Button Content=\"&lt;-\" MaxWidth=\"50\" MaxHeight=\"50\" FontSize=\"20\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Margin=\"2\" Visibility=\"{Binding ShowLeftArrow}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.MoveRoleLeftCmd }\"\r\n\t\t\t\t\t\t\tCommandParameter=\"{Binding ID}\"/>\r\n\t\t\t\t\t\t<TextBox x:Name=\"TBRoleName\" Text=\"{Binding Name}\" MinWidth=\"180\" FontSize=\"18\" MinHeight=\"50\" MaxHeight=\"50\" Margin=\"2\"/>\r\n\t\t\t\t\t\t<Button Content=\"X\" MaxWidth=\"50\" MaxHeight=\"50\" FontSize=\"20\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Margin=\"2\" Visibility=\"{Binding ShowX}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.RemoveRoleCmd }\"\r\n\t\t\t\t\t\t\tCommandParameter=\"{Binding ID}\"/>\r\n\r\n\t\t\t\t\t\t<Button Content=\"-&gt;\" MaxWidth=\"50\" MaxHeight=\"50\" FontSize=\"20\" Grid.Column=\"2\" HorizontalAlignment=\"Right\" Margin=\"2\" Visibility=\"{Binding ShowRightArrow}\"\r\n\t\t\t\t\t\t\tCommand=\"{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MilitaryGui}}, Path=DataContext.MoveRoleRightCmd }\"\r\n\t\t\t\t\t\t\tCommandParameter=\"{Binding ID}\"/>\r\n\r\n\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t<CheckBox Content=\"Civilian!\" IsChecked=\"{Binding Civilian, Mode=TwoWay}\" Margin=\"2,20,2,2\" FontSize=\"18\" Grid.Row=\"2\">\r\n\t\t\t\t\t\t<CheckBox.ToolTip>\r\n\t\t\t\t\t\t\t<StackPanel Width=\"500\" Background=\"#FF365264\">\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"If enabled this role counts as civilian.\" FontSize=\"18\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\"\r\n\t\t\t\t\t\t\t\t\tPadding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"The gnome will retreat to an appropriate\" FontSize=\"18\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\"\r\n\t\t\t\t\t\t\t\t\tPadding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t\t<TextBlock Text=\"area in case of an alarm.\" FontSize=\"18\" Foreground=\"#FF365264\" Background=\"LightSkyBlue\"\r\n\t\t\t\t\t\t\t\t\tPadding=\"0,2\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t\t\t</StackPanel>\r\n\t\t\t\t\t\t</CheckBox.ToolTip>\r\n\t\t\t\t\t</CheckBox>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t\t<Border Background=\"{StaticResource PanelBackgroundGrey}\" Margin=\"4\" MinWidth=\"500\" MaxWidth=\"500\" Visibility=\"{Binding ShowConfig}\" Grid.Column=\"1\"\r\n\t\t\t\t\tCornerRadius=\"8\">\r\n\t\t\t\t<Grid>\r\n\t\t\t\t\t<ListBox ItemsSource=\"{Binding UniformItems}\" ItemTemplate=\"{StaticResource UniformItemTemplate}\" Grid.Row=\"2\" MinHeight=\"570\" MaxHeight=\"570\"\r\n\t\t\t\t\t\tBorderBrush=\"Black\" BorderThickness=\"2,2,2,2\"/>\r\n\t\t\t\t</Grid>\r\n\t\t\t</Border>\r\n\t\t</Grid>\r\n\t</DataTemplate>\r\n\t\r\n\t\r\n\t<DataTemplate x:Key=\"InvMaterialTemplate\">\r\n\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t<CheckBox Content=\"{Binding Name}\" IsChecked=\"{Binding Checked}\" Width=\"150\" Margin=\"4\" FontSize=\"16\"/>\r\n\t\t\t<TextBlock Text=\"In Stock: \"  FontSize=\"16\" Margin=\"2\" Width=\"80\" TextAlignment=\"Center\"/>\r\n\t\t\t<TextBlock Text=\"{Binding InStock}\"  FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t<TextBlock Text=\"Total: \"  FontSize=\"16\" Margin=\"2\" Width=\"50\" TextAlignment=\"Center\"/>\r\n\t\t\t<TextBlock Text=\"{Binding Total}\"    FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t</StackPanel>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"InvItemTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\" IsExpanded=\"{Binding Expanded, Mode=OneWay}\">\r\n\t\t\t<Expander.Header>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<CheckBox IsChecked=\"{Binding Checked}\" IsThreeState=\"True\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"16\" Width=\"150\"/>\r\n\t\t\t\t\t<TextBlock Text=\"In Stock: \"  FontSize=\"16\" Margin=\"2\" Width=\"80\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding InStock}\"  FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"Total: \"  FontSize=\"16\" Margin=\"2\" Width=\"50\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Total}\"    FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Expander.Header>\r\n\t\t\t<ItemsControl x:Name=\"ICMaterials\" ItemsSource=\"{Binding Children}\" ItemTemplate=\"{StaticResource InvMaterialTemplate}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"InvGroupTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\"  IsExpanded=\"{Binding Expanded, Mode=OneWay}\">\r\n\t\t\t<Expander.Header>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<CheckBox IsChecked=\"{Binding Checked}\" IsThreeState=\"True\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"16\" Width=\"150\"/>\r\n\t\t\t\t\t<TextBlock Text=\"In Stock: \"  FontSize=\"16\" Margin=\"2\" Width=\"80\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding InStock}\"  FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"Total: \"  FontSize=\"16\" Margin=\"2\" Width=\"50\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Total}\"    FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Expander.Header>\r\n\t\t\t<ItemsControl x:Name=\"ICItems\" ItemsSource=\"{Binding Children}\" ItemTemplate=\"{StaticResource InvItemTemplate}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\r\n\t<DataTemplate x:Key=\"InvCategoryTemplate\">\r\n\t\t<Expander VerticalAlignment=\"Center\" Margin=\"4\" IsExpanded=\"{Binding Expanded, Mode=OneWay}\">\r\n\t\t\t<Expander.Header>\r\n\t\t\t\t<StackPanel Orientation=\"Horizontal\">\r\n\t\t\t\t\t<CheckBox  x:Name=\"ICCB\" IsChecked=\"{Binding Checked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" IsThreeState=\"True\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Name}\" FontSize=\"16\" Width=\"150\"/>\r\n\t\t\t\t\t<TextBlock Text=\"In Stock: \"  FontSize=\"16\" Margin=\"2\" Width=\"80\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding InStock}\"  FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"Total: \"  FontSize=\"16\" Margin=\"2\" Width=\"50\" TextAlignment=\"Center\"/>\r\n\t\t\t\t\t<TextBlock Text=\"{Binding Total}\"    FontSize=\"16\" Margin=\"2\" Width=\"100\" TextAlignment=\"Center\"/>\r\n\t\t\t\t</StackPanel>\r\n\t\t\t</Expander.Header>\r\n\t\t\t<ItemsControl x:Name=\"ICGroups\" ItemsSource=\"{Binding Children}\" ItemTemplate=\"{StaticResource InvGroupTemplate}\">\r\n\t\t\t\t<ItemsControl.ItemsPanel>\r\n\t\t\t\t\t<ItemsPanelTemplate>\r\n\t\t\t\t\t\t<StackPanel/>\r\n\t\t\t\t\t</ItemsPanelTemplate>\r\n\t\t\t\t</ItemsControl.ItemsPanel>\r\n\t\t\t</ItemsControl>\r\n\t\t</Expander>\r\n\t</DataTemplate>\r\n\t\r\n\t\r\n\r\n</ResourceDictionary>\r\n"
  },
  {
    "path": "devmessages.txt",
    "content": "Welcome to Ingnomia.\r\n\r\nThis game is still under heavy development.\r\n\r\nPlease report any bugs you find using the in game bug reporting tool (F11). That will also send a zipped save game to me along with the bug description.\r\n\r\nYou can also report bugs, make suggestions or ask gameplay questions on Discord, Reddit or the Steam forum.\r\n\r\nHave fun."
  },
  {
    "path": "docs/Pipfile",
    "content": "[[source]]\nurl = \"https://pypi.org/simple\"\nverify_ssl = true\nname = \"pypi\"\n\n[packages]\njinja2 = \"*\"\n\n[dev-packages]\n\n[requires]\npython_version = \"3.9\"\n"
  },
  {
    "path": "docs/generate.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport os\nimport sys\n\nfrom lib.util import DOCDIR\nfrom lib.render import render\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"-t\", \"--theme\", help=\"theme name, defaults to 'default'\", default=\"default\")\n    parser.add_argument(\n        \"-o\",\n        \"--output\",\n        help=\"output directory, defaults to 'docs/html' in the repository\",\n        default=os.path.join(DOCDIR, \"html\"),\n    )\n    parser.add_argument(\n        \"-f\", \"--overwrite\", help=\"allow overwriting output directory when it exists\", action=\"store_true\"\n    )\n    parser.add_argument(\"-b\", \"--build\", help=\"set build ID information\", default=None)\n\n    ns = parser.parse_args()\n\n    if os.path.exists(ns.output) and not ns.overwrite:\n        print(f\"Error: output path {ns.output} exists, pass --overwrite to overwrite\")\n        sys.exit(1)\n\n    render(ns.theme, ns.output, ns.build)\n"
  },
  {
    "path": "docs/lib/__init__.py",
    "content": ""
  },
  {
    "path": "docs/lib/db.py",
    "content": "import os\nimport sqlite3\n\nfrom .util import DOCDIR, empty, log\n\nDB_PATH = os.path.join(DOCDIR, \"..\", \"content\", \"db\", \"ingnomia.db.sql\")\n\n\nclass Database:\n    def __init__(self):\n        self.conn = sqlite3.connect(\":memory:\", uri=True)\n        with open(DB_PATH) as f:\n            log(\"Loading database\")\n            self.conn.executescript(f.read())\n\n    def basesprite(self, id):\n        for row in self.conn.execute(\"SELECT sourcerectangle, tilesheet FROM BaseSprites WHERE id = ?\", (id,)):\n            return row\n        return None\n\n    def basesprites(self):\n        return [id for (id,) in self.conn.execute(\"SELECT id FROM BaseSprites\")]\n\n    def categories(self):\n        return [cat for (cat,) in self.conn.execute(\"SELECT DISTINCT category FROM Items\")]\n\n    def construction(self, id):\n        for row in self.conn.execute(\"SELECT category, type FROM Constructions WHERE id = ?\", (id,)):\n            return row\n        return None\n\n    def construction_components(self, id):\n        return self.conn.execute(\n            \"SELECT itemid, amount, materials, materialtypes FROM Constructions_Components WHERE id = ?\", (id,)\n        )\n\n    def construction_sprites(self, id):\n        return self.conn.execute(\n            \"SELECT COALESCE(spriteidoverride, spriteid), offset FROM Constructions_Sprites WHERE id = ?\",\n            (id,),\n        )\n\n    def constructions(self):\n        return [id for (id,) in self.conn.execute(\"SELECT id FROM Constructions\")]\n\n    def constructions_for_item(self, item):\n        return [\n            id for (id,) in self.conn.execute(\"SELECT id FROM Constructions WHERE type = 'Item' AND id = ?\", (item,))\n        ]\n\n    def constructions_using_item(self, item):\n        return [id for (id,) in self.conn.execute(\"SELECT id FROM Constructions_Components WHERE itemid = ?\", (item,))]\n\n    def container(self, id):\n        for row in self.conn.execute(\"SELECT capacity, requiresame FROM Containers WHERE id = ?\", (id,)):\n            return row\n        return None\n\n    def container_items(self, id):\n        return self.conn.execute(\n            \"\"\"SELECT id, spriteid, category, itemgroup\n               FROM Items\n               WHERE '|' || allowedcontainers || '|' LIKE '%|' || ? || '|%'\n                  OR '|' || carrycontainer || '|' LIKE '%|' || ? || '|%'\"\"\",\n            (id, id),\n        )\n\n    def craft(self, craft):\n        for row in self.conn.execute(\n            \"\"\"SELECT id, itemid, amount, productiontime, skillid, resultmaterial, resultmaterialtypes, conversionmaterial\n               FROM Crafts c\n               WHERE id = ?\n                 AND (amount = 0 OR EXISTS (SELECT 1 FROM Items i WHERE i.id = c.itemid))\"\"\",\n            (craft,),\n        ):\n            return row\n        return None\n\n    def craft_components(self, craft):\n        return self.conn.execute(\n            \"SELECT amount, itemid, allowedmaterial, allowedmaterialtype FROM Crafts_Components WHERE id = ?\",\n            (craft,),\n        )\n\n    def crafts_using_item(self, item):\n        return [\n            id for (id,) in self.conn.execute(\"SELECT DISTINCT id FROM Crafts_Components WHERE itemid = ?\", (item,))\n        ]\n\n    def drink_items(self):\n        return self.conn.execute(\n            \"\"\"SELECT id, spriteid, category, itemgroup, drinkvalue\n               FROM Items\n               WHERE drinkvalue > 0\"\"\"\n        )\n\n    def food_items(self):\n        return self.conn.execute(\n            \"\"\"SELECT id, spriteid, category, itemgroup, eatvalue\n               FROM Items\n               WHERE eatvalue > 0\"\"\"\n        )\n\n    def group_items(self, cat, group):\n        return self.conn.execute(\n            \"SELECT id, spriteid, allowedmaterials, allowedmaterialtypes FROM Items WHERE category = ? AND itemgroup = ?\",\n            (cat, group),\n        )\n\n    def item_crafts(self, item):\n        return self.conn.execute(\n            \"SELECT id, amount, productiontime, skillid, resultmaterial, resultmaterialtypes, conversionmaterial FROM Crafts WHERE itemid = ?\",\n            (item,),\n        )\n\n    def item_groups(self, cat):\n        return [\n            group\n            for (group,) in self.conn.execute(\n                \"SELECT DISTINCT itemgroup FROM Items WHERE category = ?\",\n                (cat,),\n            )\n        ]\n\n    def item_materials(self, item):\n        for (mat, mattypes) in self.conn.execute(\n            \"SELECT allowedmaterials, allowedmaterialtypes FROM Items WHERE id = ?\", (item,)\n        ):\n            return (mat, mattypes)\n        return (None, None)\n\n    def item_sprite(self, item):\n        for (sprite,) in self.conn.execute(\"SELECT spriteid FROM Items WHERE id = ?\", (item,)):\n            return sprite\n        return None\n\n    def items(self):\n        return self.conn.execute(\n            \"\"\"SELECT id, category, itemgroup, stacksize, value, eatvalue, drinkvalue, lightintensity,\n                      allowedmaterials, allowedmaterialtypes, allowedcontainers, carrycontainer, spriteid\n               FROM Items\"\"\"\n        )\n\n    def items_craftable_with(self, items, workshops):\n        values = [*workshops, *items]\n        wparams = \",\".join(map(lambda x: \"?\", workshops))\n        iparams = \",\".join(map(lambda x: \"?\", items))\n\n        return [\n            id\n            for (id,) in self.conn.execute(\n                f\"\"\"SELECT DISTINCT c.itemid FROM Crafts c\n                    WHERE EXISTS (\n                        SELECT 1 FROM Workshops w\n                        WHERE w.id in ({wparams})\n                        AND '|' || w.crafts || '|' LIKE '%|' || c.id || '|%'\n                    ) AND NOT EXISTS (\n                        SELECT 1 FROM Crafts_Components cc\n                        WHERE cc.id = c.id\n                        AND cc.itemid NOT IN ({iparams})\n                    )\"\"\",\n                values,\n            )\n        ]\n\n    def materials(self):\n        return self.conn.execute(\"SELECT id, color FROM Materials\")\n\n    def materials_of_type(self, type):\n        return [mat for (mat,) in self.conn.execute(\"SELECT id FROM Materials WHERE type = ?\", (type,))]\n\n    def materials_flat(self, mats=None, mattypes=None):\n        mats = [] if empty(mats) else mats.split(\"|\")\n        mattypes = [] if empty(mattypes) else mattypes.split(\"|\")\n        return [*mats, *[m for t in mattypes for m in self.materials_of_type(t)]]\n\n    def plant_harvest_action(self, id):\n        for (action,) in self.conn.execute(\"SELECT action FROM Plants_OnHarvest WHERE id = ?\", (id,)):\n            return action\n        return None\n\n    def plant_produces(self, id):\n        return self.conn.execute(\n            \"\"\"SELECT GROUP_CONCAT(chance, '|'), itemid, materialid\n               FROM Plants_OnHarvest_HarvestedItem\n               WHERE id = ?\n               GROUP BY itemid, materialid\"\"\",\n            (id,),\n        )\n\n    def plant_fell(self, id):\n        return self.conn.execute(\"SELECT itemid, materialid, random FROM Plants_OnFell WHERE id = ?\", (id,))\n\n    def plant_types(self):\n        return [type for (type,) in self.conn.execute(\"SELECT DISTINCT type FROM Plants\")]\n\n    def plant_sprites(self, id):\n        return [\n            (spriteid, layout)\n            for (spriteid, layout) in self.conn.execute(\n                \"SELECT DISTINCT spriteid, layout FROM Plants_States WHERE id = ?\", (id,)\n            )\n        ]\n\n    def plants(self, type):\n        return self.conn.execute(\n            \"SELECT id, growsin, growsinseason, iskilledinseason, losesfruitinseason, material, numfruitsperseason FROM Plants WHERE type = ?\",\n            (type,),\n        )\n\n    def sprite(self, id):\n        # Keep last row only\n        row = None\n        for r in self.conn.execute(\"SELECT offset, basesprite, tint FROM Sprites WHERE id = ?\", (id,)):\n            row = r\n        return row\n\n    def sprite_by_material(self, id):\n        return self.conn.execute(\n            \"SELECT basesprite, materialid, sprite, effect FROM Sprites_ByMaterials WHERE id = ?\",\n            (id,),\n        )\n\n    def sprite_by_material_type(self, id):\n        return self.conn.execute(\n            \"\"\"SELECT bmt.basesprite, m.id, bmt.sprite\n               FROM Sprites_ByMaterialTypes bmt\n               JOIN Materials m ON m.type = bmt.materialtype\n               WHERE bmt.id = ?\"\"\",\n            (id,),\n        )\n\n    def sprite_combine(self, id):\n        return self.conn.execute(\n            \"SELECT basesprite, offset, sprite, tint FROM Sprites_Combine WHERE id = ?\",\n            (id,),\n        )\n\n    def sprite_frames(self, id):\n        return self.conn.execute(\"SELECT DISTINCT basesprite FROM Sprites_Frames WHERE id = ?\", (id,))\n\n    def sprite_random(self, id):\n        return self.conn.execute(\"SELECT basesprite, sprite FROM Sprites_Random WHERE id = ?\", (id,))\n\n    def sprite_rotations(self, id):\n        return self.conn.execute(\n            \"SELECT basesprite, sprite, rotation, effect FROM Sprites_Rotations WHERE id = ?\", (id,)\n        )\n\n    def sprite_seasons(self, id):\n        return self.conn.execute(\"SELECT basesprite, season FROM Sprites_Seasons WHERE id = ?\", (id,))\n\n    def sprite_seasons_rotations(self, id, season):\n        return self.conn.execute(\n            \"SELECT basesprite, rotation FROM Sprites_Seasons_Rotations WHERE id = ?\", (f\"{id}{season}\",)\n        )\n\n    def sprites(self):\n        return [id for (id,) in self.conn.execute(\"SELECT id FROM Sprites\")]\n\n    def translation(self, key):\n        for (text,) in self.conn.execute(\n            \"SELECT text FROM Translation WHERE id = ?\",\n            (key,),\n        ):\n            return text\n\n    def tree_layout(self, id):\n        return self.conn.execute(\n            \"SELECT offset, rotation, spriteid, fruitpos FROM TreeLayouts_Layout WHERE id = ?\", (id,)\n        )\n\n    def uncraftable_items(self):\n        return [id for (id,) in self.conn.execute(\"SELECT id FROM Items EXCEPT SELECT itemid FROM Crafts\")]\n\n    def workshop_components(self, id):\n        return self.conn.execute(\n            \"SELECT itemid, amount FROM Workshops_Components WHERE id = ? AND amount > 0\",\n            (id,),\n        )\n\n    def workshop_requires(self, id):\n        return\n\n    def workshops(self):\n        return self.conn.execute(\"SELECT id, crafts, tab FROM Workshops\")\n\n    def workshops_craftable_with(self, itemids):\n        params = \", \".join(map(lambda x: \"?\", itemids))\n        return [\n            id\n            for (id,) in self.conn.execute(\n                f\"\"\"SELECT w.id FROM Workshops w\n                    WHERE NOT EXISTS (\n                        SELECT 1\n                        FROM Workshops_Components c\n                        WHERE c.id = w.id\n                          AND c.amount > 0\n                          AND c.itemid NOT IN ({params})\n                    )\"\"\",\n                tuple(itemids),\n            )\n        ]\n\n    def workshops_for_craft(self, craft):\n        return [\n            id\n            for (id,) in self.conn.execute(\n                \"SELECT id FROM Workshops WHERE '|' || crafts || '|' LIKE '%|' || ? ||  '|%'\",\n                (craft,),\n            )\n        ]\n\n    def workshop_sprites(self, id):\n        return self.conn.execute(\n            \"\"\"SELECT spriteid, offset, wallrotation, itemid, materialitem, amount, isfloor\n               FROM Workshops_Components\n               WHERE id = ?\"\"\",\n            (id,),\n        )\n\n    def workshops_using_item(self, item):\n        return [\n            id\n            for (id,) in self.conn.execute(\n                \"SELECT DISTINCT id FROM Workshops_Components WHERE itemid = ?\",\n                (item,),\n            )\n        ]\n\n\ndb = Database()\n"
  },
  {
    "path": "docs/lib/material.py",
    "content": "from .db import db\nfrom .util import empty\n\n\nclass MaterialSet:\n    colors = {id: color for (id, color) in db.materials()}\n\n    def __init__(self, materials, types, conversion=None):\n        if not isinstance(materials, list):\n            materials = [] if empty(materials) else materials.split(\"|\")\n\n        if not isinstance(types, list):\n            types = [] if empty(types) else types.split(\"|\")\n\n        if \"RandomMetal\" in materials:\n            materials.remove(\"RandomMetal\")\n            types.append(\"Metal\")\n\n        types_materials = [m for t in types for m in db.materials_of_type(t)]\n\n        if not empty(conversion) and conversion in materials or conversion in types_materials:\n            materials = [conversion]\n            types = []\n            types_materials = []\n\n        self.all_materials = sorted(set([*materials, *types_materials]))\n        self.labels = [\n            *[f\"any {t}\" for t in sorted(types)],\n            *sorted([db.translation(f\"$MaterialName_{m}\") for m in materials]),\n        ]\n\n        idparts = [*[f\"M{m}\" for m in sorted(materials)], *[f\"T{t}\" for t in sorted(types)]]\n\n        if len(idparts):\n            self.id = \"\".join(idparts)\n        else:\n            self.id = \"any\"\n\n        unique_colors = set()\n        unique_materials = set()\n        for m in self.all_materials:\n            color = MaterialSet.colors[m]\n            if color not in unique_colors:\n                unique_colors.add(color)\n                unique_materials.add(m)\n\n        self.unique_tints = sorted(unique_materials)\n\n    def covers(self, itemid):\n        (mats, mattypes) = db.item_materials(itemid)\n        all_materials = set(db.materials_flat(mats, mattypes))\n\n        return all_materials == set(self.all_materials)\n\n    def __eq__(self, other):\n        return other is not None and self.id == other.id\n\n    def __repr__(self):\n        return repr({\"type\": \"MaterialSet\", \"id\": self.id})\n"
  },
  {
    "path": "docs/lib/render.py",
    "content": "from .themes import themes\n\n\ndef render(theme, output, build_id):\n    try:\n        ThemeCtor = themes[theme]\n    except KeyError:\n        raise KeyError(f\"Theme '{theme}' was not found\")\n\n    t = ThemeCtor()\n    t.render(output, build_id)\n"
  },
  {
    "path": "docs/lib/sprites/__init__.py",
    "content": "from .sprite import SpriteManager, MissingMaterials\nfrom .layout import Layout\n"
  },
  {
    "path": "docs/lib/sprites/layout.py",
    "content": "import random\n\nfrom ..db import db\nfrom ..util import empty, sprite_offset3d\nfrom .sprite import EmptySprite, Sprite, SpriteManager\n\n\ndef iso_projectx(x, y, z):\n    return int((x - y) * 16)\n\n\ndef iso_projecty(x, y, z):\n    return int((x + y) * 8 - z * 20)\n\n\ndef iso_project(pos):\n    (x, y, z) = (pos[\"x\"], pos[\"y\"], pos[\"z\"])\n    return {\"x\": iso_projectx(x, y, z), \"y\": iso_projecty(x, y, z)}\n\n\nclass Layout:\n    @classmethod\n    def sprite(self, id):\n        return Layout(\n            [\n                LayoutCell({\"x\": 0, \"y\": 0, \"z\": 0}, EmptySprite(), overrides={\"is_floor\": True}),\n                LayoutCell({\"x\": 0, \"y\": 0, \"z\": 0}, id),\n            ]\n        )\n\n    @classmethod\n    def construction(self, id):\n        sprites = list(db.construction_sprites(id))\n        if len(sprites) == 0:\n            sprites = [(id, \"0 0 0\")]\n\n        return Layout(\n            [\n                LayoutCell({\"x\": 0, \"y\": 0, \"z\": 0}, EmptySprite(), overrides={\"is_floor\": True}),\n                *[LayoutCell(sprite_offset3d(offset), spriteid) for (spriteid, offset) in sprites],\n            ]\n        )\n\n    @classmethod\n    def workshop(self, id):\n        sprites = list(db.workshop_sprites(id))\n        if len(sprites) == 0:\n            raise ValueError(f\"No sprites for workshop {id}\")\n\n        item_materials = {}\n        input_materials = []\n        for (_, _, _, itemid, _, amount, _) in sprites:\n            if not empty(itemid) and amount > 0:\n                if itemid not in item_materials:\n                    (mats, mattypes) = db.item_materials(itemid)\n                    item_materials[itemid] = sorted(db.materials_flat(mats, mattypes))\n\n                for _ in range(int(amount)):\n                    input_materials.append(item_materials[itemid])\n\n        cells = []\n        for (spriteid, offset, rotation, itemid, materialitem, _, isfloor) in sprites:\n            pos = sprite_offset3d(offset)\n            if pos[\"z\"] == 0 and empty(isfloor):\n                cells.append(LayoutCell(pos, EmptySprite(), overrides={\"is_floor\": True}))\n\n            if empty(spriteid) or spriteid == \"WorkshopInputIndicator\":\n                cells.append(LayoutCell(pos, EmptySprite()))\n            else:\n                overrides = {}\n\n                if not empty(rotation):\n                    overrides[\"rotation\"] = rotation\n\n                if not empty(itemid):\n                    overrides[\"materials\"] = item_materials[itemid]\n                elif not empty(materialitem):\n                    indices = [int(i) for i in materialitem.split(\"|\")]\n                    if len(indices) == 1:\n                        overrides[\"materials\"] = input_materials[indices[0]]\n                    else:\n                        overrides[\"multi_materials\"] = [input_materials[i] for i in indices]\n\n                cells.append(LayoutCell(pos, spriteid, overrides=overrides))\n\n        return Layout(cells)\n\n    @classmethod\n    def tree(self, layoutid, large_floor=False):\n        cells = []\n        layout = list(db.tree_layout(layoutid))\n\n        floorpos = set([(0, 0)])\n        if large_floor and any([not offset.startswith(\"0 0\") for (offset, _, _, _) in layout]):\n            floorpos = [(x, y) for x in range(-1, 2) for y in range(-1, 2)]\n\n        for (offset, rotation, spriteid, _) in layout:\n            pos = sprite_offset3d(offset)\n\n            if pos[\"z\"] == 0:\n                for x, y in floorpos:\n                    cells.append(LayoutCell({\"x\": x, \"y\": y, \"z\": 0}, EmptySprite(), overrides={\"is_floor\": True}))\n\n            overrides = {\"random\": \"first\"}\n            if not empty(rotation):\n                overrides[\"rotation\"] = rotation\n\n            cells.append(\n                LayoutCell(\n                    pos,\n                    spriteid,\n                    overrides=overrides,\n                )\n            )\n\n        return Layout(cells)\n\n    def __init__(self, cells):\n        # 3D AABB\n        axes = [\"x\", \"y\", \"z\"]\n        mins = {axis: min([c.pos[axis] for c in cells]) for axis in axes}\n        maxes = {axis: max([c.pos[axis] for c in cells]) for axis in axes}\n        sizes = {axis: maxes[axis] - mins[axis] + 1 for axis in axes}\n\n        # Project to 2D bbox\n        mins2d = {\n            \"x\": min(iso_projectx(c.pos[\"x\"], c.pos[\"y\"] + 1, c.pos[\"z\"]) for c in cells),\n            \"y\": min(iso_projecty(c.pos[\"x\"], c.pos[\"y\"], c.pos[\"z\"] + 1) for c in cells),\n        }\n\n        maxes2d = {\n            \"x\": max(iso_projectx(c.pos[\"x\"] + 1, c.pos[\"y\"], c.pos[\"z\"]) for c in cells),\n            \"y\": max(iso_projecty(c.pos[\"x\"] + 1, c.pos[\"y\"] + 1, c.pos[\"z\"]) for c in cells),\n        }\n\n        self.bbox = {\n            \"width\": maxes2d[\"x\"] - mins2d[\"x\"],\n            \"height\": maxes2d[\"y\"] - mins2d[\"y\"],\n            \"minx\": mins2d[\"x\"] + 16,\n            \"miny\": mins2d[\"y\"] + 20,\n        }\n\n        # Sort cells for correct drawing order\n        self.cells = sorted(\n            sorted(sorted(cells, key=lambda c: c.pos[\"x\"]), key=lambda c: c.pos[\"y\"]), key=lambda c: c.pos[\"z\"]\n        )\n\n    def set_floor(self, spriteid, tint=None, random=None, season=None, materials=None):\n        sprite = SpriteManager.get(spriteid)\n\n        overrides = {\"is_floor\": True}\n\n        if tint is not None:\n            overrides[\"materials\"] = [tint]\n        elif materials is not None:\n            overrides[\"materials\"] = materials\n\n        if random is not None:\n            overrides[\"random\"] = random\n\n        if season is not None:\n            overrides[\"season\"] = season\n\n        for index in [self.cells.index(c) for c in self.cells if c.overrides.get(\"is_floor\") == True]:\n            self.cells[index] = LayoutCell(self.cells[index].pos, sprite, overrides=overrides)\n\n    def select(self, **kwargs):\n        return {\"bbox\": self.bbox, \"cells\": [c.select(**kwargs) for c in self.cells]}\n\n\nclass LayoutCell:\n    def __init__(self, pos, sprite, overrides={}):\n        self.sprite = sprite if isinstance(sprite, Sprite) else SpriteManager.get(sprite)\n        self.pos = pos\n        self.projected = iso_project(pos)\n        self.overrides = overrides\n\n    def select(self, **kwargs):\n        if \"materials\" in self.overrides:\n            kwargs[\"materials\"] = self.overrides[\"materials\"]\n\n        if \"multi_materials\" in self.overrides:\n            kwargs[\"multi_materials\"] = self.overrides[\"multi_materials\"]\n\n        if \"rotation\" in self.overrides:\n            kwargs[\"rotation\"] = self.overrides[\"rotation\"]\n\n        if \"random\" in self.overrides:\n            kwargs[\"random\"] = self.overrides[\"random\"]\n\n        if \"season\" in self.overrides:\n            kwargs[\"season\"] = self.overrides[\"season\"]\n\n        return {\"pos\": self.pos, \"projected\": self.projected, \"layers\": self.sprite.select(**kwargs)}\n"
  },
  {
    "path": "docs/lib/sprites/render.py",
    "content": "from ..db import db\nfrom ..util import empty\n\ncolors = {mat: color for (mat, color) in db.materials()}\n\n\nclass RenderBase:\n    animation = False\n\n    def __init__(self, base, tilesheet, rect, material=None, effects=[], ox=0, oy=0, anim_frame=0, anim_length=1):\n        self.base = base\n        self.tilesheet = tilesheet\n        self.rect = rect\n        self.material = material\n        self.effects = [e for e in effects if not empty(e) and e != \"none\"]\n        self.ox = ox\n        self.oy = oy\n        self.anim_frame = anim_frame\n        self.anim_length = anim_length\n\n    def __repr__(self):\n        return repr(self.__dict__)\n\n    def uid(self, use_color=False):\n        dct = self.__dict__\n\n        if use_color and (self.material is not None):\n            dct = {**dct, \"material\": colors[self.material]}\n\n        return repr(dct)\n\n\nclass RenderLayers:\n    def __init__(self, layers):\n        self.layers = layers\n\n    def __repr__(self):\n        return repr(self.layers)\n\n\nclass RenderAlternatives:\n    def __init__(self, alternatives):\n        self.alternatives = alternatives\n\n    def unique(self, use_color=False):\n        unique_uids = set()\n        unique_alts = []\n\n        for alt in self.alternatives:\n            uid = alt.uid(use_color=use_color)\n            if uid not in unique_uids:\n                unique_uids.add(uid)\n                unique_alts.append(alt)\n\n        return unique_alts\n\n    def common(self):\n        common = {}\n        attrs = [\"tilesheet\", \"material\", \"ox\", \"oy\"]\n        rattrs = [\"x\", \"y\", \"w\", \"h\"]\n\n        for attr in attrs:\n            values = set([getattr(alt, attr) for alt in self.alternatives])\n            if len(values) == 1:\n                common[attr] = values.pop()\n\n        effects = set([\",\".join(alt.effects) for alt in self.alternatives])\n        if len(values) == 1:\n            common[\"effects\"] = effects.pop().split(\",\")\n\n        for attr in rattrs:\n            values = set([alt.rect[attr] for alt in self.alternatives])\n            if len(values) == 1:\n                common[f\"rect{attr}\"] = values.pop()\n\n        return common\n\n    def __repr__(self):\n        return repr(self.alternatives)\n\n\nclass Render:\n    @classmethod\n    def base(cls, *args, **kwargs):\n        return cls.layers([cls.alternatives([RenderBase(*args, **kwargs)])])\n\n    @classmethod\n    def layers(cls, layers):\n        # Flatten layers\n        if any([isinstance(layer, RenderLayers) for layer in layers]):\n            return cls.layers(\n                [sub for layer in layers for sub in (layer.layers if isinstance(layer, RenderLayers) else [layer])]\n            )\n\n        return RenderLayers(layers)\n\n    @classmethod\n    def alternatives(cls, alternatives):\n        # Flatten alternatives\n        if any([isinstance(alt, RenderAlternatives) for alt in alternatives]):\n            sub_alts = [\n                sub\n                for alt in alternatives\n                for sub in (alt.alternatives if isinstance(alt, RenderAlternatives) else [alt])\n            ]\n\n            anim_lengths = set([sub.anim_length for sub in sub_alts])\n\n            if len(anim_lengths) > 1:\n                raise ValueError(f\"Alternative with multiple animation lengths\")\n\n            anim_length = anim_lengths.pop()\n\n            # Interleave animation frames\n            anim_frames = set([sub.anim_frame for sub in sub_alts])\n            if anim_length > 1 and len(sub_alts) > anim_length and len(anim_frames) == anim_length:\n                interleaved = []\n                while len(sub_alts):\n                    for frame in range(anim_length):\n                        next_frame = [sub for sub in sub_alts if sub.anim_frame == frame][0]\n                        interleaved.append(next_frame)\n                        sub_alts.pop(sub_alts.index(next_frame))\n                sub_alts = interleaved\n\n            return cls.alternatives(sub_alts)\n\n        # Make layers toplevel\n        if any([isinstance(alt, RenderLayers) for alt in alternatives]):\n            layers = []\n            num_layers = max([len(alt.layers) for alt in alternatives if isinstance(alt, RenderLayers)])\n\n            for i in range(num_layers):\n                layer_alts = []\n                for alt in alternatives:\n                    if isinstance(alt, RenderLayers) and i < len(alt.layers):\n                        layer_alts.append(alt.layers[i])\n                    elif isinstance(alt, RenderBase) and i == 0:\n                        layer_alts.append(alt)\n\n                layers.append(cls.alternatives(layer_alts))\n\n            return cls.layers(layers)\n\n        return cls.layers([RenderAlternatives(alternatives)])\n\n    @classmethod\n    def empty(cls):\n        return cls.layers([])\n"
  },
  {
    "path": "docs/lib/sprites/sprite.py",
    "content": "from random import choice\n\nfrom ..db import db\nfrom ..util import empty, log, sprite_offset, sprite_rect\n\nfrom .render import Render\n\n\ndef base_or_sprite(base, sprite):\n    return BaseSprite(base) if not empty(base) else SpriteManager.get(sprite, internal=True)\n\n\nclass MissingMaterials(Exception):\n    def __init__(self, id, materials):\n        super().__init__(f\"Missing materials for '{id}': {', '.join(materials)}\")\n        self.materials = materials\n\n\nclass Sprite:\n    def __init__(self, id, data, tint=None, offset=None):\n        self.id = id\n        self.data = data\n        self.tint = tint\n        self.offset = offset\n        self.setup()\n\n    def setup(self):\n        raise NotImplementedError()\n\n    # Possible kwargs:\n    #  rotation: one of 'FR' (default), 'FL', 'BR', 'BL' or 'all'\n    #  season: one of 'Spring' (default), 'Summer', 'Winter', 'Autumn' or 'all'\n    #  random: 'all' (default), 'random' or 'first'\n    #  frames: 'all' (default), any int, any range\n    #  materials: 'any' (default) or a list of material IDs\n    #  multi_materials: None (default) or a list of values suitable for 'materials' (for CombinedSprites)\n    def select(self, tint=None, offset=None, **kwargs):\n        if self.tint is not None:\n            tint = self.tint\n\n        if self.offset is not None:\n            offset = self.offset\n\n        return self._select(tint=tint, offset=offset, **kwargs)\n\n    def _select(self, **kwargs):\n        raise NotImplementedError()\n\n    def __repr__(self):\n        return repr({\"sprite\": type(self).__name__, \"attrs\": self.__dict__})\n\n\nclass EmptySprite(Sprite):\n    def __init__(self):\n        super().__init__(\"empty\", None)\n\n    def setup(self):\n        pass\n\n    def _select(self, **kwargs):\n        return Render.empty()\n\n\nclass BaseSprite(Sprite):\n    def __init__(self, id, **kwargs):\n        super().__init__(id, None, **kwargs)\n\n    def setup(self):\n        base = db.basesprite(self.id)\n        if base is None:\n            raise ValueError(f\"No BaseSprite with id '{self.id}'\")\n\n        (rect, self.tilesheet) = base\n        self.rect = sprite_rect(rect)\n\n    def _select(self, tint=None, materials=None, effects=[], offset=None, anim_frame=0, anim_length=1, **kwargs):\n        params = {\"effects\": effects, \"anim_frame\": anim_frame, \"anim_length\": anim_length}\n\n        if offset is not None:\n            params[\"ox\"] = offset[\"x\"]\n            params[\"oy\"] = offset[\"y\"]\n\n        if (tint == \"Material\" or self.tint == \"Material\") and materials is not None:\n            return Render.alternatives(\n                [Render.base(self.id, self.tilesheet, self.rect, material=mat, **params) for mat in materials]\n            )\n\n        return Render.base(self.id, self.tilesheet, self.rect, **params)\n\n\nclass AnimatedSprite(Sprite):\n    def setup(self):\n        self.frames = [BaseSprite(base) if isinstance(base, str) else base for (base,) in self.data]\n\n    def _select(self, frames=\"all\", **kwargs):\n        if frames == \"all\":\n            indices = [i for i in range(len(self.frames))]\n        elif isinstance(frames, int):\n            indices = [frames]\n        elif isinstance(frames, range):\n            indices = frames\n        else:\n            raise ValueError(f\"Invalid frames spec for '{self.id}': {frames}\")\n\n        return Render.alternatives(\n            [self.frames[i].select(anim_frame=indices.index(i), anim_length=len(indices), **kwargs) for i in indices]\n        )\n\n\nclass RandomSprite(Sprite):\n    def setup(self):\n        self.choices = [base_or_sprite(base, sprite) for (base, sprite) in self.data]\n\n    def _select(self, random=\"all\", **kwargs):\n        if random == \"first\":\n            return self.choices[0].select(**kwargs)\n        elif random == \"random\":\n            return choice(self.choices).select(**kwargs)\n        elif random == \"all\":\n            return Render.alternatives([c.select(**kwargs) for c in self.choices])\n        else:\n            raise ValueError(f\"Invalid random spec for '{self.id}': {random}\")\n\n\nclass RotatingSprite(Sprite):\n    def setup(self):\n        self.rotations = {}\n        self.effects = {}\n\n        for (base, sprite, rotation, effect) in self.data:\n            self.rotations[rotation] = base_or_sprite(base, sprite)\n            self.effects[rotation] = effect\n\n    def _select(self, rotation=\"FR\", effects=[], **kwargs):\n        if rotation == \"all\":\n            return Render.alternatives(\n                [self.rotations[r].select(effects=[*effects, self.effects[r]], **kwargs) for r in self.rotations.keys()]\n            )\n        elif rotation in self.rotations:\n            return self.rotations[rotation].select(effects=[*effects, self.effects[rotation]], **kwargs)\n        else:\n            raise ValueError(f\"Invalid rotation spec for '{self.id}': {rotation}\")\n\n\nclass SeasonalSprite(Sprite):\n    def setup(self):\n        self.seasons = {}\n\n        for (base, season) in self.data:\n            if empty(base):\n                rotations = list(db.sprite_seasons_rotations(self.id, season))\n                if len(rotations) == 0:\n                    raise ValueError(f\"No season rotations in {season} for sprite '{self.id}'\")\n\n                self.seasons[season] = RotatingSprite(\n                    self.id, [(base, None, rotation, None) for (base, rotation) in rotations]\n                )\n            else:\n                self.seasons[season] = BaseSprite(base)\n\n    def _select(self, season=\"Spring\", **kwargs):\n        if season == \"all\":\n            return Render.alternatives([self.seasons[s].select(**kwargs) for s in self.seasons.keys()])\n        elif season in self.seasons:\n            return self.seasons[season].select(**kwargs)\n        else:\n            raise ValueError(f\"Invalid season spec for '{self.id}': {season}\")\n\n\nclass CombinedSprite(Sprite):\n    def setup(self):\n        self.layers = []\n        self.offsets = []\n        self.tints = []\n\n        for (base, offset, sprite, tint) in self.data:\n            self.layers.append(base_or_sprite(base, sprite))\n            self.offsets.append(sprite_offset(offset))\n            self.tints.append(None if empty(tint) else tint)\n\n    def _select(self, tint=None, multi_materials=None, offset=None, **kwargs):\n        if multi_materials is not None:\n            if len(multi_materials) != len(self.layers):\n                raise ValueError(\n                    f\"Invalid multi materials for '{self.id}': expected {len(self.layers)}, got {len(multi_materials)}\"\n                )\n\n            return Render.layers(\n                [\n                    layer.select(offset=offset, tint=ctint if tint is None else tint, materials=mats, **kwargs)\n                    for (layer, offset, ctint, mats) in zip(self.layers, self.offsets, self.tints, multi_materials)\n                ]\n            )\n\n        return Render.layers(\n            [\n                layer.select(offset=offset, tint=ctint if tint is None else tint, **kwargs)\n                for (layer, offset, ctint) in zip(self.layers, self.offsets, self.tints)\n            ]\n        )\n\n\nclass MaterialSprite(Sprite):\n    def setup(self):\n        self.materials = {}\n        self.effects = {}\n\n        for (base, mat, sprite, effect) in self.data:\n            self.materials[mat] = base_or_sprite(base, sprite)\n            self.effects[mat] = effect\n\n    def _select(self, materials=\"any\", effects=[], **kwargs):\n        if materials == \"any\":\n            materials = self.materials.keys()\n        else:\n            missing = [m for m in materials if m not in self.materials]\n            if len(missing):\n                raise MissingMaterials(self.id, sorted(missing))\n\n        return Render.alternatives(\n            [self.materials[m].select(materials=[m], effects=[*effects, self.effects[m]], **kwargs) for m in materials]\n        )\n\n\nclass MaterialTypeSprite(MaterialSprite):\n    def __init__(self, id, data, **kwargs):\n        super().__init__(id, [(base, mat, sprite, None) for (base, mat, sprite) in data], **kwargs)\n\n\nclass SpriteManager:\n    empty = EmptySprite()\n    sprites = {}\n    exports = set()\n\n    @classmethod\n    def get(cls, id, internal=False):\n        if empty(id):\n            raise ValueError(\"Cannot create sprite without an id\")\n\n        if id not in cls.sprites:\n            try:\n                cls.sprites[id] = cls._build(id)\n            except Exception as ex:\n                log(f\"Error building sprite '{id}': {ex}\", \"! \")\n                cls.sprites[id] = cls.empty\n\n        if not internal:\n            cls.exports.add(id)\n\n        return cls.sprites[id]\n\n    @classmethod\n    def random(cls, id, spriteids):\n        return RandomSprite(id, [(None, id) for id in spriteids])\n\n    @classmethod\n    def _build(cls, id):\n        try:\n            (offset, base, tint) = db.sprite(id)\n        except:\n            log(f\"No sprite with id '{id}'\", \"! \")\n            return cls.empty\n\n        if empty(tint):\n            tint = None\n\n        if empty(offset):\n            offset = None\n\n        if empty(base):\n            base = id\n\n        kwargs = {\"tint\": tint, \"offset\": sprite_offset(offset)}\n\n        by_material = list(db.sprite_by_material(id))\n        if len(by_material):\n            return MaterialSprite(id, by_material, **kwargs)\n\n        by_material_type = list(db.sprite_by_material_type(id))\n        if len(by_material_type):\n            return MaterialTypeSprite(id, by_material_type, **kwargs)\n\n        random = list(db.sprite_random(id))\n        if len(random):\n            return RandomSprite(id, random, **kwargs)\n\n        rotations = list(db.sprite_rotations(id))\n        if len(rotations):\n            return RotatingSprite(id, rotations, **kwargs)\n\n        seasons = list(db.sprite_seasons(id))\n        if len(seasons):\n            return SeasonalSprite(id, seasons, **kwargs)\n\n        frames = list(db.sprite_frames(id))\n        if len(frames):\n            return AnimatedSprite(id, frames, **kwargs)\n\n        combine = list(db.sprite_combine(id))\n        if len(combine):\n            return CombinedSprite(id, combine, **kwargs)\n\n        return BaseSprite(base, **kwargs)\n"
  },
  {
    "path": "docs/lib/store.py",
    "content": "from .db import db\nfrom .material import MaterialSet\nfrom .util import empty, log, sort_translations, total_amount, amount_hint\n\n\nclass Store:\n    def category_groups(self, cat):\n        return sort_translations(\n            [\n                {\n                    \"id\": group,\n                    \"translation\": self.translate(\"group\", group),\n                    \"items\": self.group_items(cat, group),\n                }\n                for group in db.item_groups(cat)\n            ]\n        )\n\n    def categories(self):\n        return sort_translations(\n            [\n                {\n                    \"id\": cat,\n                    \"translation\": self.translate(\"category\", cat),\n                    \"groups\": self.category_groups(cat),\n                }\n                for cat in db.categories()\n            ]\n        )\n\n    def categorize(self, items):\n        return sort_translations(\n            [\n                {\n                    \"id\": cat,\n                    \"translation\": self.translate(\"category\", cat),\n                    \"groups\": sort_translations(\n                        [\n                            {\n                                \"id\": group,\n                                \"translation\": self.translate(\"group\", group),\n                                \"items\": [item for item in items if item[\"cat\"] == cat and item[\"group\"] == group],\n                            }\n                            for group in set([item[\"group\"] for item in items if item[\"cat\"] == cat])\n                        ]\n                    ),\n                }\n                for cat in set([item[\"cat\"] for item in items])\n            ]\n        )\n\n    def construction(self, id):\n        (category, type) = db.construction(id)\n        if category is None:\n            category = type\n\n        components = self.construction_components(id)\n        if len(components) == 0:\n            log(f\"Empty construction {id}\", \"! \")\n            return None\n\n        matset = components[0][\"material_set\"]\n\n        return {\n            \"id\": id,\n            \"translation\": self.translate(\"construction\", id),\n            \"material_set\": matset,\n            \"components_unsorted\": components,\n            \"components\": sort_translations(components),\n            \"category\": category,\n            \"type\": type,\n        }\n\n    def construction_component(self, itemid, amount, mats, mattypes):\n        matset = MaterialSet(mats, mattypes)\n\n        if matset.id == \"any\":\n            (materials, mattypes) = db.item_materials(itemid)\n            matset = MaterialSet(materials, mattypes)\n\n        return {\n            \"id\": itemid,\n            \"translation\": self.translate(\"item\", itemid),\n            \"spriteid\": self.item_spriteid(itemid),\n            \"material_set\": matset,\n            \"amount\": int(amount),\n        }\n\n    def construction_components(self, id):\n        return [self.construction_component(*row) for row in db.construction_components(id)]\n\n    def constructions(self):\n        constructions = [c for c in [self.construction(id) for id in db.constructions()] if c is not None]\n\n        return [\n            {\"category\": cat, \"constructions\": sort_translations([c for c in constructions if c[\"category\"] == cat])}\n            for cat in sorted(set([c[\"category\"] for c in constructions]))\n        ]\n\n    def container(self, id):\n        if empty(id):\n            return None\n\n        row = db.container(id)\n        if row is None:\n            return None\n\n        (capacity, same) = row\n\n        return {\n            \"id\": id,\n            \"translation\": self.translate(\"item\", id),\n            \"spriteid\": self.item_spriteid(id),\n            \"capacity\": int(capacity),\n            \"same\": int(same) == 1,\n        }\n\n    def container_items(self, id):\n        return self.categorize(\n            [\n                {\n                    \"id\": item,\n                    \"cat\": cat,\n                    \"group\": group,\n                    \"translation\": self.translate(\"item\", item),\n                    \"spriteid\": self.item_spriteid(item),\n                }\n                for (item, sprite, cat, group) in db.container_items(id)\n            ]\n        )\n\n    def craft_component(self, amount, itemid, mats, mattypes):\n        matset = MaterialSet(mats, mattypes)\n        return {\n            \"id\": itemid,\n            \"translation\": self.translate(\"item\", itemid),\n            \"spriteid\": self.item_spriteid(itemid),\n            \"material_set\": matset,\n            \"amount\": int(amount),\n        }\n\n    def craft_components(self, craft):\n        return sort_translations([self.craft_component(*row) for row in db.craft_components(craft)])\n\n    def craft_workshops(self, craft):\n        return sort_translations(\n            [{\"id\": id, \"translation\": self.translate(\"workshop\", id)} for id in db.workshops_for_craft(craft)]\n        )\n\n    def craft(self, id, itemid, amount, time, skill, rmats, rmattypes, rconv):\n        matset = MaterialSet(rmats, rmattypes, rconv)\n        return {\n            \"id\": itemid,\n            \"translation\": \"none\" if itemid is None else self.translate(\"item\", itemid),\n            \"spriteid\": None if itemid is None else self.item_spriteid(itemid),\n            \"material_set\": matset,\n            \"time\": int(time),\n            \"skill\": self.translate(\"skill\", skill),\n            \"components\": self.craft_components(id),\n            \"workshops\": self.craft_workshops(id),\n            \"amount\": int(amount),\n        }\n\n    def drinks(self):\n        return self.categorize(\n            [\n                {\n                    \"id\": item,\n                    \"cat\": cat,\n                    \"group\": group,\n                    \"translation\": self.translate(\"item\", item),\n                    \"spriteid\": self.item_spriteid(item),\n                    \"drinkvalue\": drinkval,\n                }\n                for (item, sprite, cat, group, drinkval) in db.drink_items()\n            ]\n        )\n\n    def food(self):\n        return self.categorize(\n            [\n                {\n                    \"id\": item,\n                    \"cat\": cat,\n                    \"group\": group,\n                    \"translation\": self.translate(\"item\", item),\n                    \"spriteid\": self.item_spriteid(item),\n                    \"eatvalue\": eatval,\n                }\n                for (item, sprite, cat, group, eatval) in db.food_items()\n            ]\n        )\n\n    def group_items(self, cat, group):\n        return sort_translations(\n            [\n                {\"id\": item, \"translation\": self.translate(\"item\", item), \"spriteid\": self.item_spriteid(item)}\n                for (item, _, _, _) in db.group_items(cat, group)\n            ]\n        )\n\n    def item(self, id, cat, group, stack, value, evalue, dvalue, light, mats, mattypes, cnt, ccnt, sprite):\n        containerinfo = {}\n        if cat == \"Containers\":\n            containerinfo = self.container(id)\n            containerinfo[\"can_contain\"] = self.container_items(id)\n\n        (materials, material_tree) = self.material_tree(mats, mattypes)\n\n        return {\n            \"id\": id,\n            \"translation\": self.translate(\"item\", id),\n            \"group\": {\n                \"id\": group,\n                \"translation\": self.translate(\"group\", group),\n            },\n            \"category\": {\n                \"id\": cat,\n                \"translation\": self.translate(\"category\", cat),\n            },\n            \"stack\": stack,\n            \"container\": self.container(cnt),\n            \"carry\": self.container(ccnt),\n            \"spriteid\": self.item_spriteid(id),\n            \"materials\": materials,\n            \"material_tree\": material_tree,\n            \"value\": value,\n            \"evalue\": evalue,\n            \"dvalue\": dvalue,\n            \"light\": light,\n            \"crafts\": self.item_crafts(id),\n            \"rcrafts\": self.item_rcrafts(id),\n            \"wcrafts\": self.item_wcrafts(id),\n            \"constructions\": self.item_constructions(id),\n            \"rconstructions\": self.item_rconstructions(id),\n            **containerinfo,\n        }\n\n    def item_constructions(self, item):\n        constructions = [self.construction(id) for id in db.constructions_for_item(item)]\n\n        return [\n            {\"category\": cat, \"constructions\": sort_translations([c for c in constructions if c[\"category\"] == cat])}\n            for cat in sorted(set([c[\"category\"] for c in constructions]))\n        ]\n\n    def item_rconstructions(self, item):\n        constructions = [self.construction(id) for id in db.constructions_using_item(item)]\n\n        return [\n            {\"category\": cat, \"constructions\": sort_translations([c for c in constructions if c[\"category\"] == cat])}\n            for cat in sorted(set([c[\"category\"] for c in constructions]))\n        ]\n\n    def item_crafts(self, item):\n        return [\n            self.craft(id, item, amount, time, skill, rmats, rmattypes, rconv)\n            for (id, amount, time, skill, rmats, rmattypes, rconv) in db.item_crafts(item)\n        ]\n\n    def item_rcraft(self, craft):\n        row = db.craft(craft)\n        return None if row is None else self.craft(*row)\n\n    def item_rcrafts(self, item):\n        return list(filter(lambda c: c is not None, [self.item_rcraft(craft) for craft in db.crafts_using_item(item)]))\n\n    def item_wcrafts(self, item):\n        return [{\"id\": id, \"translation\": self.translate(\"workshop\", id)} for id in db.workshops_using_item(item)]\n\n    def item_spriteid(self, item):\n        sprite = db.item_sprite(item)\n        return item if sprite is None else sprite\n\n    def items(self):\n        return sort_translations([self.item(*row) for row in db.items()])\n\n    def materials(self, mats, mattypes):\n        return sort_translations(\n            [{\"id\": id, \"translation\": self.translate(\"material\", id)} for id in db.materials_flat(mats, mattypes)]\n        )\n\n    def material_tree(self, mats, mattypes):\n        mats = [] if mats is None else mats.split(\"|\")\n        mattypes = [] if mattypes is None else mattypes.split(\"|\")\n\n        tree = sort_translations(\n            [\n                *(\n                    []\n                    if len(mats) == 0\n                    else [\n                        {\n                            \"id\": \"Other\",\n                            \"materials\": sort_translations(\n                                [{\"id\": mat, \"translation\": self.translate(\"material\", mat)} for mat in mats]\n                            ),\n                        }\n                    ]\n                ),\n                *[\n                    {\n                        \"id\": type,\n                        \"materials\": sort_translations(\n                            [\n                                {\"id\": mat, \"translation\": self.translate(\"material\", mat)}\n                                for mat in db.materials_of_type(type)\n                            ]\n                        ),\n                    }\n                    for type in mattypes\n                ],\n            ]\n        )\n\n        return ([*mats, *[mat for type in mattypes for mat in db.materials_of_type(type)]], tree)\n\n    def plant_produce(self, chance, itemid, materialid, fruits_per_season=0):\n        matset = MaterialSet(materialid, None)\n\n        if fruits_per_season == 0:\n            amount = total_amount(chance)\n            hint = amount_hint(chance)\n        else:\n            amount = int(fruits_per_season)\n            hint = \"Per season\"\n\n        return {\n            \"id\": itemid,\n            \"translation\": self.translate(\"item\", itemid),\n            \"spriteid\": self.item_spriteid(itemid),\n            \"material_set\": matset,\n            \"amount\": amount,\n            \"amount_hint\": hint,\n            \"type\": \"harvest\",\n        }\n\n    def plant_fell(self, plantid, itemid, materialid, random):\n        matset = MaterialSet(materialid, None)\n\n        if random > 0:\n            amount = f\"1-{int(random)}\"\n        else:\n            layout = list(db.tree_layout(plantid))\n            amount = 1 if len(layout) == 0 else len(layout)\n\n        return {\n            \"id\": itemid,\n            \"translation\": self.translate(\"item\", itemid),\n            \"spriteid\": self.item_spriteid(itemid),\n            \"material_set\": matset,\n            \"amount\": amount,\n            \"type\": \"fell\",\n        }\n\n    def plant_produces(self, id, fruits_per_season=0):\n        return [\n            *[self.plant_produce(*row, fruits_per_season) for row in db.plant_produces(id)],\n            *[self.plant_fell(id, *row) for row in db.plant_fell(id)],\n        ]\n\n    def plant(self, id, growsin, growseason, killseason, loseseason, material, fruits):\n        harvest_action = db.plant_harvest_action(id)\n        fruits_per_season = 0\n        if harvest_action == \"ReduceFruitCount\":\n            fruits_per_season = fruits\n\n        return {\n            \"id\": id,\n            \"sprites\": db.plant_sprites(id),\n            \"material\": material,\n            \"growsin\": growsin,\n            \"growseason\": [] if growseason is None else growseason.split(\"|\"),\n            \"killseason\": [] if killseason is None else killseason.split(\"|\"),\n            \"loseseason\": [] if loseseason is None else loseseason.split(\"|\"),\n            \"harvestproduces\": self.plant_produces(id, fruits_per_season),\n        }\n\n    def plants(self):\n        floors = {\"Tree\": \"grass\", \"Mushroom\": \"grass\"}\n\n        return [\n            {\n                \"type\": type,\n                \"floor\": floors.get(type, \"farm\"),\n                \"plants\": sort_translations([self.plant(*row) for row in db.plants(type)]),\n            }\n            for type in db.plant_types()\n        ]\n\n    def tints(self):\n        return [\n            {\n                \"id\": id,\n                \"r\": int(color.split(\" \")[0]),\n                \"g\": int(color.split(\" \")[1]),\n                \"b\": int(color.split(\" \")[2]),\n                \"a\": int(color.split(\" \")[3]),\n            }\n            for (id, color) in db.materials()\n        ]\n\n    def translate(self, type, id):\n        text = db.translation(f\"${type.capitalize()}Name_{id}\")\n        return id if text is None else text\n\n    def workshop_components(self, id):\n        return sort_translations(\n            [\n                {\n                    \"id\": itemid,\n                    \"translation\": self.translate(\"item\", itemid),\n                    \"spriteid\": self.item_spriteid(itemid),\n                    \"amount\": int(amount),\n                    \"workshops\": sort_translations(\n                        map(\n                            lambda w: {\"id\": w, \"translation\": self.translate(\"workshop\", w)},\n                            set(\n                                [\n                                    wid\n                                    for (craftid, amount, time, skill, _, _, _) in db.item_crafts(itemid)\n                                    for wid in db.workshops_for_craft(craftid)\n                                    if id != wid\n                                ],\n                            ),\n                        )\n                    ),\n                }\n                for (itemid, amount) in db.workshop_components(id)\n            ]\n        )\n\n    def workshop_craft(self, craft):\n        row = db.craft(craft)\n        return None if row is None else self.craft(*row)\n\n    def workshop_crafts(self, crafts):\n        if crafts is None:\n            return []\n\n        return sort_translations(\n            filter(\n                lambda c: c is not None,\n                [self.workshop_craft(craft) for craft in crafts.split(\"|\")],\n            )\n        )\n\n    def workshops(self):\n        return sort_translations(\n            [\n                {\n                    \"id\": id,\n                    \"translation\": self.translate(\"workshop\", id),\n                    \"crafts\": self.workshop_crafts(crafts),\n                    \"components\": self.workshop_components(id),\n                    \"tab\": tab,\n                }\n                for (id, crafts, tab) in db.workshops()\n            ]\n        )\n\n\nstore = Store()\n"
  },
  {
    "path": "docs/lib/themes/__init__.py",
    "content": "from .default.theme import DefaultTheme\n\nthemes = {\"default\": DefaultTheme}\n"
  },
  {
    "path": "docs/lib/themes/default/__init__.py",
    "content": ""
  },
  {
    "path": "docs/lib/themes/default/assets/doc.js",
    "content": "function setupSearch() {\n  let input = document.querySelector('input[type=\"search\"]')\n  let queryDisplay = document.querySelector('.search-query')\n  let results = document.querySelector('section.search-results')\n  let noResults = document.querySelector('.no-results')\n  let content = document.querySelector('section.content')\n\n  let entries = [\n    ...document.querySelectorAll('.search-results li[data-keywords]')\n  ].map((e) => ({\n    element: e,\n    keywords: e.getAttribute('data-keywords').toLowerCase().replace(/ /g, '')\n  }))\n\n  function search(e) {\n    let { value } = input\n\n    if (value) {\n      queryDisplay.textContent = value\n\n      let query = value.toLowerCase().replace(/ /g, '')\n      let firstMatch = null\n      let matchCount = 0\n\n      for (let { element, keywords } of entries) {\n        if (keywords.includes(query)) {\n          matchCount++\n\n          if (!firstMatch) {\n            firstMatch = element\n          }\n\n          element.style.display = 'list-item'\n        } else {\n          element.style.display = 'none'\n        }\n      }\n\n      noResults.style.display = matchCount > 0 ? 'none' : 'block'\n\n      results.style.display = 'block'\n      content.style.display = 'none'\n\n      if (firstMatch && e.keyCode === 13) {\n        firstMatch.querySelector('a').click()\n      }\n    } else {\n      results.style.display = 'none'\n      content.style.display = 'block'\n    }\n  }\n\n  input.value = ''\n  input.addEventListener('keyup', search)\n  input.addEventListener('change', search)\n}\n\nfunction setupCollapse() {\n  for (let header of document.querySelectorAll('[data-collapse]')) {\n    let group = header.getAttribute('data-collapse')\n    let trigger = document.createElement('a')\n\n    trigger.className = 'collapse-trigger'\n    trigger.href = '#'\n    trigger.setAttribute('data-collapsed', 'false')\n    trigger.textContent = '(collapse)'\n\n    trigger.addEventListener('click', (e) => {\n      e.preventDefault()\n\n      let collapsed = trigger.getAttribute('data-collapsed')\n      if (collapsed === 'true') {\n        trigger.setAttribute('data-collapsed', 'false')\n        trigger.textContent = '(collapse)'\n\n        for (let elem of document.querySelectorAll(\n          `[data-collapse-group=\"${group}\"]`\n        )) {\n          elem.style.display = 'table-row'\n        }\n      } else {\n        trigger.setAttribute('data-collapsed', 'true')\n        trigger.textContent = '(expand)'\n\n        for (let elem of document.querySelectorAll(\n          `[data-collapse-group=\"${group}\"]`\n        )) {\n          elem.style.display = 'none'\n        }\n      }\n    })\n\n    header.appendChild(trigger)\n    trigger.click()\n  }\n}\n\n;(function () {\n  setupSearch()\n  setupCollapse()\n})()\n"
  },
  {
    "path": "docs/lib/themes/default/assets/style.css",
    "content": "/* Global styles */\n\n:root {\n  --color-fade: #888;\n  --color-text: #444;\n  --color-hover: #111;\n  --color-bg: #eee;\n  --color-bg-alt: #f8f8f8;\n  --color-bg-tables: #fff;\n  --color-border: #aaa;\n\n  --layout-width: 1000px;\n  --layout-nav: 200px;\n\n  --font-size: 0.8rem;\n  --font-size-menu: calc(var(--font-size) * 1.25);\n\n  --margin-large: 1rem;\n  --margin-mid: calc(var(--margin-large) / 2);\n  --margin-small: calc(var(--margin-large) / 5);\n  --margin-tiny: calc(var(--margin-large) / 10);\n  --margin-icon: calc(3 * var(--margin-large));\n}\n\nbody {\n  margin: 0;\n\n  font-family: sans-serif;\n  font-size: var(--font-size);\n\n  color: var(--color-text);\n  background-color: var(--color-bg);\n}\n\nli {\n  list-style: square;\n}\n\na {\n  text-decoration: none;\n}\n\na:link,\na:visited,\na:active {\n  color: var(--color-text);\n  border-bottom: 1px dotted var(--color-text);\n}\n\na:hover {\n  color: var(--color-hover);\n  border-bottom: 1px solid var(--color-hover);\n}\n\na.hint,\na.hint:hover {\n  color: var(--color-text);\n  border-bottom: 1px dotted var(--color-text);\n  cursor: help;\n}\n\n/* Layout */\n\nsection.container,\ntable.nav,\nfooter {\n  margin: var(--margin-large) auto;\n  max-width: var(--layout-width);\n  width: 100%;\n}\n\nsection.container {\n  display: flex;\n  flex-flow: row nowrap;\n}\n\nnav {\n  width: var(--layout-nav);\n  margin-right: var(--margin-large);\n}\n\nsection.content,\nsection.search-results {\n  flex-grow: 1;\n}\n\nsection.search-results {\n  display: none;\n}\n\nfooter {\n  color: var(--color-fade);\n  text-align: center;\n  font-style: italic;\n}\n\n/* Navbar */\n\nnav .icon {\n  margin: var(--margin-large) var(--margin-icon);\n  max-width: calc(var(--layout-nav) - 2 * var(--margin-icon));\n  image-rendering: crisp-edges;\n  image-rendering: pixelated;\n}\n\nnav input {\n  border: 1px solid var(--color-border);\n  margin-bottom: var(--margin-large);\n  width: 100%;\n}\n\nnav ul {\n  padding: 0;\n}\n\nnav li {\n  margin: var(--margin-mid) 0;\n  list-style: none;\n  font-weight: bold;\n  font-size: var(--font-size-menu);\n\n  display: flex;\n  flex-flow: row nowrap;\n  justify-content: flex-start;\n  align-items: center;\n}\n\nnav li a {\n  margin-left: var(--margin-mid);\n}\n\nnav .l-32-56 {\n  margin-top: -20px;\n}\n\n/* Tables */\n\ntable {\n  border-spacing: 0;\n  border: 1px solid var(--color-border);\n  background-color: var(--color-bg-tables);\n}\n\ntd.number {\n  text-align: center;\n}\n\ntd {\n  padding: var(--margin-small);\n}\n\nth {\n  background-color: var(--color-bg);\n  padding: var(--margin-tiny) var(--margin-small);\n  border: var(--margin-tiny) solid var(--color-bg-tables);\n\n  text-align: center;\n}\n\n/* Navtable */\n\ntable.nav th.category,\ntable.nav th.group {\n  white-space: nowrap;\n}\n\ntable.nav th.group,\ntable.nav th.group a {\n  color: var(--color-fade);\n}\n\ntable.nav a.collapse-trigger {\n  margin-left: var(--margin-mid);\n  font-weight: normal;\n}\n\n/* Craft tables */\n\ntable.workshop-components tr:nth-child(2n + 1),\ntable.workshops tr:nth-child(2n + 1),\ntable.crafts tr:nth-child(2n + 1),\ntable.constructions tr:nth-child(2n + 1) {\n  background-color: var(--color-bg-alt);\n}\n\ntable.crafts .single td {\n  vertical-align: bottom;\n}\n\n/* Plant tables */\n\ntable.plants {\n  width: 100%;\n}\n\ntable.plants tr:nth-child(2n + 1) {\n  background-color: var(--color-bg-alt);\n}\n\ntable.plants td.seasons {\n  text-align: center;\n}\n\n.subsection {\n  margin-top: var(--margin-large);\n  font-weight: bold;\n}\n\n/* Misc */\n\nh2 .sprite {\n  float: right;\n}\n\nh2 .type {\n  font-weight: normal;\n  font-style: italic;\n  color: var(--color-fade);\n}\n\nh2 .type:after {\n  content: ': ';\n}\n\ntable.iteminfo {\n  width: 100%;\n}\n\ntable.iteminfo th {\n  white-space: nowrap;\n}\n\ntable.item-materials {\n  width: 100%;\n}\n\n.buildlist {\n  display: flex;\n  flex-flow: row;\n}\n\n.buildlist table + table {\n  margin-left: var(--margin-large);\n}\n\n.entry {\n  white-space: nowrap;\n}\n\n.workshop-sprite {\n  float: right;\n}\n\n.workshop-with-sprite {\n  display: inline-flex;\n  flex-flow: column;\n  align-items: center;\n  border-bottom: none !important;\n  margin-right: var(--margin-mid);\n}\n\na.workshop-with-sprite span.link {\n  border-bottom: 1px dotted var(--color-text);\n}\n\na.workshop-with-sprite:hover span.link {\n  border-bottom: 1px solid var(--color-hover);\n}\n"
  },
  {
    "path": "docs/lib/themes/default/sprites.py",
    "content": "from collections import defaultdict\n\nfrom ...sprites import SpriteManager, MissingMaterials, Layout\nfrom ...util import empty, log\n\n\nclass Animation:\n    anims = []\n\n    @classmethod\n    def get(cls, id, frames):\n        for anim in cls.anims:\n            if anim.has_frames(frames):\n                anim.ids.append(id)\n                return anim\n        anim = cls(id, frames)\n        cls.anims.append(anim)\n        return anim\n\n    def has_frames(self, frames):\n        return frames == self.frames\n\n    def __init__(self, id, frames):\n        self.ids = [id]\n        self.frames = frames\n\n    def id(self):\n        return f\"anim_{Animation.anims.index(self)}\"\n\n\nclass StyleRule:\n    rules = []\n\n    @classmethod\n    def set(cls, selectors, props):\n        for rule in cls.rules:\n            if rule.has_props(props):\n                rule.selectors |= set(selectors)\n                return rule\n        rule = cls(selectors, props)\n        cls.rules.append(rule)\n        return rule\n\n    def __init__(self, selectors, props={}):\n        self.selectors = set(selectors)\n        self.props = props\n\n    def has_props(self, props):\n        return props == self.props\n\n\ndef sprite_style(alt, common={}):\n    props = {}\n\n    if \"tilesheet\" not in common:\n        props[\"background-image\"] = f\"url({alt.tilesheet})\"\n\n    if \"rectx\" not in common or \"recty\" not in common:\n        props[\"background-position\"] = f\"-{alt.rect['x']}px -{alt.rect['y']}px\"\n\n    if \"rectw\" not in common:\n        props[\"width\"] = f\"{alt.rect['w']}px\"\n\n    if \"recth\" not in common:\n        props[\"height\"] = f\"{alt.rect['h']}px\"\n\n    if \"ox\" not in common and alt.ox != 0:\n        props[\"left\"] = f\"{alt.ox}px\"\n\n    if \"oy\" not in common and alt.oy != 0:\n        props[\"top\"] = f\"{alt.oy}px\"\n\n    if alt.material:\n        props[\"filter\"] = f\"url(tints.svg#{alt.material})\"\n\n    if \"effects\" not in common and len(alt.effects) > 0:\n        transforms = []\n\n        for effect in alt.effects:\n            if effect == \"Rot90\":\n                transforms.append(\"rotate(-90deg)\")\n            elif effect == \"FlipHorizontal\":\n                transforms.append(\"rotateY(180deg)\")\n\n        props[\"transform\"] = \" \".join(transforms)\n\n    return props\n\n\ndef common_style(common):\n    props = {}\n\n    if \"tilesheet\" in common:\n        props[\"background-image\"] = f\"url({common['tilesheet']})\"\n\n    if \"rectx\" in common and \"recty\" in common:\n        props[\"background-position\"] = f\"-{common['rectx']}px -{common['recty']}px\"\n\n    if \"rectw\" in common:\n        props[\"width\"] = f\"{common['rectw']}px\"\n\n    if \"recth\" in common:\n        props[\"height\"] = f\"{common['recth']}px\"\n\n    if \"ox\" in common and common[\"ox\"] != 0:\n        props[\"left\"] = f\"{common['ox']}px\"\n\n    if \"oy\" in common and common[\"oy\"] != 0:\n        props[\"top\"] = f\"{common['oy']}px\"\n\n    if \"effect\" in common and len(common[\"effects\"]) > 0:\n        transforms = []\n\n        for effect in common[\"effects\"]:\n            if effect == \"Rot90\":\n                transforms.append(\"rotate(-90deg)\")\n            elif effect == \"FlipHorizontal\":\n                transforms.append(\"rotateY(180deg)\")\n\n        props[\"transform\"] = \" \".join(transforms)\n\n    return props\n\n\nclass StyleManager:\n    item_sprites = {}\n    plant_sprites = {}\n    construction_sprites = {}\n    workshop_sprites = {}\n    menu_sprites = {}\n\n    warnings = set()\n    tilesheets = set()\n\n    select_args = {\"random\": \"all\", \"frames\": \"all\"}\n\n    floors = defaultdict(\n        lambda: {\"id\": \"SolidSelectionFloor\", \"material\": \"None\"},\n        farm={\"id\": \"TilledSoil\", \"material\": \"Dirt\"},\n        grass={\"id\": \"Grass\", \"material\": \"None\", \"season\": \"Summer\"},\n        mushroom={\"id\": \"MushroomGrass\", \"material\": \"None\"},\n        logs={\"id\": \"LogFloor\", \"material\": \"Pine\"},\n    )\n\n    menu = {\n        \"Items\": {\n            \"source\": lambda: Layout.sprite(\"Crate\"),\n            \"args\": {\"materials\": [\"Oak\"]},\n        },\n        \"Food\": {\"source\": lambda: Layout.sprite(\"ShepherdsPie\"), \"floor\": \"logs\"},\n        \"Plants\": {\n            \"source\": lambda: Layout.sprite(\"PlantLargeWithFruit\"),\n            \"args\": {\"materials\": [\"Tomato\"]},\n            \"floor\": \"farm\",\n        },\n        \"Constructions\": {\n            \"source\": lambda: Layout.construction(\"BlockStairs\"),\n            \"args\": {\"materials\": [\"Marble\"]},\n        },\n        \"Workshops\": {\n            \"source\": lambda: Layout.sprite(\"Workbench\"),\n            \"args\": {\"materials\": [\"Pine\"]},\n            \"floor\": \"grass\",\n        },\n    }\n\n    @classmethod\n    def set_floor(cls, layout, id):\n        floor = cls.floors[id]\n        layout.set_floor(\n            floor[\"id\"],\n            tint=floor[\"material\"],\n            random=\"random\",\n            season=None if \"season\" not in floor else floor[\"season\"],\n        )\n\n    @classmethod\n    def create_item_sprite(cls, item, floor=\"item\"):\n        (id, spriteid, materials) = (item[\"id\"], item[\"spriteid\"], item[\"materials\"])\n\n        layout = Layout.sprite(spriteid)\n        cls.set_floor(layout, floor)\n\n        sprite_data = {\"layout\": layout, \"materials\": {}}\n\n        try:\n            try:\n                sprite_data[\"materials\"][\"any\"] = layout.select(materials=sorted(materials), **cls.select_args)\n            except MissingMaterials as mm:\n                cls.warnings.add(mm.args[0])\n                present = [m for m in materials if m not in mm.materials]\n                sprite_data[\"materials\"][\"any\"] = layout.select(materials=sorted(present), **cls.select_args)\n        except Exception as ex:\n            cls.warnings.add(ex.args[0])\n\n        for mat in materials:\n            try:\n                sprite_data[\"materials\"][f\"M{mat}\"] = layout.select(materials=[mat], **cls.select_args)\n            except Exception as ex:\n                cls.warnings.add(ex.args[0])\n\n        cls.item_sprites[id] = sprite_data\n\n    @classmethod\n    def add_item_materialset(cls, item, matset):\n        sprite_data = cls.item_sprites[item]\n        (layout, materials) = (sprite_data[\"layout\"], sprite_data[\"materials\"])\n\n        if matset.id not in materials:\n            try:\n                try:\n                    materials[matset.id] = layout.select(materials=matset.all_materials, **cls.select_args)\n                except MissingMaterials as mm:\n                    cls.warnings.add(mm.args[0])\n                    present = [m for m in matset.all_materials if m not in mm.materials]\n                    materials[matset.id] = layout.select(materials=present, **cls.select_args)\n            except Exception as ex:\n                cls.warnings.add(ex.args[0])\n\n    @classmethod\n    def create_plant_sprite(cls, plant, floor=\"farm\"):\n        (id, sprites, material) = (plant[\"id\"], plant[\"sprites\"], plant[\"material\"])\n\n        tree_layout = set(layout for (_, layout) in sprites if not empty(layout))\n        if len(tree_layout):\n            layout = Layout.tree(tree_layout.pop(), large_floor=True)\n        else:\n            layout = Layout.sprite(SpriteManager.random(f\"plant-{id}\", [sprite for (sprite, _) in sprites]))\n\n        cls.set_floor(layout, floor)\n\n        try:\n            cls.plant_sprites[id] = {\"materials\": {\"any\": layout.select(materials=[material], **cls.select_args)}}\n        except Exception as ex:\n            cls.warnings.add(ex.args[0])\n\n    @classmethod\n    def create_construction_sprite(cls, construction, floor=\"construction\"):\n        (id, matset) = (construction[\"id\"], construction[\"material_set\"])\n\n        try:\n            layout = Layout.construction(id)\n        except Exception as ex:\n            cls.warnings.add(ex.args[0])\n            return\n\n        cls.set_floor(layout, floor)\n\n        sprite_data = {\"layout\": layout, \"materials\": {}}\n        select_args = {**cls.select_args}\n\n        if len(construction[\"components\"]) == 1:\n            select_args[\"materials\"] = matset.all_materials\n        else:\n            select_args[\"multi_materials\"] = [\n                c[\"material_set\"].all_materials for c in construction[\"components_unsorted\"]\n            ]\n\n        try:\n            try:\n                sprite_data[\"materials\"][\"any\"] = layout.select(**select_args)\n            except MissingMaterials as mm:\n                cls.warnings.add(mm.args[0])\n                select_args[\"materials\"] = sorted([m for m in select_args[\"materials\"] if m not in mm.materials])\n                sprite_data[\"materials\"][\"any\"] = layout.select(**select_args)\n        except Exception as ex:\n            cls.warnings.add(ex.args[0])\n            return\n\n        cls.construction_sprites[id] = sprite_data\n\n    @classmethod\n    def create_workshop_sprite(cls, workshop, floor=\"grass\"):\n        id = workshop[\"id\"]\n\n        try:\n            layout = Layout.workshop(id)\n        except Exception as ex:\n            cls.warnings.add(ex.args[0])\n            return\n\n        cls.set_floor(layout, floor)\n\n        try:\n            cls.workshop_sprites[id] = {\"materials\": {\"any\": layout.select(**cls.select_args)}}\n        except Exception as ex:\n            cls.warnings.add(ex.args[0])\n\n    @classmethod\n    def create_menu_sprite(cls, item):\n        id = item[\"label\"]\n        if id not in cls.menu:\n            return\n\n        sdef = cls.menu[id]\n        layout = sdef[\"source\"]()\n\n        cls.set_floor(layout, sdef.get(\"floor\", \"default\"))\n        cls.menu_sprites[id] = {\"layout\": layout, \"materials\": {\"any\": layout.select(**(sdef.get(\"args\", {})))}}\n\n    @classmethod\n    def styles(cls):\n        \"\"\"Generate style rules and keyframes, and deduplicate them\"\"\"\n\n        all_sprites = {\n            **{f\"i-{k}\": v for k, v in cls.item_sprites.items()},\n            **{f\"p-{k}\": v for k, v in cls.plant_sprites.items()},\n            **{f\"k-{k}\": v for k, v in cls.construction_sprites.items()},\n            **{f\"w-{k}\": v for k, v in cls.workshop_sprites.items()},\n            **{f\"m-{k}\": v for k, v in cls.menu_sprites.items()},\n        }\n\n        for classname, sprite_data in all_sprites.items():\n            for material, rendered in sprite_data[\"materials\"].items():\n                (bbox, cells) = (rendered[\"bbox\"], rendered[\"cells\"])\n\n                sprite_data[\"rule\"] = StyleRule.set(\n                    [f\".l-{bbox['width']}-{bbox['height']}\"],\n                    {\"width\": f\"{bbox['width']}px\", \"height\": f\"{bbox['height']}px\"},\n                )\n\n                StyleRule.set(\n                    [f\".l-{bbox['width']}-{bbox['height']}.zoomed\"],\n                    {\"width\": f\"{bbox['width'] * 2}px\", \"height\": f\"{bbox['height'] * 2}px\"},\n                )\n\n                for cell in cells:\n                    (x, y, z) = (cell[\"pos\"][\"x\"], cell[\"pos\"][\"y\"], cell[\"pos\"][\"z\"])\n                    (left, top) = (\n                        cell[\"projected\"][\"x\"] - bbox[\"minx\"],\n                        cell[\"projected\"][\"y\"] - bbox[\"miny\"],\n                    )\n\n                    StyleRule.set(\n                        [f\".l-{bbox['width']}-{bbox['height']} .cp-{x}-{y}-{z}\"],\n                        {\"left\": f\"{left}px\", \"top\": f\"{top}px\", \"--minx\": bbox[\"minx\"], \"--miny\": bbox[\"miny\"]},\n                    )\n\n                    cell_number = cells.index(cell) + 1\n                    layers = cell[\"layers\"].layers\n\n                    for layer in layers:\n                        alternatives = layer.unique(use_color=True)\n                        alt_count = len(alternatives)\n\n                        layer_number = layers.index(layer) + 1\n                        layer_selectors = [f\".{classname}.m-{material} .cn-{cell_number} .y-{layer_number}\"]\n\n                        for alt in alternatives:\n                            cls.tilesheets.add(alt.tilesheet)\n\n                        if alt_count > 1:\n                            common = layer.common()\n                            anim = Animation.get(\n                                f\"{classname}-{material}-{cell_number}-{layer_number}\",\n                                [sprite_style(alt, common) for alt in alternatives],\n                            )\n\n                            duration = sum([1 / alt.anim_length for alt in alternatives])\n                            StyleRule.set(\n                                layer_selectors,\n                                {\n                                    \"animation\": f\"{duration}s infinite step-end\",\n                                    \"animation-name\": anim,\n                                    **common_style(common),\n                                },\n                            )\n                        elif alt_count == 1:\n                            StyleRule.set(layer_selectors, sprite_style(alternatives[0]))\n\n        return (Animation.anims, StyleRule.rules)\n"
  },
  {
    "path": "docs/lib/themes/default/templates/base.html.j2",
    "content": "<!DOCTYPE html>\n{% import \"macros.html.j2\" as macros with context %}\n<head>\n  <title>{% block title %}Ingnomia docs{% endblock %}</title>\n\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"{{ base }}assets/style.css\" />\n  <link rel=\"stylesheet\" type=\"text/css\" href=\"{{ base }}assets/sprites.css\" />\n  <link rel=\"shortcut icon\" href=\"{{ base }}assets/icon.png\" />\n</head>\n<body>\n  <section class=\"container\">\n    <nav>\n      <a href=\"{{ base }}index.html\">\n        <img class=\"icon\" src=\"{{ base }}assets/icon.png\">\n      </a>\n\n      <input type=\"search\" placeholder=\"Quick search...\">\n\n      <ul>\n        {% for item in menu %}\n          <li>\n            {{ macros.menusprite(item.label) }}\n            <a href=\"{{ base }}{{ item.href }}\">{{ item.label }}</a>\n          </li>\n        {% endfor %}\n      </ul>\n    </nav>\n\n    <section class=\"content\">\n      {% block content %}{% endblock %}\n    </section>\n\n    <section class=\"search-results\">\n      <h2>Search results for \"<span class=\"search-query\"></span>\"</h2>\n\n      <span class=\"no-results\">No results :(</span>\n\n      <ul>\n        {% for item in index %}\n          <li data-keywords=\"{{ item.kw }}\"><a href=\"{{ base }}{{ item.href }}\">{{ item.type|title }}: {{ item.label|title }}</a></li>\n        {% endfor %}\n      </ul>\n    </section>\n  </section>\n\n  {{ navtable_rendered }}\n\n  <footer>\n    <div>\n      Generated on {{ build.date }} UTC\n      {% if build.id %}from version {{ build.id }}{% endif %}\n    </div>\n  </footer>\n\n  <script src=\"{{ base }}assets/doc.js\"></script>\n</body>\n"
  },
  {
    "path": "docs/lib/themes/default/templates/constructions.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n{% block title %}\n  All Constructions - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <h2>All Constructions</h2>\n\n  {{ macros.constrlist(constructions) }}\n{% endblock %}"
  },
  {
    "path": "docs/lib/themes/default/templates/food.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n\n{% macro food_table(data, value_label, value_attr) %}\n  <table class=\"food\">\n    <tr>\n      <th colspan=\"2\">Items</th>\n      <th>{{ value_label }}</th>\n    </tr>\n    {% for category in data %}\n      {% for group in category.groups %}\n        {% for item in group[\"items\"] %}\n          <tr>\n            {% if loop.index == 1 %}\n              <th class=\"category\" rowspan=\"{{ loop.length }}\">\n                {{ group.translation|title }}\n              </th>\n            {% endif %}\n\n            <td>\n              {% if item.spriteid %}\n                {{ macros.itemsprite(item.id) }}\n              {% endif %}\n              <a href=\"{{ base }}item/{{ item.id }}.html\">{{ item.translation|title }}</a>\n            </td>\n\n            <td class=\"number\">\n              {{ item[value_attr] }}\n            </td>\n          </tr>\n        {% endfor %}\n      {% endfor %}\n    {% endfor %}\n  </table>\n{% endmacro %}\n\n{% block title %}\n  All Food & Drinks - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <h2>All Food & Drinks</h2>\n\n  <h3>Food</h3>\n\n  {{ food_table(data=food, value_label=\"Eat value\", value_attr=\"eatvalue\") }}\n\n  <h3>Drinks</h3>\n\n  {{ food_table(data=drinks, value_label=\"Drink value\", value_attr=\"drinkvalue\") }}\n{% endblock %}"
  },
  {
    "path": "docs/lib/themes/default/templates/index.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n\n{% block content %}\n  <h2>Auto-generated documentation for Ingnomia</h2>\n\n  Use the menu, the table below or the search box to navigate.\n{% endblock %}\n"
  },
  {
    "path": "docs/lib/themes/default/templates/item.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n{% block title %}\n  {{ item.translation|title }} - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <h2>\n    <span class=\"type\">Item</span>\n    {{ item.translation|title }}\n  </h2>\n\n  <table class=\"iteminfo\">\n    <tr>\n      <th>Category</th>\n      <td>{{ item.category.translation|title }}</td>\n      <td rowspan=\"0\">\n        {{ macros.itemsprite(item.id, zoom=True) }}\n      </td>\n    </tr>\n    <tr>\n      <th>Group</th>\n      <td>{{ item.group.translation|title }}</td>\n    </tr>\n    <tr>\n      <th>Storage</th>\n      <td>\n        {% if item.stack %}\n          <div>\n            {% if item.stack == 1 %}\n              Does not stack\n            {% else %}\n              Stacks by {{ item.stack }}\n            {% endif %}\n\n            on the ground\n          </div>\n        {% endif %}\n        {% if item.container %}\n          <div>{{ macros.item(item.container) }} <i>(max. {{ item.container.capacity }}, in stockpiles)</i></div>\n        {% endif %}\n        {% if item.carry %}\n          <div>{{ macros.item(item.carry) }} <i>(max. {{ item.carry.capacity }}, for carrying)</i></div>\n        {% endif %}\n      </td>\n    </tr>\n    {% if item.capacity %}\n      <tr>\n        <th>Capacity</th>\n        <td>{{ item.capacity }} {% if item.same %}identical{% else %}varied{% endif %} items</td>\n      </tr>\n    {% endif %}\n    <tr>\n      <th>Value</th>\n      <td>{{ item.value }}</td>\n    </tr>\n    {% if item.evalue %}\n      <tr>\n        <th>Eat value</th>\n        <td>{{ item.evalue }}</td>\n      </tr>\n    {% endif %}\n    {% if item.dvalue %}\n      <tr>\n        <th>Drink value</th>\n        <td>{{ item.dvalue }}</td>\n      </tr>\n    {% endif %}\n    {% if item.light %}\n      <tr>\n        <th>Light intensity</th>\n        <td>{{ item.light }}</td>\n      </tr>\n    {% endif %}\n  </table>\n\n  {% if item.materials|length %}\n    <h3>Materials</h3>\n\n    <table class=\"item-materials\">\n      {% for type in item.material_tree %}\n        <tr>\n          <th>{{ type.id }}</th>\n          <td>\n            {% for mat in type.materials %}\n              <span class=\"entry\">\n                {{ macros.itemsprite(item.id, matset=\"M\" ~ mat.id) }}\n                {{ mat.translation|title }}\n                {% if not loop.last %}\n                  &bull;\n                {% endif %}\n              </span>\n            {% endfor %}\n          </td>\n        </tr>\n      {% endfor %}\n    </table>\n  {% endif %}\n\n  {% if item.crafts|length %}\n    <h3>Crafting recipes</h3>\n\n    {{ macros.craftlist(item.crafts) }}\n  {% endif %}\n\n  {% if item.constructions|length %}\n    <h3>Construction recipes</h3>\n\n    {{ macros.constrlist(item.constructions) }}\n  {% endif %}\n\n  {% if item.rcrafts|length %}\n    <h3>Used to craft</h3>\n\n    {{ macros.craftlist(item.rcrafts) }}\n  {% endif %}\n\n  {% if item.wcrafts|length or item.rconstructions|length %}\n    <h3>Used to build</h3>\n\n    <div class=\"buildlist\">\n      {% if item.rconstructions|length %}\n        {{ macros.constrlist(item.rconstructions) }}\n      {% endif %}\n\n      {% if item.wcrafts|length %}\n        <table class=\"workshops\">\n          <tr>\n            <th>Workshop</th>\n          </tr>\n\n          {% for workshop in item.wcrafts %}\n            <tr>\n              <td>\n                <a href=\"{{ base }}workshop/{{ workshop.id }}.html\">{{ workshop.translation|title }}</a>\n              </td>\n            </tr>\n          {% endfor %}\n        </table>\n      {% endif %}\n    </div>\n  {% endif %}\n\n  {% if item.can_contain %}\n    <h3>Allowed items in container</h3>\n\n    {{ macros.nav_table(custom_data=item.can_contain, custom_path=\"item\", class=\"\") }}\n  {% endif %}\n{% endblock %}\n"
  },
  {
    "path": "docs/lib/themes/default/templates/items.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n{% block title %}\n  All Items - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <h2>All Items</h2>\n\n  {{ macros.nav_table(only_section=\"Items\", class=\"\") }}\n{% endblock %}"
  },
  {
    "path": "docs/lib/themes/default/templates/macros.html.j2",
    "content": "{% macro spritelayout(rendered, type, id, matset='any', zoom=False) %}\n  <span class=\"\n    layout\n    l-{{ rendered.bbox.width }}-{{ rendered.bbox.height }}\n    {{ type }}-{{ id }}\n    m-{{ matset }}\n    {% if zoom %}zoomed{% endif %}\">\n    <span class=\"cells\">\n      {% for cell in rendered.cells %}\n        <span class=\"\n          cell\n          cp-{{ cell.pos.x }}-{{ cell.pos.y }}-{{ cell.pos.z }}\n          cn-{{ loop.index }}\">\n          {% for layer in cell.layers.layers %}\n            <span class=\"layer y-{{ loop.index }}\"></span>\n          {% endfor %}\n        </span>\n      {% endfor %}\n    </span>\n  </span>\n{% endmacro %}\n\n{% macro itemsprite(id, matset='any', zoom=False) %}\n  {% if sm.item_sprites[id] and sm.item_sprites[id].materials[matset] %}\n    {{ spritelayout(sm.item_sprites[id].materials[matset], 'i', id, matset, zoom) }}\n  {% endif %}\n{% endmacro %}\n\n{% macro plantsprite(id) %}\n  {% if sm.plant_sprites[id] %}\n    {{ spritelayout(sm.plant_sprites[id].materials.any, 'p', id, 'any') }}\n  {% endif %}\n{% endmacro %}\n\n{% macro constrsprite(id) %}\n  {% if sm.construction_sprites[id] %}\n    {{ spritelayout(sm.construction_sprites[id].materials.any, 'k', id, 'any') }}\n  {% endif %}\n{% endmacro %}\n\n{% macro workshopsprite(id, zoom=False) %}\n  {% if sm.workshop_sprites[id] %}\n    {{ spritelayout(sm.workshop_sprites[id].materials.any, 'w', id, 'any', zoom) }}\n  {% endif %}\n{% endmacro %}\n\n{% macro menusprite(id) %}\n  {% if sm.menu_sprites[id] %}\n    {{ spritelayout(sm.menu_sprites[id].materials.any, 'm', id, 'any') }}\n  {% endif %}\n{% endmacro %}\n\n{% macro item(i) %}\n  {% if i.material_set %}\n    {% set matset = i.material_set.id %}\n  {% else %}\n    {% set matset = \"any\" %}\n  {% endif %}\n\n  {{ itemsprite(i.id, matset=matset) }}\n  <a href=\"{{ base }}item/{{ i.id }}.html\">\n    {{ i.translation|title }}{% if i.material_set and i.material_set.labels|length and not i.material_set.covers(i.id) %}\n      ({{ i.material_set.labels|map(\"title\")|join('/') }})\n    {% endif %}</a>\n{% endmacro %}\n\n{% macro itemamount(i) %}\n  {% if i.amount == 0 %}\n    <i>destroyed</i>\n  {% else %}\n    {% if i.amount_hint %}\n      <a class=\"hint\" title=\"{{ i.amount_hint }}\">{{ i.amount }}x</a>\n    {% else %}\n      {{ i.amount }}x\n    {% endif %}\n\n    {{ item(i) }}\n  {% endif %}\n{% endmacro %}\n\n{% macro workshop(w) %}\n  <a href=\"{{ base }}workshop/{{ w.id }}.html\">{{ w.translation|title }}</a>\n{% endmacro %}\n\n{% macro craftlist(crafts, show_workshop=true) %}\n  <table class=\"crafts\">\n    <tr>\n      <th>Output</th>\n      <th>Components</th>\n      {% if show_workshop %}<th>Workshop</th>{% endif %}\n      <th>Time</th>\n      <th>Skill</th>\n    </tr>\n\n    {% for craft in crafts %}\n      <tr {% if craft.components|length == 1 %}class=\"single\"{% endif %}>\n        <td>{{ itemamount(craft) }}</td>\n        <td>\n          {% for component in craft.components %}\n            <div>{{ itemamount(component) }}</div>\n          {% endfor %}\n        </td>\n        {% if show_workshop %}\n          <td>\n            {% for w in craft.workshops %}\n              <div>{{ workshop(w) }}</div>\n            {% endfor %}\n          </td>\n        {% endif %}\n        <td class=\"number\">{{ craft.time }}</td>\n        <td>{{ craft.skill|title }}</td>\n      </tr>\n    {% endfor %}\n  </table>\n{% endmacro %}\n\n{% macro constrlist(constructions) %}\n  <table class=\"constructions\">\n    <tr>\n      <th>Category</th>\n      <th>Construction</th>\n      <th>Components</th>\n    </tr>\n\n    {% for cat in constructions %}\n      {% for construction in cat.constructions %}\n        <tr>\n          {% if loop.index == 1 %}\n            <th rowspan=\"{{ loop.length }}\">{{ cat.category }}</th>\n          {% endif %}\n\n          <td>\n            {{ macros.constrsprite(construction.id) }}\n            {{ construction.translation|title }}</td>\n          <td>\n            {% for component in construction.components %}\n              <div>{{ macros.itemamount(component) }}</div>\n            {% endfor %}\n          </td>\n        </tr>\n      {% endfor %}\n    {% endfor %}\n  </table>\n{% endmacro %}\n\n{% macro nav_table(only_section=None, class=\"nav\", custom_data=None, custom_path=None, workshop_sprites=False) %}\n  <table class=\"{{ class }}\">\n    {% if not custom_data %}\n      {% set data = navtable %}\n    {% else %}\n      {% set only_section = \"custom\" %}\n      {% set data = [{\"label\":\"custom\", \"path\": custom_path, \"categories\": custom_data}] %}\n    {% endif %}\n\n    {% for section in data %}\n      {% if not only_section or only_section == section.label %}\n        {% if not only_section %}\n          <tr>\n            <th colspan=\"3\" class=\"section\" data-collapse=\"{{ section.label }}\">{{ section.label }}</th>\n          </tr>\n        {% endif %}\n\n        {% for category in section.categories %}\n          {% for group in category.groups %}\n            <tr {% if not only_section %}data-collapse-group=\"{{ section.label }}\"{% endif %}>\n              {% if loop.index == 1 %}\n                <th class=\"category\" rowspan=\"{{ loop.length }}\">\n                  {{ category.translation|title }}\n                </th>\n              {% endif %}\n\n              {% if not group.hide %}\n                <th class=\"group\">\n                  {{ group.translation|title }}\n                </th>\n              {% endif %}\n\n              <td colspan=\"{% if group.hide %}2{% else %}1{% endif %}\">\n                {% for item in group['items'] %}\n                  <span class=\"entry\">\n                    {% if workshop_sprites and section.path == 'workshop' %}\n                      <a class=\"workshop-with-sprite\" href=\"{{ base }}{{ section.path }}/{{ item.id }}.html\">\n                        {{ workshopsprite(item.id) }}\n                        <span class=\"link\">{{ item.translation|title }}</span>\n                      </a>\n                    {% else %}\n                      {% if section.path == 'item' and item.spriteid %}\n                        {{ itemsprite(item.id) }}\n                      {% endif %}\n\n                      <a href=\"{{ base }}{{ section.path }}/{{ item.id }}.html\">{{ item.translation|title }}</a>\n\n                      {% if not loop.last %}\n                        &bull;\n                      {% endif %}\n                    {% endif %}\n                  </span>\n                {% endfor %}\n              </td>\n            </tr>\n          {% endfor %}\n        {% endfor %}\n      {% endif %}\n    {% endfor %}\n  </table>\n{% endmacro %}"
  },
  {
    "path": "docs/lib/themes/default/templates/navtable.html.j2",
    "content": "{% import \"macros.html.j2\" as macros with context %}\n{{ macros.nav_table() }}\n"
  },
  {
    "path": "docs/lib/themes/default/templates/plants.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n{% block title %}\n  All Plants - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <h2>All Plants</h2>\n\n  <table class=\"plants\">\n    {% for type in plants %}\n      <tr>\n        <th colspan=\"2\" rowspan=\"2\">{{ type.type }}</th>\n        <th colspan=\"3\">Seasons</th>\n        <th rowspan=\"2\">Harvest yield</th>\n      </tr>\n      <tr>\n        <th>Grows</th>\n        <th>Dies</th>\n        <th>Loses fruit</th>\n      </tr>\n\n      {% for plant in type.plants %}\n        <tr>\n          <td>\n            {{ plant.id|title }}\n          </td>\n          <td>\n            {{ macros.plantsprite(plant.id) }}\n          </td>\n          <td class=\"seasons\">\n            {% for season in plant.growseason %}\n              <div>{{ season }}</div>\n            {% endfor %}\n          </td>\n          <td class=\"seasons\">\n            {% for season in plant.killseason %}\n            <div>{{ season }}</div>\n            {% endfor %}\n          </td>\n          <td class=\"seasons\">\n            {% for season in plant.loseseason %}\n              <div>{{ season }}</div>\n            {% endfor %}\n          </td>\n          <td>\n            {% for produce in plant.harvestproduces if produce.type == \"harvest\" %}\n              <div>{{ macros.itemamount(produce) }}</div>\n            {% endfor %}\n\n            {% for produce in plant.harvestproduces if produce.type == \"fell\" %}\n              {% if loop.index == 1 %}\n                <div class=\"subsection\">When felling:</div>\n              {% endif %}\n              <div>{{ macros.itemamount(produce) }}</div>\n            {% endfor %}\n          </td>\n        </tr>\n      {% endfor %}\n    {% endfor %}\n  </table>\n{% endblock %}"
  },
  {
    "path": "docs/lib/themes/default/templates/sprites.css.j2",
    "content": ".zoomed .cells {\n  position: absolute;\n  transform: translate(-50%, -50%) scale(2, 2) translate(50%, 50%);\n}\n\n.layout {\n  display: inline-block;\n  position: relative;\n  image-rendering: crisp-edges;\n  image-rendering: pixelated;\n  vertical-align: text-bottom;\n}\n\n.cell, .layer {\n  display: block;\n  position: absolute;\n}\n\n{% for anim in sprite_anims %}\n  @keyframes {{ anim.id() }} {\n    {% for frame in anim.frames %}\n      {{ (100 * loop.index0 / loop.length) | round(2) }}% {\n        {% for prop, value in frame.items() %}\n          {{ prop }}: {{ value }};\n        {% endfor %}\n      }\n    {% endfor %}\n  }\n{% endfor %}\n\n{% for rule in sprite_rules %}\n  {% for selector in rule.selectors|sort %}\n    {{ selector }}{% if not loop.last %},{% endif %}\n  {% endfor %}\n  {\n    {% for prop, value in rule.props.items() %}\n      {% if prop == \"animation\" %}\n        animation: {{ rule.props[\"animation-name\"].id() }} {{ value }};\n      {% elif prop != \"animation-name\" %}\n        {{ prop }}: {{ value }};\n      {% endif %}\n    {% endfor %}\n  }\n{% endfor %}\n"
  },
  {
    "path": "docs/lib/themes/default/templates/tints.svg.j2",
    "content": "<svg xmlns=\"http://www.w3.org/2000/svg\">\n  {% for tint in tints %}\n    <filter id=\"{{ tint.id }}\" color-interpolation-filters=\"sRGB\" filterUnits=\"objectBoundingBox\" x=\"0%\" y=\"0%\" width=\"100%\" height=\"100%\">\n      <feColorMatrix\n        values=\"{{ tint.r / 255 }} 0 0 0 0\n                0 {{ tint.g / 255 }} 0 0 0\n                0 0 {{ tint.b / 255 }} 0 0\n                0 0 0 {{ tint.a / 255 }} 0\" />\n    </filter>\n  {% endfor %}\n</svg>\n"
  },
  {
    "path": "docs/lib/themes/default/templates/workshop.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n{% block title %}\n  {{ workshop.translation|title }} - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <span class=\"workshop-sprite\">{{ macros.workshopsprite(workshop.id, zoom=True) }}</span>\n\n  <h2>\n    <span class=\"type\">{{ workshop.tab|title }} workshop</span>\n    {{ workshop.translation|title }}\n  </h2>\n\n  <h3>Building components</h3>\n\n  <table class=\"workshop-components\">\n    <tr>\n      <th>Item</th>\n      <th>Requires workshop</th>\n    </tr>\n    {% for item in workshop.components %}\n      <tr>\n        <td>\n          {{ macros.itemamount(item) }}\n        </td>\n        <td>\n          {% if item.workshops|length %}\n            {% for w in item.workshops %}\n              <div>{{ macros.workshop(w) }}</div>\n            {% endfor %}\n          {% else %}\n            <i>(raw material)</i>\n          {% endif %}\n        </td>\n      </tr>\n    {% endfor %}\n  </table>\n\n  {% if workshop.crafts|length %}\n    <h3>Used to craft</h3>\n\n    {{ macros.craftlist(workshop.crafts, show_workshop=false) }}\n  {% endif %}\n{% endblock %}"
  },
  {
    "path": "docs/lib/themes/default/templates/workshops.html.j2",
    "content": "{% extends \"base.html.j2\" %}\n{% import \"macros.html.j2\" as macros with context %}\n\n{% block title %}\n  All Workshops - {{ super() }}\n{% endblock %}\n\n{% block content %}\n  <h2>All Workshops</h2>\n\n  {{ macros.nav_table(only_section=\"Workshops\", class=\"\", workshop_sprites=True) }}\n{% endblock %}"
  },
  {
    "path": "docs/lib/themes/default/theme.py",
    "content": "from datetime import datetime\nimport os\nimport shutil\nfrom jinja2 import Environment, FileSystemLoader\n\nfrom ...store import store\nfrom ...util import DOCDIR, log, sort_translations, format_css\nfrom .sprites import StyleManager\n\nTHEME_PATH = os.path.dirname(__file__)\nASSET_PATH = os.path.join(THEME_PATH, \"assets\")\nTEMPLATE_PATH = os.path.join(THEME_PATH, \"templates\")\nCONTENT_PATH = os.path.realpath(os.path.join(DOCDIR, \"..\", \"content\"))\n\n\nclass DefaultTheme:\n    content_assets = [\"icon.png\"]\n    assets = []\n\n    def __init__(self):\n        self.assets = os.listdir(ASSET_PATH)\n        self.env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))\n\n    def render(self, output, build_id):\n        # Setup directories\n        shutil.rmtree(output, ignore_errors=True)\n\n        for subdir in [\"assets\", \"workshop\", \"item\"]:\n            os.makedirs(os.path.join(output, subdir))\n\n        log(\"Gathering data\")\n\n        categories = store.categories()\n        items = store.items()\n        food = store.food()\n        drinks = store.drinks()\n        plants = store.plants()\n        tints = store.tints()\n        workshops = store.workshops()\n        constructions = store.constructions()\n\n        menu = [\n            {\"label\": \"Items\", \"href\": \"items.html\"},\n            {\"label\": \"Food\", \"href\": \"food.html\"},\n            {\"label\": \"Plants\", \"href\": \"plants.html\"},\n            {\"label\": \"Constructions\", \"href\": \"constructions.html\"},\n            {\"label\": \"Workshops\", \"href\": \"workshops.html\"},\n        ]\n\n        navtable = [\n            {\"label\": \"Items\", \"categories\": categories, \"path\": \"item\"},\n            {\n                \"label\": \"Workshops\",\n                \"categories\": sort_translations(\n                    [\n                        {\n                            \"translation\": g,\n                            \"groups\": [{\"hide\": True, \"items\": list(filter(lambda w: w[\"tab\"] == g, workshops))}],\n                        }\n                        for g in set(map(lambda w: w[\"tab\"], workshops))\n                    ]\n                ),\n                \"path\": \"workshop\",\n            },\n        ]\n\n        search_index = [\n            *[\n                {\n                    \"label\": i[\"translation\"],\n                    \"href\": f\"item/{i['id']}.html\",\n                    \"type\": \"item\",\n                    \"kw\": (\n                        f\"{i['id']} {i['translation']} \"\n                        f\"{i['category']['id']} {i['category']['translation']} \"\n                        f\"{i['group']['id']} {i['group']['translation']}\"\n                    ),\n                }\n                for i in items\n            ],\n            *[\n                {\n                    \"label\": w[\"translation\"],\n                    \"href\": f\"workshop/{w['id']}.html\",\n                    \"type\": \"workshop\",\n                    \"kw\": f\"{w['id']} {w['translation']}\",\n                }\n                for w in workshops\n            ],\n        ]\n\n        log(\"Building sprites\")\n\n        for item in items:\n            StyleManager.create_item_sprite(item)\n\n        for item in items:\n            for craft in [*item[\"crafts\"], *item[\"rcrafts\"]]:\n                if craft[\"id\"]:\n                    StyleManager.add_item_materialset(craft[\"id\"], craft[\"material_set\"])\n                for component in craft[\"components\"]:\n                    StyleManager.add_item_materialset(component[\"id\"], component[\"material_set\"])\n\n        for cat in constructions:\n            for constr in cat[\"constructions\"]:\n                StyleManager.create_construction_sprite(constr)\n                for component in constr[\"components\"]:\n                    StyleManager.add_item_materialset(component[\"id\"], component[\"material_set\"])\n\n        for workshop in workshops:\n            StyleManager.create_workshop_sprite(workshop)\n\n        for type in plants:\n            if type[\"type\"] == \"Plant\":\n                floor = \"farm\"\n            elif type[\"type\"] == \"Tree\":\n                floor = \"grass\"\n            elif type[\"type\"] == \"Mushroom\":\n                floor = \"mushroom\"\n\n            for plant in type[\"plants\"]:\n                StyleManager.create_plant_sprite(plant, floor=floor)\n\n        for item in menu:\n            StyleManager.create_menu_sprite(item)\n\n        for w in sorted(StyleManager.warnings):\n            log(w, \"! \")\n\n        (sprite_anims, sprite_rules) = StyleManager.styles()\n\n        log(\"Rendering\")\n\n        global_context = {\n            \"menu\": menu,\n            \"navtable\": navtable,\n            \"index\": search_index,\n            \"build\": {\"id\": build_id, \"date\": datetime.utcnow().isoformat(\" \", timespec=\"minutes\")},\n            \"sm\": StyleManager,\n        }\n\n        # Prerender navtable\n        navtable_rendered_root = self.env.get_template(\"navtable.html.j2\").render(**global_context)\n        navtable_rendered_nest = self.env.get_template(\"navtable.html.j2\").render(base=\"../\", **global_context)\n\n        # Generate sprites css\n        with open(os.path.join(output, \"assets\", \"sprites.css\"), mode=\"w\") as f:\n            f.write(\n                format_css(\n                    self.env.get_template(\"sprites.css.j2\").render(\n                        tints=tints, sprite_anims=sprite_anims, sprite_rules=sprite_rules\n                    )\n                )\n            )\n\n        # Generate tint filters\n        with open(os.path.join(output, \"assets\", \"tints.svg\"), mode=\"w\") as f:\n            f.write(self.env.get_template(\"tints.svg.j2\").render(tints=tints))\n\n        # Generate item index\n        with open(os.path.join(output, \"items.html\"), mode=\"w\") as f:\n            f.write(\n                self.env.get_template(\"items.html.j2\").render(\n                    base=\"\", navtable_rendered=navtable_rendered_root, **global_context\n                )\n            )\n\n        # Generate item pages\n        for item in items:\n            with open(os.path.join(output, \"item\", f\"{item['id']}.html\"), mode=\"w\") as f:\n                f.write(\n                    self.env.get_template(\"item.html.j2\").render(\n                        item=item, base=\"../\", navtable_rendered=navtable_rendered_nest, **global_context\n                    )\n                )\n\n        # Generate food index\n        with open(os.path.join(output, \"food.html\"), mode=\"w\") as f:\n            f.write(\n                self.env.get_template(\"food.html.j2\").render(\n                    base=\"\", navtable_rendered=navtable_rendered_root, food=food, drinks=drinks, **global_context\n                )\n            )\n\n        # Generate plant index\n        with open(os.path.join(output, \"plants.html\"), mode=\"w\") as f:\n            f.write(\n                self.env.get_template(\"plants.html.j2\").render(\n                    base=\"\", navtable_rendered=navtable_rendered_root, plants=plants, **global_context\n                )\n            )\n\n        # Generate workshop index\n        with open(os.path.join(output, \"workshops.html\"), mode=\"w\") as f:\n            f.write(\n                self.env.get_template(\"workshops.html.j2\").render(\n                    base=\"\", navtable_rendered=navtable_rendered_root, **global_context\n                )\n            )\n\n        # Generate workshop pages\n        for workshop in workshops:\n            with open(os.path.join(output, \"workshop\", f\"{workshop['id']}.html\"), mode=\"w\") as f:\n                f.write(\n                    self.env.get_template(\"workshop.html.j2\").render(\n                        workshop=workshop, base=\"../\", navtable_rendered=navtable_rendered_nest, **global_context\n                    )\n                )\n\n        # Generate construction index\n        with open(os.path.join(output, \"constructions.html\"), mode=\"w\") as f:\n            f.write(\n                self.env.get_template(\"constructions.html.j2\").render(\n                    base=\"\", navtable_rendered=navtable_rendered_root, constructions=constructions, **global_context\n                )\n            )\n\n        # Generate index\n        with open(os.path.join(output, \"index.html\"), mode=\"w\") as f:\n            f.write(\n                self.env.get_template(\"index.html.j2\").render(\n                    base=\"\", navtable_rendered=navtable_rendered_root, **global_context\n                )\n            )\n\n        # Copy assets\n        for asset in self.content_assets:\n            shutil.copy(os.path.join(CONTENT_PATH, asset), os.path.join(output, \"assets\", asset))\n        for asset in self.assets:\n            shutil.copy(os.path.join(ASSET_PATH, asset), os.path.join(output, \"assets\", asset))\n        for asset in StyleManager.tilesheets:\n            shutil.copy(os.path.join(CONTENT_PATH, \"tilesheet\", asset), os.path.join(output, \"assets\", asset))\n"
  },
  {
    "path": "docs/lib/util.py",
    "content": "import os\n\nDOCDIR = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))\n\n\ndef empty(value):\n    return value is None or value == \"\"\n\n\ndef sprite_rect(rect):\n    (x, y, w, h) = map(int, rect.split(\" \"))\n    return {\"x\": x, \"y\": y, \"w\": w, \"h\": h}\n\n\ndef sprite_offset(offset):\n    (x, y) = (0, 0) if empty(offset) else map(int, offset.replace(\",\", \"\").strip().split(\" \"))\n    return {\"x\": x, \"y\": y}\n\n\ndef sprite_offset3d(offset):\n    (x, y, z) = (0, 0, 0) if empty(offset) else map(int, offset.strip().split(\" \"))\n    return {\"x\": x, \"y\": y, \"z\": z}\n\n\ndef sprite_layers(sprite):\n    return sprite\n\n\ndef sort_translations(lst):\n    return sorted(lst, key=lambda item: item[\"translation\"] if \"translation\" in item else item[\"id\"])\n\n\ndef total_amount(chance):\n    return sum(map(lambda x: 1 if float(x) == 0 else float(x), chance.split(\"|\")))\n\n\ndef amount_hint(chance):\n    chances = list(map(float, chance.split(\"|\")))\n    guaranteed = len(list(filter(lambda x: x == 0, chances)))\n    optional = filter(lambda x: x > 0, chances)\n\n    if guaranteed == len(chances):\n        return None\n\n    return \", \".join([f\"{guaranteed} guaranteed\", *map(lambda c: f\"{int(c*100)}% chance to get 1 more\", optional)])\n\n\ndef format_css(css):\n    \"\"\"Trivial formatter to make reading output easier\"\"\"\n    lines = []\n    level = 0\n\n    for line in css.splitlines():\n        line = line.strip()\n        if len(line):\n            if \"{\" in line:\n                lines.append(f\"{'  ' * level}{line}\")\n                level = level + 1\n            elif \"}\" in line:\n                level = level - 1\n                lines.append(f\"{'  ' * level}{line}\")\n            else:\n                lines.append(f\"{'  ' * level}{line}\")\n\n    return \"\\n\".join(lines)\n\n\ndef log(msg, prefix=\"* \"):\n    print(f\"{prefix}{msg}\")\n"
  },
  {
    "path": "gui/SampleData/GameModelSampleData.xaml",
    "content": "﻿<IngnomiaGUI:GameModel xmlns:IngnomiaGUI=\"clr-namespace:IngnomiaGUI\"\n                       Day=\"Cras nam aenean class\"\n                       FastSpeed=\"True\"\n                       NormalSpeed=\"False\"\n                       Paused=\"True\"\n                       ShowCategoryButtons=\"Visible\"\n                       ShowCommandButtons=\"Visible\"\n                       Sun=\"Integer curae\"\n                       Time=\"Vestibulum amet curabitur aliquam\"\n                       Year=\"Duis nunc maecenas sed praesent\"\n                       >\n    <IngnomiaGUI:GameModel.CommandButtons>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n        <IngnomiaGUI:CommandButton Name=\"Foo\"/>\n    </IngnomiaGUI:GameModel.CommandButtons>\n    <IngnomiaGUI:GameModel.BuildButtons>\n        <IngnomiaGUI:BuildButton Name=\"Foo\"/>\n        <IngnomiaGUI:BuildButton Name=\"Bar\"/>\n        <IngnomiaGUI:BuildButton Name=\"Foo\"/>\n        <IngnomiaGUI:BuildButton Name=\"Bar\"/>\n        <IngnomiaGUI:BuildButton Name=\"Foo\"/>\n        <IngnomiaGUI:BuildButton Name=\"Bar\"/>\n    </IngnomiaGUI:GameModel.BuildButtons>\n    <IngnomiaGUI:GameModel.BuildItems>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n        <IngnomiaGUI:BuildItem Name=\"Foo\">\n            <IngnomiaGUI:BuildItem.RequiredItems>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\">\n                    <IngnomiaGUI:RequiredItem.Materials>\n                        <IngnomiaGUI:AvailableMaterial Name=\"Foo\" Amount=\"1\"></IngnomiaGUI:AvailableMaterial>\n                    </IngnomiaGUI:RequiredItem.Materials>\n                </IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n                <IngnomiaGUI:RequiredItem Name=\"Wood\" Amount=\"1\"></IngnomiaGUI:RequiredItem>\n            </IngnomiaGUI:BuildItem.RequiredItems>\n        </IngnomiaGUI:BuildItem>\n    </IngnomiaGUI:GameModel.BuildItems>\n</IngnomiaGUI:GameModel>\n"
  },
  {
    "path": "gui/SampleData/StockpileModelSampleData.xaml",
    "content": "﻿<IngnomiaGUI:StockpileModel xmlns:IngnomiaGUI=\"clr-namespace:IngnomiaGUI\" Name=\"Cras vestibulum\" PullFromHere=\"False\" PullFromOther=\"True\" Suspended=\"True\">\n    <IngnomiaGUI:StockpileModel.SelectedPrio>\n        <IngnomiaGUI:SpPriority Name=\"Nullam conubia bibendum dictumst\"/>\n    </IngnomiaGUI:StockpileModel.SelectedPrio>\n    <IngnomiaGUI:StockpileModel.Filters>\n        <IngnomiaGUI:CategoryItem Name=\"Food\" Checked=\"True\" Expanded=\"False\">\n            <IngnomiaGUI:CategoryItem.Children></IngnomiaGUI:CategoryItem.Children>\n        </IngnomiaGUI:CategoryItem>\n        <IngnomiaGUI:CategoryItem Name=\"Metal\" Checked=\"False\" Expanded=\"False\">\n            <IngnomiaGUI:CategoryItem.Children></IngnomiaGUI:CategoryItem.Children>\n        </IngnomiaGUI:CategoryItem>\n        <IngnomiaGUI:CategoryItem Name=\"Misc\" Expanded=\"True\">\n            <IngnomiaGUI:CategoryItem.Children>\n                <IngnomiaGUI:GroupItem Name=\"Furniture\" Checked=\"True\" Expanded=\"False\"/>\n            </IngnomiaGUI:CategoryItem.Children>\n        </IngnomiaGUI:CategoryItem>\n    </IngnomiaGUI:StockpileModel.Filters>\n</IngnomiaGUI:StockpileModel>\n"
  },
  {
    "path": "gui/SampleData/ViewModelSampleData.xaml",
    "content": "﻿<IngnomiaGUI:ViewModel xmlns:IngnomiaGUI=\"clr-namespace:IngnomiaGUI\"\n                       Platform=\"Aliquam aenean vestibulum mauris\"\n                       ShowMainMenu=\"Hidden\"\n                       ShowGameGUI=\"Visible\"\n                       State=\"GameRunning\"\n                       WindowHeight=\"1080\"\n                       WindowWidth=\"1920\"\n                       />\n"
  },
  {
    "path": "gui/Src/App.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n    <startup> \n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6.1\"/>\n    </startup>\n</configuration>\n"
  },
  {
    "path": "gui/Src/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\nusing System.Resources;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\nusing System.Windows;\n\n// General Information about an assembly is controlled through the following \n// set of attributes. Change these attribute values to modify the information\n// associated with an assembly.\n[assembly: AssemblyTitle(\"IngnomiaGUI\")]\n[assembly: AssemblyDescription(\"\")]\n[assembly: AssemblyConfiguration(\"\")]\n[assembly: AssemblyCompany(\"\")]\n[assembly: AssemblyProduct(\"Samples.ApplicationTutorial\")]\n[assembly: AssemblyCopyright(\"Copyright ©  2017\")]\n[assembly: AssemblyTrademark(\"\")]\n[assembly: AssemblyCulture(\"\")]\n\n// Setting ComVisible to false makes the types in this assembly not visible \n// to COM components.  If you need to access a type in this assembly from \n// COM, set the ComVisible attribute to true on that type.\n[assembly: ComVisible(false)]\n\n//In order to begin building localizable applications, set \n//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file\n//inside a <PropertyGroup>.  For example, if you are using US english\n//in your source files, set the <UICulture> to en-US.  Then uncomment\n//the NeutralResourceLanguage attribute below.  Update the \"en-US\" in\n//the line below to match the UICulture setting in the project file.\n\n//[assembly: NeutralResourcesLanguage(\"en-US\", UltimateResourceFallbackLocation.Satellite)]\n\n\n// Version information for an assembly consists of the following four values:\n//\n//      Major Version\n//      Minor Version \n//      Build Number\n//      Revision\n//\n// You can specify all the values or you can default the Build and Revision Numbers \n// by using the '*' as shown below:\n// [assembly: AssemblyVersion(\"1.0.*\")]\n[assembly: AssemblyVersion(\"1.0.0.0\")]\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\n"
  },
  {
    "path": "gui/Src/stubs.cs",
    "content": "﻿using System.Windows.Controls;\r\nusing System.Collections.Generic;\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n    public enum State\r\n    {\r\n        Main,\r\n        Start,\r\n        Settings,\r\n        NewGame,\r\n        LoadGame,\r\n        Wait,\r\n        GameRunning,\r\n        Ingame\r\n    };\r\n\r\n    public partial class MainMenu : UserControl\r\n    {\r\n    }\r\n\r\n    public partial class GameGui : UserControl\r\n    { \r\n    }\r\n\r\n    public class CommandButton\r\n    {\r\n        public string Name { get; set; }\r\n    }\r\n\r\n    public class BuildButton\r\n    {\r\n        public string Name { get; set; }\r\n    }\r\n\r\n    public class AvailableMaterial\r\n    {\r\n        public string Name { get; set; }\r\n        public int Amount { get; set; }\r\n    }\r\n\r\n    public class RequiredItem\r\n    {\r\n        public string Name { get; set; }\r\n        public int Amount { get; set; }\r\n        public List<AvailableMaterial> Materials { get; set; }\r\n        public AvailableMaterial SelectedMaterial { get; set; }\r\n    }\r\n\r\n    public enum BuildItemType\r\n    {\r\n        Workshop,\r\n        Item,\r\n        Terrain\r\n    };\r\n\r\n    public class BuildItem\r\n    {\r\n        public string Name { get; set; }\r\n        public List<RequiredItem> RequiredItems { get; set; }\r\n    }\r\n\r\n    public class CommonModel\r\n    {\r\n\r\n        public double WindowWidth { get; set; }\r\n        public double WindowHeight { get; set; }\r\n    }\r\n\r\n    public class GameModel : CommonModel\r\n    {\r\n        public string Day { get; set; }\r\n        public string Year { get; set; }\r\n        public string Time { get; set; }\r\n        public string Sun { get; set; }\r\n\r\n        public bool Paused { get; set; }\r\n        public bool NormalSpeed { get; set; }\r\n        public bool FastSpeed { get; set; }\r\n\r\n        public System.Windows.Visibility ShowCommandButtons { get; set; }\r\n        public List<CommandButton> CommandButtons { get; set; }\r\n\r\n        public System.Windows.Visibility ShowCategoryButtons { get; set; }\r\n        public List<BuildButton> BuildButtons { get; set; }\r\n        public List<BuildItem> BuildItems { get; set; }\r\n\r\n    }\r\n\r\n    public class LoadGameModel\r\n    {\r\n        public class SaveItem\r\n        {\r\n            public string Name { get; set; }\r\n            public string Version { get; set; }\r\n            public string Data { get; set; }\r\n        }\r\n\r\n        public List<SaveItem> SavedKingdoms { get; set; }\r\n        public SaveItem SelectedKingdom { get; set; }\r\n        public List<SaveItem> SavedGames { get; set; }\r\n        public SaveItem SelectedGame { get; set; }\r\n    }\r\n\r\n    public class ViewModel : CommonModel\r\n    {\r\n        public State State { get; set; }\r\n        public string Platform { get; set; }\r\n\r\n        public System.Windows.Visibility ShowMainMenu { get; set; }\r\n        public System.Windows.Visibility ShowGameGUI { get; set; }\r\n    }\r\n\r\n    public partial class IngamePage : UserControl\r\n    {\r\n    }\r\n\r\n    public partial class SettingsPage : UserControl\r\n    {\r\n    }\r\n\r\n    public partial class LoadGamePage : UserControl\r\n    {\r\n    }\r\n\r\n    public partial class Main : UserControl\r\n    {\r\n    }\r\n\r\n    public class SpPriority\r\n    {\r\n        public string Name { get; set; }\r\n    }\r\n\r\n    public class MaterialItem\r\n    {\r\n        public string Name { get; set; }\r\n        public bool Checked { get; set; }\r\n    }\r\n\r\n    public class ItemItem\r\n    {\r\n        public string Name { get; set; }\r\n        public bool? Checked { get; set; }\r\n        public bool Expanded { get; set; }\r\n        public List<MaterialItem> Children { get; set; }\r\n    }\r\n\r\n    public class GroupItem\r\n    {\r\n        public string Name { get; set; }\r\n        public bool? Checked { get; set; }\r\n        public bool Expanded { get; set; }\r\n        public List<ItemItem> Children { get; set; }\r\n    }\r\n\r\n    public class CategoryItem\r\n    {\r\n        public string Name { get; set; }\r\n        public bool? Checked { get; set; }\r\n        public bool Expanded { get; set; }\r\n        public List<GroupItem> Children { get; set; }\r\n    }\r\n\r\n    public class StockpileModel\r\n    {\r\n        public string Name { get; set; }\r\n        public bool Suspended { get; set; }\r\n        public bool PullFromHere { get; set; }\r\n        public bool PullFromOther { get; set; }\r\n        public List<SpPriority> Priorities { get; set; }\r\n        public SpPriority SelectedPrio { get; set; }\r\n        public List<CategoryItem> Filters { get; set; }\r\n    }\r\n\r\n    public class NewGameModel\r\n    {\r\n    }\r\n\r\n    public class TileInfoModel\r\n    {\r\n    }\r\n\r\n    public class WorkshopModel\r\n    {\r\n    }\r\n\r\n    public class SettingsModel\r\n    {\r\n    }\r\n\r\n    public class PopulationModel\r\n    {\r\n    }\r\n\r\n    public class AgricultureModel\r\n    {\r\n    }\r\n\r\n    public class CreatureInfoModel\r\n    {\r\n    }\r\n\r\n    public class DebugModel\r\n    {\r\n    }\r\n\r\n    public partial class StockpileGui : UserControl\r\n    {\r\n    }\r\n\r\n    public partial class PopulationWindow : UserControl\r\n    {\r\n    }\r\n\r\n    public class MilitaryModel\r\n    {\r\n    }\r\n\r\n    public class NeighborsModel\r\n    {\r\n    }\r\n\r\n    public class InventoryModel\r\n    {\r\n    }\r\n\r\n    public class ColorToBrushConverter\r\n    {\r\n    }\r\n\r\n    public class ColorToBrushConverterDark\r\n    {\r\n    }\r\n\r\n    public class SelectionModel\r\n    {\r\n    }\r\n}\r\n"
  },
  {
    "path": "gui/app.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n<startup><supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.5\"/></startup></configuration>\n"
  },
  {
    "path": "gui/gui.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"14.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\r\n  <PropertyGroup>\r\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\r\n    <Platform Condition=\" '$(Platform)' == '' \">x64</Platform>\r\n    <ProjectGuid>{8429DBC8-7A07-466F-B814-C5F158CF0A65}</ProjectGuid>\r\n    <OutputType>Library</OutputType>\r\n    <AppDesignerFolder>Properties</AppDesignerFolder>\r\n    <RootNamespace>IngnomiaGUI</RootNamespace>\r\n    <AssemblyName>IngnomiaGUI</AssemblyName>\r\n    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>\r\n    <FileAlignment>512</FileAlignment>\r\n    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>\r\n    <WarningLevel>4</WarningLevel>\r\n    <PublishUrl>publish\\</PublishUrl>\r\n    <Install>true</Install>\r\n    <InstallFrom>Disk</InstallFrom>\r\n    <UpdateEnabled>false</UpdateEnabled>\r\n    <UpdateMode>Foreground</UpdateMode>\r\n    <UpdateInterval>7</UpdateInterval>\r\n    <UpdateIntervalUnits>Days</UpdateIntervalUnits>\r\n    <UpdatePeriodically>false</UpdatePeriodically>\r\n    <UpdateRequired>false</UpdateRequired>\r\n    <MapFileExtensions>true</MapFileExtensions>\r\n    <ApplicationRevision>0</ApplicationRevision>\r\n    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>\r\n    <IsWebBootstrapper>false</IsWebBootstrapper>\r\n    <UseApplicationTrust>false</UseApplicationTrust>\r\n    <BootstrapperEnabled>true</BootstrapperEnabled>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|x64' \">\r\n    <PlatformTarget>x64</PlatformTarget>\r\n    <DebugSymbols>true</DebugSymbols>\r\n    <DebugType>full</DebugType>\r\n    <Optimize>false</Optimize>\r\n    <OutputPath>bin\\Debug\\</OutputPath>\r\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'RelWithDebInfo|x64' \">\r\n    <PlatformTarget>x64</PlatformTarget>\r\n    <DebugType>pdbonly</DebugType>\r\n    <Optimize>true</Optimize>\r\n    <OutputPath>bin\\Release\\</OutputPath>\r\n    <DefineConstants>TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n  </PropertyGroup>\r\n  <PropertyGroup>\r\n    <StartupObject />\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Reference Include=\"Microsoft.CSharp\" />\r\n    <Reference Include=\"System\" />\r\n    <Reference Include=\"System.Data\" />\r\n    <Reference Include=\"System.Xml\" />\r\n    <Reference Include=\"System.Core\" />\r\n    <Reference Include=\"System.Xml.Linq\" />\r\n    <Reference Include=\"System.Data.DataSetExtensions\" />\r\n    <Reference Include=\"System.Net.Http\" />\r\n    <Reference Include=\"System.Xaml\">\r\n      <RequiredTargetFramework>4.0</RequiredTargetFramework>\r\n    </Reference>\r\n    <Reference Include=\"WindowsBase\" />\r\n    <Reference Include=\"PresentationCore\" />\r\n    <Reference Include=\"PresentationFramework\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"Src\\Properties\\AssemblyInfo.cs\" />\r\n    <Page Include=\"..\\content\\xaml\\**\\*.xaml\">\r\n      <Link>Src\\%(RecursiveDir)%(Filename).xaml</Link>\r\n      <Generator>MSBuild:Compile</Generator>\r\n      <SubType>Designer</SubType>\r\n    </Page>\r\n    <Compile Include=\"Src\\stubs.cs\">\r\n      <SubType>Code</SubType>\r\n    </Compile>\r\n    <DesignData Include=\"SampleData\\GameModelSampleData.xaml\">\r\n      <Generator>MSBuild:Compile</Generator>\r\n      <SubType>Designer</SubType>\r\n    </DesignData>\r\n    <DesignData Include=\"SampleData\\ViewModelSampleData.xaml\">\r\n      <Generator>MSBuild:Compile</Generator>\r\n      <SubType>Designer</SubType>\r\n    </DesignData>\r\n    <DesignData Include=\"SampleData\\StockpileModelSampleData.xaml\">\r\n      <Generator>MSBuild:Compile</Generator>\r\n      <SubType>Designer</SubType>\r\n    </DesignData>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <AppDesigner Include=\"Src\\Properties\\\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"app.config\" />\r\n    <None Include=\"Src\\App.config\" />\r\n    <Resource Include=\"..\\content\\xaml\\**\\*.ttf\">\r\n      <Link>Src\\%(RecursiveDir)%(Filename).ttf</Link>\r\n    </Resource>\r\n    <Resource Include=\"..\\content\\xaml\\**\\*.png\">\r\n      <Link>Src\\%(RecursiveDir)%(Filename).png</Link>\r\n    </Resource>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <PackageReference Include=\"Noesis.GUI.Extensions\">\r\n      <Version>3.0.0-rc1</Version>\r\n    </PackageReference>\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Folder Include=\"Properties\\\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <BootstrapperPackage Include=\"Microsoft.Net.Framework.3.5.SP1\">\r\n      <Visible>False</Visible>\r\n      <ProductName>.NET Framework 3.5 SP1</ProductName>\r\n      <Install>false</Install>\r\n    </BootstrapperPackage>\r\n  </ItemGroup>\r\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\r\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \n       Other similar extension points exist, see Microsoft.Common.targets.\n  <Target Name=\"BeforeBuild\">\n  </Target>\n  <Target Name=\"AfterBuild\">\n  </Target>\n  -->\r\n</Project>"
  },
  {
    "path": "keybindings.json",
    "content": "[\n    {\n        \"GroupName\": \"Navigation\",\n        \"Keys\": [\n            {\n                \"Command\": \"WorldScrollLeft\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"A\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"WorldScrollRight\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"D\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"WorldScrollUp\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"W\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"WorldScrollDown\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"S\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RotateWorldCW\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \",\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RotateWorldCCW\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \".\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ZMinus\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": true,\n                    \"Key\": \"-\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ZPlus\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": true,\n                    \"Key\": \"]\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ZoomIn\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"-\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ZoomOut\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"+\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            }\n        ]\n    },\n    {\n        \"GroupName\": \"Game\",\n        \"Keys\": [\n\t\t\t{\n                \"Command\": \"QuickSave\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"F5\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n\t\t\t{\n                \"Command\": \"QuickLoad\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"F8\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n\t\t\n            {\n                \"Command\": \"ToggleFullScreen\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"F\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"OpenGnomeList\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"G\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ToggleWalls\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"H\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ToggleAxles\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"Q\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"OpenLastActionWindow\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"L\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"TogglePause\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"Space\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"P\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RotateSelection\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"R\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey1\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"1\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey2\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"2\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey3\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"3\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey4\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"4\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey5\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"5\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey6\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"6\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey7\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"7\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey8\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"8\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey9\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"9\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MenuButtonKey0\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"0\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            }\n        ]\n    },\n    {\n        \"GroupName\": \"Debug\",\n        \"Keys\": [\n            {\n                \"Command\": \"OpenDebugWindow\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": true,\n                    \"Key\": \"D\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ToggleDebugMode\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": true,\n                    \"Ctrl\": false,\n                    \"Key\": \"D\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"PrintDebug\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ToggleOverlay\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"O\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ToggleDebugOverlay\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"I\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ReloadShaders\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"J\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"OpenLogWindow\",\n                \"Desc\": \"open log window\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": true,\n                    \"Key\": \"L\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"OpenBugReportWindow\",\n                \"Desc\": \"open bug report window\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"F11\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ReloadCSS\",\n                \"Desc\": \"reload css\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"F10\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ToggleRenderCreatures\",\n                \"Desc\": \"toggle render creatures\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"#\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            }\n        ]\n    },\n    {\n        \"GroupName\": \"Actions\",\n        \"Keys\": [\n            {\n                \"Command\": \"Mine\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"DigHole\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ExplorativeMine\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RemoveRamp\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RemoveFloor\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RemovePlant\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MineStairsUp\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"DigStairsDown\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"DigRampDown\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CreateRoom\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CreateStockpile\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CreateGrove\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CreateFarm\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CreatePasture\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CreateNoPass\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildWall\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ReplaceWall\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"V\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildWallFloor\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildFancyWall\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildFloor\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"ReplaceFloor\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildFancyFloor\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildScaffold\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildFence\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildWorkshop\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildStairs\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildRamp\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildRampCorner\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CutClipping\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"BuildItem\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"PlantTree\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"FellTree\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"Forage\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"HarvestTree\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RemoveDesignation\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"Deconstruct\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"CancelJob\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"RaisePrio\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"LowerPrio\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MagicNatureSpeedGrowth\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            },\n            {\n                \"Command\": \"MagicGeomancyRevealOre\",\n                \"Desc\": \"\",\n                \"Key1\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                },\n                \"Key2\": {\n                    \"Alt\": false,\n                    \"Ctrl\": false,\n                    \"Key\": \"\",\n                    \"Shift\": false\n                }\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "file(GLOB_RECURSE SOURCE_LIST\n\t\"*.h\"\n\t\"*.hpp\"\n\t\"*.cpp\"\n)\n\ntarget_sources(${PROJECT_NAME}\n\tPRIVATE\n\t\t${SOURCE_LIST}\n\t\t${CMAKE_CURRENT_LIST_FILE}\n)\n\ntarget_precompile_headers(${PROJECT_NAME}\n\tPRIVATE\n\t\tpch.h\n)\n"
  },
  {
    "path": "src/base/PathFinderThread.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"PathFinderThread.h\"\r\n\r\n#include \"../base/global.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\n#include <map>\r\n\r\n#define DEADLYFLUIDLEVEL 4\r\n\r\nPathFinderThread::PathFinderThread( World* world, Position start, const std::unordered_set<Position>& goals, bool ignoreNoPass, PathFinderThread::CompletionCallback callback ) :\r\n\tm_world( world ),\r\n\tm_start( start ),\r\n\tm_goals( goals ),\r\n\tm_ignoreNoPass( ignoreNoPass ),\r\n\tm_callback( callback )\r\n{\r\n}\r\n\r\nvoid PathFinderThread::operator()()\r\n{\r\n\tfindPath();\r\n}\r\n\r\nbool PathFinderThread::evalPos( const Position& current, const Position& next, std::unordered_map<Position, PathElement>& path, PriorityQueue<Position, double>& frontier, const Position& goal ) const\r\n{\r\n\tconst Tile& tile = m_world->getTile( next );\r\n\r\n\tif ( tile.flags & TileFlag::TF_WALKABLE && tile.fluidLevel < DEADLYFLUIDLEVEL )\r\n\t{\r\n\t\tif ( m_ignoreNoPass || !( tile.flags & TileFlag::TF_NOPASS ) )\r\n\t\t{\r\n\t\t\tdouble new_cost = path[current].cost + cost( current, next );\r\n\t\t\t// Try insert, doesn't overwrite if already visited\r\n\t\t\tauto nextIt   = path.insert( { next, { new_cost, current } } );\r\n\t\t\tauto& oldPath = nextIt.first->second;\r\n\t\t\t// If actually new or at least cheaper\r\n\t\t\tif ( nextIt.second || new_cost < oldPath.cost )\r\n\t\t\t{\r\n\t\t\t\t// then update costs and priority\r\n\t\t\t\toldPath.cost     = new_cost;\r\n\t\t\t\toldPath.previous = current;\r\n\t\t\t\tdouble priority  = new_cost + heuristic( next, goal );\r\n\t\t\t\tfrontier.put( next, priority );\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool PathFinderThread::evalRampPos( const Position& current, const Position& rampPos, std::unordered_map<Position, PathElement>& path, PriorityQueue<Position, double>& frontier, const Position& goal ) const\r\n{\r\n\tconst Tile& rampTopTile = m_world->getTile( rampPos );\r\n\r\n\tif ( !(bool)( rampTopTile.floorType & FT_RAMPTOP ) )\r\n\t\treturn false;\r\n\r\n\tauto next = rampPos.belowOf();\r\n\r\n\tconst Tile& tile = m_world->getTile( next );\r\n\r\n\tif ( tile.flags & TileFlag::TF_WALKABLE && tile.fluidLevel < DEADLYFLUIDLEVEL )\r\n\t{\r\n\t\tif ( m_ignoreNoPass || !( tile.flags & TileFlag::TF_NOPASS ) )\r\n\t\t{\r\n\t\t\tdouble new_cost = path[current].cost + cost( current, next );\r\n\t\t\t// Try insert, doesn't overwrite if already visited\r\n\t\t\tauto nextIt   = path.insert( { next, { new_cost, current } } );\r\n\t\t\tauto& oldPath = nextIt.first->second;\r\n\t\t\t// If actually new or at least cheaper\r\n\t\t\tif ( nextIt.second || new_cost < oldPath.cost )\r\n\t\t\t{\r\n\t\t\t\t// then update costs and priority\r\n\t\t\t\toldPath.cost     = new_cost;\r\n\t\t\t\toldPath.previous = current;\r\n\t\t\t\tdouble priority  = new_cost + heuristic( next, goal );\r\n\t\t\t\tfrontier.put( next, priority );\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid PathFinderThread::findPath()\r\n{\r\n\t//qDebug() << \"find path \" << m_start.toString() << \" \" << m_goal.toString();\r\n\tstd::unordered_map<Position, PathElement> pathField;\r\n\tPriorityQueue<Position, double> frontier;\r\n\r\n\t// Take a pessimistic guess for how many positions we need to visit\r\n\tint expectedPositions = 0;\r\n\tfor(const auto& goal : m_goals)\r\n\t{\r\n\t\texpectedPositions = std::max( m_start.distSquare( goal, 3 ) / 8, expectedPositions );\r\n\t}\r\n\tpathField.reserve( expectedPositions );\r\n\r\n\tfrontier.put( m_start, 0 );\r\n\tpathField.insert( { m_start, PathElement { 0.0, m_start } } );\r\n\r\n\tfor ( const auto& goal : m_goals )\r\n\t{\r\n\t\tbool found = false;\r\n\t\t// Chance we already passed the current goal while searching for a previous one\r\n\t\tif ( pathField.count(goal) > 0 )\r\n\t\t{\r\n\t\t\tfound = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Re-weight frontier acording to current goal\r\n\t\t\t{\r\n\t\t\t\tauto oldFrontier = std::move( frontier );\r\n\t\t\t\t// Don't care about order\r\n\t\t\t\tfor ( const auto& pos : oldFrontier.raw() )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst auto& field = pathField[pos.second];\r\n\t\t\t\t\tfrontier.put( pos.second, field.cost + heuristic( pos.second, goal ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\twhile ( !frontier.empty() && !found )\r\n\t\t{\r\n\t\t\tconst auto current = frontier.top().second;\r\n\r\n\t\t\t// Either shortcut or fully process\r\n\t\t\tif ( current == goal )\r\n\t\t\t{\r\n\t\t\t\tfound = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfrontier.pop();\r\n\t\t\t}\r\n\r\n\t\t\tbool north = false;\r\n\t\t\tbool east  = false;\r\n\t\t\tbool south = false;\r\n\t\t\tbool west  = false;\r\n\r\n\t\t\tauto next = current.northOf();\r\n\t\t\tnorth     = evalPos( current, next, pathField, frontier, goal );\r\n\t\t\tevalRampPos( current, next, pathField, frontier, goal );\r\n\r\n\t\t\tnext = current.eastOf();\r\n\t\t\teast = evalPos( current, next, pathField, frontier, goal );\r\n\t\t\tevalRampPos( current, next, pathField, frontier, goal );\r\n\r\n\t\t\tnext  = current.southOf();\r\n\t\t\tsouth = evalPos( current, next, pathField, frontier, goal );\r\n\t\t\tevalRampPos( current, next, pathField, frontier, goal );\r\n\r\n\t\t\tnext = current.westOf();\r\n\t\t\twest = evalPos( current, next, pathField, frontier, goal );\r\n\t\t\tevalRampPos( current, next, pathField, frontier, goal );\r\n\r\n\t\t\tif ( north && east )\r\n\t\t\t{\r\n\t\t\t\tnext = current.neOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\t\t\tif ( east && south )\r\n\t\t\t{\r\n\t\t\t\tnext = current.seOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\t\t\tif ( south && west )\r\n\t\t\t{\r\n\t\t\t\tnext = current.swOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\t\t\tif ( west && north )\r\n\t\t\t{\r\n\t\t\t\tnext = current.nwOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\r\n\t\t\tTile& curTile = m_world->getTile( current );\r\n\r\n\t\t\tif ( (bool)( curTile.wallType & ( WT_STAIR | WT_SCAFFOLD ) ) )\r\n\t\t\t{\r\n\t\t\t\tnext = current.aboveOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\t\t\tif ( (bool)( curTile.floorType & ( FT_STAIRTOP | FT_SCAFFOLD ) ) )\r\n\t\t\t{\r\n\t\t\t\tnext = current.belowOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\t\t\tif ( (bool)( curTile.wallType & ( WT_RAMP ) ) )\r\n\t\t\t{\r\n\t\t\t\tauto above = current.aboveOf();\r\n\t\t\t\tnext       = above.northOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t\tnext = above.eastOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t\tnext = above.southOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t\tnext = above.westOf();\r\n\t\t\t\tevalPos( current, next, pathField, frontier, goal );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tPath path;\r\n\t\tif ( found )\r\n\t\t{\r\n\t\t\tPosition next = goal;\r\n\t\t\twhile ( next != m_start )\r\n\t\t\t{\r\n\t\t\t\tpath.push_back( next );\r\n\t\t\t\tnext = pathField[next].previous;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t/*\r\n\t\tqDebug() << \"##################################################################################################\";\r\n\t\tqDebug() << \"no path found\";\r\n\t\tqDebug() << \"start: \" << m_start.toString() << \" goal: \" << m_goal.toString();\r\n\t\tqDebug() << \"##################################################################################################\";\r\n\t\t*/\r\n\t\t}\r\n\t\tm_callback( m_start, goal, m_ignoreNoPass, std::move(path) );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/base/PathFinderThread.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../base/priorityqueue.h\"\r\n\r\n#include <functional>\r\n#include <vector>\r\n#include <unordered_set>\r\n\r\nclass World;\r\n\r\nclass PathFinderThread\r\n{\r\npublic:\r\n\tusing Path               = std::vector<Position>;\r\n\tusing CompletionCallback = std::function<void(Position, Position, bool ignoreNoPass, Path )>;\r\n\tPathFinderThread()       = delete;\r\n\tPathFinderThread( World* world, Position start, const std::unordered_set<Position>& goals, bool ignoreNoPass, CompletionCallback callback );\r\n\r\n\tvoid operator()();\r\nprivate:\r\n\tvoid findPath();\r\n\r\n\tWorld* m_world = nullptr;\r\n\tconst Position m_start;\r\n\tconst std::unordered_set<Position> m_goals;\r\n\tconst bool m_ignoreNoPass = false;\r\n\r\n\tCompletionCallback m_callback;\r\n\r\n\tstatic inline double heuristic( const Position& a, const Position& b )\r\n\t{\r\n\t\t// Heuristic needs to represent the lowest, possible cost from a to b\r\n\t\t// Going even lower increases the search space, but still yields correct path\r\n\t\t// Going too high will result in fiding sub-optimal paths as the search space is reduced too much\r\n\t\treturn cost(a, b);\r\n\t}\r\n\r\n\tstatic inline double cost( const Position& lhs, const Position& rhs )\r\n\t{\r\n\t\treturn std::sqrt( abs( lhs.x - rhs.x ) + abs( lhs.y - rhs.y ) + 2 * abs( lhs.z - rhs.z ) );\r\n\t}\r\n\r\n\tstruct PathElement\r\n\t{\r\n\t\tdouble cost;\r\n\t\tPosition previous;\r\n\t};\r\n\r\n\tbool evalPos( const Position& current, const Position& next, std::unordered_map<Position, PathElement>& path, PriorityQueue<Position, double>& frontier, const Position& goal ) const;\r\n\tbool evalRampPos( const Position& current, const Position& next, std::unordered_map<Position, PathElement>& path, PriorityQueue<Position, double>& frontier, const Position& goal ) const;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_factory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_factory.h\"\r\n\r\n#include \"../config.h\"\r\n#include \"../global.h\"\r\n\r\n#include <QDebug>\r\n\r\nnamespace\r\n{\r\nclass BT_NodeDummy final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeDummy( QString name, QVariantMap& blackboard ) :\r\n\t\tBT_Node( name, blackboard )\r\n\t{\r\n\t}\r\n\t~BT_NodeDummy()\r\n\t{\r\n\t}\r\n\r\n\tBT_Node* takeChild()\r\n\t{\r\n\t\tif ( m_children.size() )\r\n\t\t{\r\n\t\t\tauto child = m_children.back();\r\n\t\t\tm_children.pop_back();\r\n\t\t\treturn child;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn nullptr;\r\n\t\t}\r\n\t}\r\n};\r\n}\r\n\r\nBT_Node* BT_Factory::load( const QString id, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard )\r\n{\r\n\tQDomElement root = Global::behaviorTree( id );\r\n\tQString mainTree = root.attribute( \"main_tree_to_execute\" );\r\n\r\n\tBT_Node* behaviorTree = getTree( mainTree, root, actions, blackboard );\r\n\tif ( !behaviorTree )\r\n\t{\r\n\t\tqDebug() << \"Fatal error. Failed to load behavior tree\";\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\treturn behaviorTree;\r\n}\r\n\r\nBT_Node* BT_Factory::getTree( QString treeID, QDomElement documentRoot, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard )\r\n{\r\n\tQDomElement treeElement = documentRoot.firstChildElement();\r\n\twhile ( !treeElement.isNull() )\r\n\t{\r\n\t\tQString nodeName = treeElement.nodeName();\r\n\r\n\t\tif ( nodeName == \"BehaviorTree\" )\r\n\t\t{\r\n\t\t\tQString thisTreeID = treeElement.attribute( \"ID\" );\r\n\t\t\tif ( thisTreeID == treeID )\r\n\t\t\t{\r\n\t\t\t\tQDomElement treeRoot = treeElement.firstChildElement();\r\n\r\n\t\t\t\tBT_NodeDummy dummy( \"dummy\", blackboard );\r\n\r\n\t\t\t\tcreateBTNode( treeRoot, &dummy, documentRoot, actions, blackboard );\r\n\r\n\t\t\t\tBT_Node* rootNode = dummy.takeChild();\r\n\r\n\t\t\t\tassert( rootNode );\r\n\t\t\t\tif ( rootNode )\r\n\t\t\t\t{\r\n\t\t\t\t\tgetNodes( rootNode, treeRoot, documentRoot, actions, blackboard );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tqCritical() << \"failed to create root node for behavior tree \" << treeID;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn rootNode;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ttreeElement = treeElement.nextSiblingElement();\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid BT_Factory::getNodes( BT_Node* parent, QDomElement root, QDomElement& documentRoot, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard )\r\n{\r\n\tQDomElement treeElement = root.firstChildElement();\r\n\twhile ( !treeElement.isNull() )\r\n\t{\r\n\t\tBT_Node* node = createBTNode( treeElement, parent, documentRoot, actions, blackboard );\r\n\r\n\t\tif ( treeElement.hasChildNodes() )\r\n\t\t{\r\n\t\t\tgetNodes( node, treeElement, documentRoot, actions, blackboard );\r\n\t\t}\r\n\r\n\t\ttreeElement = treeElement.nextSiblingElement();\r\n\t}\r\n}\r\n\r\nBT_Node* BT_Factory::createBTNode( QDomElement domElement, BT_Node* parent, QDomElement& documentRoot, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard )\r\n{\r\n\tQString nodeName = domElement.nodeName();\r\n\tBT_Node* bn      = nullptr;\r\n\tif ( nodeName == \"Action\" )\r\n\t{\r\n\t\tif ( !actions.contains( domElement.attribute( \"ID\" ) ) )\r\n\t\t{\r\n\t\t\tqCritical() << \"Action \" << domElement.attribute( \"ID\" ) << \" doesn't exist in behaviorMap\";\r\n\t\t\tabort();\r\n\t\t}\r\n\t\tbn = parent->addAction( domElement.attribute( \"ID\" ), actions[domElement.attribute( \"ID\" )] );\r\n\t}\r\n\telse if ( nodeName == \"Condition\" )\r\n\t{\r\n\t\tif ( !actions.contains( domElement.attribute( \"ID\" ) ) )\r\n\t\t{\r\n\t\t\tqCritical() << \"Condition doesn't exist in behaviorMap:\" << domElement.attribute( \"ID\" );\r\n\t\t\tabort();\r\n\t\t}\r\n\t\tbn = parent->addConditional( domElement.attribute( \"ID\" ), actions[domElement.attribute( \"ID\" )] );\r\n\t}\r\n\telse if ( nodeName == \"Fallback\" )\r\n\t{\r\n\t\tbn = parent->addFallback( domElement.attribute( \"name\" ) );\r\n\t}\r\n\telse if ( nodeName == \"FallbackStar\" )\r\n\t{\r\n\t\tbn = parent->addFallbackStar( domElement.attribute( \"name\" ) );\r\n\t}\r\n\telse if ( nodeName == \"ForceSuccess\" )\r\n\t{\r\n\t\tbn = parent->addForceSuccess();\r\n\t}\r\n\telse if ( nodeName == \"ForceFailure\" )\r\n\t{\r\n\t\tbn = parent->addForceFailure();\r\n\t}\r\n\telse if ( nodeName == \"Sequence\" )\r\n\t{\r\n\t\tbn = parent->addSequence( domElement.attribute( \"name\" ) );\r\n\t}\r\n\telse if ( nodeName == \"SequenceStar\" )\r\n\t{\r\n\t\tbn = parent->addSequenceStar( domElement.attribute( \"name\" ) );\r\n\t}\r\n\telse if ( nodeName == \"Repeat\" )\r\n\t{\r\n\t\tbn = parent->addRepeat( domElement.attribute( \"name\" ), domElement.attribute( \"num_cycles\" ).toInt() );\r\n\t}\r\n\telse if ( nodeName == \"RetryUntilSuccesful\" )\r\n\t{\r\n\t\tbn = parent->addRepeatUntilSuccess( domElement.attribute( \"name\" ), domElement.attribute( \"num_attempts\" ).toInt() );\r\n\t}\r\n\telse if ( nodeName == \"Inverter\" )\r\n\t{\r\n\t\tbn = parent->addInverter( domElement.attribute( \"name\" ) );\r\n\t}\r\n\telse if ( nodeName == \"BB_Precondition\" )\r\n\t{\r\n\t\tbn = parent->addBBPrecondition( domElement.attribute( \"name\" ), domElement.attribute( \"key\" ), domElement.attribute( \"expected\" ) );\r\n\t}\r\n\telse if ( nodeName == \"SubTree\" )\r\n\t{\r\n\t\tQString subtreeID = domElement.attribute( \"ID\" );\r\n\t\t//qDebug() << \"request subtree: \" << subtreeID;\r\n\t\tbn = getTree( subtreeID, documentRoot, actions, blackboard );\r\n\t\tif ( bn )\r\n\t\t{\r\n\t\t\t//qDebug() << \"found subtree\";\r\n\t\t\tparent->addTree( bn );\r\n\t\t}\r\n\t}\r\n\treturn bn;\r\n}\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_factory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_tree.h\"\r\n\r\n#include <QDomDocument>\r\n#include <QHash>\r\n#include <QObject>\r\n#include <QVariantMap>\r\n\r\n#include <functional>\r\n\r\nclass BT_Factory\r\n{\r\npublic:\r\n\tBT_Factory()  = delete;\r\n\t~BT_Factory() = delete;\r\n\r\n\tstatic BT_Node* load( const QString id, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard );\r\n\r\nprivate:\r\n\tstatic BT_Node* createBTNode( QDomElement treeElement, BT_Node* parent, QDomElement& documentRoot, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard );\r\n\r\n\tstatic BT_Node* getTree( QString treeID, QDomElement documentRoot, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard );\r\n\r\n\tstatic void getNodes( BT_Node* parent, QDomElement root, QDomElement& documentRoot, QHash<QString, std::function<BT_RESULT( bool )>>& actions, QVariantMap& blackboard );\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_node.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_node.h\"\r\n\r\n#include \"bt_tree.h\"\r\n\r\n#include <QDebug>\r\n\r\nBT_Node::BT_Node( QString name, QVariantMap& blackboard ) :\r\n\tm_name( name ),\r\n\tm_blackboard( blackboard )\r\n{\r\n}\r\n\r\nBT_Node::~BT_Node()\r\n{\r\n\tfor ( const auto& child : m_children )\r\n\t{\r\n\t\tdelete child;\r\n\t}\r\n}\r\n\r\nQVariantMap BT_Node::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Name\", m_name );\r\n\tout.insert( \"ID\", m_index );\r\n\tout.insert( \"Status\", (unsigned char)m_status );\r\n\r\n\tQVariantList childs;\r\n\tfor ( const auto& child : m_children )\r\n\t{\r\n\t\tchilds.append( child->serialize() );\r\n\t}\r\n\tout.insert( \"Childs\", childs );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid BT_Node::deserialize( QVariantMap in )\r\n{\r\n\tif ( m_name != in.value( \"Name\" ).toString() )\r\n\t{\r\n\t\tqDebug() << \"error loading behavior tree state - nodes don't match\";\r\n\t}\r\n\tm_index  = in.value( \"ID\" ).toInt();\r\n\tm_status = (BT_RESULT)in.value( \"Status\" ).toInt();\r\n\r\n\tauto vcl  = in.value( \"Childs\" ).toList();\r\n\tint index = 0;\r\n\tif ( vcl.size() == m_children.size() )\r\n\t{\r\n\r\n\t\tfor ( auto child : m_children )\r\n\t\t{\r\n\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//tree changed between saving and loading, this will have undetermined results\r\n\t\t// TODO throw exception or make config option to allow or deny loading this\r\n\t\tif ( vcl.size() < m_children.size() )\r\n\t\t{\r\n\t\t\tfor ( auto vcm : vcl )\r\n\t\t\t{\r\n\t\t\t\tm_children[index++]->deserialize( vcm.toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto child : m_children )\r\n\t\t\t{\r\n\t\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nBT_Node* BT_Node::addFallback( QString name )\r\n{\r\n\tBT_NodeFallback* bn = new BT_NodeFallback( name, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addFallbackStar( QString name )\r\n{\r\n\tBT_NodeFallbackStar* bn = new BT_NodeFallbackStar( name, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addSequence( QString name )\r\n{\r\n\tBT_NodeSequence* bn = new BT_NodeSequence( name, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addSequenceStar( QString name )\r\n{\r\n\tBT_NodeSequenceStar* bn = new BT_NodeSequenceStar( name, m_blackboard, true );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addForceSuccess()\r\n{\r\n\tBT_NodeForceSuccess* bn = new BT_NodeForceSuccess( m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addForceFailure()\r\n{\r\n\tBT_NodeForceFailure* bn = new BT_NodeForceFailure( m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addInverter( QString name )\r\n{\r\n\tBT_NodeInverter* bn = new BT_NodeInverter( name, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addRepeat( QString name, int num )\r\n{\r\n\tBT_NodeRepeat* bn = new BT_NodeRepeat( name, num, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addRepeatUntilSuccess( QString name, int num )\r\n{\r\n\tBT_NodeRepeatUntilSuccess* bn = new BT_NodeRepeatUntilSuccess( name, num, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nvoid BT_Node::addTree( BT_Node* tree )\r\n{\r\n\tm_children.push_back( tree );\r\n}\r\n\r\nBT_Node* BT_Node::addConditional( QString name, std::function<BT_RESULT( bool )> callback )\r\n{\r\n\tBT_NodeConditional* bn = new BT_NodeConditional( name, m_blackboard, callback );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addAction( QString name, std::function<BT_RESULT( bool )> callback )\r\n{\r\n\tBT_NodeAction* bn = new BT_NodeAction( name, m_blackboard, callback );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nBT_Node* BT_Node::addBBPrecondition( QString name, QString key, QString expected )\r\n{\r\n\tBT_NodeBBPrecondition* bn = new BT_NodeBBPrecondition( name, key, expected, m_blackboard );\r\n\tm_children.push_back( bn );\r\n\r\n\treturn bn;\r\n}\r\n\r\nvoid BT_Node::haltAllChildren()\r\n{\r\n\tfor ( auto child : m_children )\r\n\t{\r\n\t\tchild->halt();\r\n\t}\r\n}\r\n\r\nvoid BT_Node::halt()\r\n{\r\n\tm_index = 0;\r\n\thaltAllChildren();\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_node.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QString>\r\n#include <QVariantMap>\r\n#include <QVector>\r\n\r\n#include <vector>\r\n\r\nenum class BT_RESULT\r\n{\r\n\tFAILURE,\r\n\tSUCCESS,\r\n\tRUNNING,\r\n\tIDLE\r\n};\r\n\r\nclass BT_Node\r\n{\r\npublic:\r\n\tBT_Node( QString name, QVariantMap& blackboard );\r\n\tvirtual ~BT_Node();\r\n\r\n\tvirtual QVariantMap serialize() const;\r\n\tvirtual void deserialize( QVariantMap in );\r\n\r\n\tvirtual BT_RESULT tick()\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t};\r\n\r\n\tvirtual void haltAllChildren();\r\n\tvirtual void halt();\r\n\r\n\tBT_RESULT status() const\r\n\t{\r\n\t\treturn m_status;\r\n\t}\r\n\r\n\tBT_Node* addFallback( QString name );\r\n\tBT_Node* addFallbackStar( QString name );\r\n\tBT_Node* addForceSuccess();\r\n\tBT_Node* addForceFailure();\r\n\tBT_Node* addSequence( QString name );\r\n\tBT_Node* addSequenceStar( QString name );\r\n\tBT_Node* addInverter( QString name );\r\n\tBT_Node* addRepeat( QString name, int num );\r\n\tBT_Node* addRepeatUntilSuccess( QString name, int num );\r\n\tBT_Node* addBBPrecondition( QString name, QString key, QString expected );\r\n\r\n\tvoid addTree( BT_Node* tree );\r\n\r\n\tBT_Node* addConditional( QString name, std::function<BT_RESULT( bool )> callback );\r\n\tBT_Node* addAction( QString name, std::function<BT_RESULT( bool )> callback );\r\n\r\nprotected:\r\n\tconst QString m_name;\r\n\tQVariantMap& m_blackboard;\r\n\r\n\tstd::vector<BT_Node*> m_children;\r\n\r\n\tBT_RESULT m_status = BT_RESULT::IDLE;\r\n\r\n\tint m_index = 0;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodeaction.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodeaction.h\"\r\n\r\nBT_NodeAction::BT_NodeAction( QString name, QVariantMap& blackboard, std::function<BT_RESULT( bool )> callback ) :\r\n\tBT_Node( name, blackboard ),\r\n\tm_callback( callback )\r\n{\r\n}\r\n\r\nBT_NodeAction::~BT_NodeAction()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeAction::tick()\r\n{\r\n\tm_status = m_callback( false );\r\n\treturn m_status;\r\n}\r\n\r\nvoid BT_NodeAction::halt()\r\n{\r\n\tif ( m_status == BT_RESULT::RUNNING )\r\n\t{\r\n\t\tm_status = BT_RESULT::IDLE; //m_callback( true );\r\n\t}\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodeaction.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeAction final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeAction( QString name, QVariantMap& blackboard, std::function<BT_RESULT( bool )> callback );\r\n\t~BT_NodeAction();\r\n\r\n\tBT_RESULT tick();\r\n\r\n\tvoid halt();\r\n\r\n\tBT_Node* addFallback( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addFallbackStar( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addSequence( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addSequenceStar( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addInverter( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addRepeat( QString name, int num )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addRepeatUntilSuccess( QString name, int num )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\r\n\tvoid addTree( BT_Node* tree ) {};\r\n\r\n\tBT_Node* addConditional( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addAction( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\r\nprivate:\r\n\tstd::function<BT_RESULT( bool )> m_callback;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodebbprecondition.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodebbprecondition.h\"\r\n\r\nBT_NodeBBPrecondition::BT_NodeBBPrecondition( QString name, QString key, QString expected, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard ),\r\n\tm_key( key ),\r\n\tm_expected( expected )\r\n{\r\n}\r\n\r\nBT_NodeBBPrecondition::~BT_NodeBBPrecondition()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeBBPrecondition::tick()\r\n{\r\n\tif ( m_blackboard.value( m_key ).toString() == m_expected || m_expected == \"*\" )\r\n\t{\r\n\t\tif ( m_children.size() > 0 )\r\n\t\t{\r\n\t\t\treturn m_children[0]->tick();\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodebbprecondition.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeBBPrecondition final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeBBPrecondition( QString name, QString key, QString expected, QVariantMap& blackboard );\r\n\t~BT_NodeBBPrecondition();\r\n\r\n\tBT_RESULT tick();\r\n\r\nprivate:\r\n\tQString m_key;\r\n\tQString m_expected;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodeconditional.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodeconditional.h\"\r\n\r\nBT_NodeConditional::BT_NodeConditional( QString name, QVariantMap& blackboard, std::function<BT_RESULT( bool )> callback ) :\r\n\tBT_Node( name, blackboard ),\r\n\tm_callback( callback )\r\n{\r\n}\r\n\r\nBT_NodeConditional::~BT_NodeConditional()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeConditional::tick()\r\n{\r\n\tm_status = m_callback( false );\r\n\treturn m_status;\r\n}\r\n\r\nvoid BT_NodeConditional::halt()\r\n{\r\n\tif ( m_status == BT_RESULT::RUNNING )\r\n\t{\r\n\t\tm_status = BT_RESULT::IDLE; // m_callback( true );\r\n\t}\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodeconditional.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeConditional final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeConditional( QString name, QVariantMap& blackboard, std::function<BT_RESULT( bool )> callback );\r\n\t~BT_NodeConditional();\r\n\r\n\tBT_RESULT tick();\r\n\r\n\tvoid halt();\r\n\r\n\tBT_Node* addFallback( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addFallbackStar( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addSequence( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addSequenceStar( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addInverter( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addRepeat( QString name, int num )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addRepeatUntilSuccess( QString name, int num )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\r\n\tvoid addTree( BT_Node* tree ) {};\r\n\r\n\tBT_Node* addConditional( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\tBT_Node* addAction( QString name )\r\n\t{\r\n\t\treturn nullptr;\r\n\t};\r\n\r\nprivate:\r\n\tstd::function<BT_RESULT( bool )> m_callback;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodefallback.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodefallback.h\"\r\n\r\nBT_NodeFallback::BT_NodeFallback( QString name, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard )\r\n{\r\n}\r\n\r\nBT_NodeFallback::~BT_NodeFallback()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeFallback::tick()\r\n{\r\n\tm_status = BT_RESULT::RUNNING;\r\n\r\n\tfor ( int index = 0; index < m_children.size(); ++index )\r\n\t{\r\n\t\tBT_RESULT child_status = m_children[index]->tick();\r\n\r\n\t\tif ( child_status == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\t// Suspend execution and return RUNNING.\r\n\t\t\t// At the next tick, index will be the same.\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t\telse if ( child_status == BT_RESULT::SUCCESS )\r\n\t\t{\r\n\t\t\t// Suspend execution and return SUCCESS.\r\n\t\t\t// index is reset and children are halted.\r\n\t\t\thaltAllChildren();\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\t// all the children returned FAILURE. Return FAILURE too.\r\n\thaltAllChildren();\r\n\treturn BT_RESULT::FAILURE;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodefallback.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeFallback final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeFallback( QString name, QVariantMap& blackboard );\r\n\t~BT_NodeFallback();\r\n\r\n\tBT_RESULT tick();\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodefallbackstar.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodefallbackstar.h\"\r\n\r\nBT_NodeFallbackStar::BT_NodeFallbackStar( QString name, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard )\r\n{\r\n}\r\n\r\nBT_NodeFallbackStar::~BT_NodeFallbackStar()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeFallbackStar::tick()\r\n{\r\n\tm_status = BT_RESULT::RUNNING;\r\n\r\n\twhile ( m_index < m_children.size() )\r\n\t{\r\n\t\tBT_RESULT child_status = m_children[m_index]->tick();\r\n\r\n\t\tif ( child_status == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\t// Suspend execution and return RUNNING.\r\n\t\t\t// At the next tick, index will be the same.\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t\telse if ( child_status == BT_RESULT::FAILURE )\r\n\t\t{\r\n\t\t\t// continue the while loop\r\n\t\t\t++m_index;\r\n\t\t}\r\n\t\telse if ( child_status == BT_RESULT::SUCCESS )\r\n\t\t{\r\n\t\t\t// Suspend execution and return SUCCESS.\r\n\t\t\t// At the next tick, index will be the same.\r\n\t\t\thaltAllChildren();\r\n\t\t\tm_index = 0;\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\t// all the children returned FAILURE. Return FAILURE too.\r\n\thaltAllChildren();\r\n\tm_index = 0;\r\n\treturn BT_RESULT::FAILURE;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodefallbackstar.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeFallbackStar final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeFallbackStar( QString name, QVariantMap& blackboard );\r\n\t~BT_NodeFallbackStar();\r\n\r\n\tBT_RESULT tick();\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodeforcefailure.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodeforcefailure.h\"\r\n\r\nBT_NodeForceFailure::BT_NodeForceFailure( QVariantMap& blackboard ) :\r\n\tBT_Node( \"ForceFailure\", blackboard )\r\n{\r\n}\r\n\r\nBT_NodeForceFailure::~BT_NodeForceFailure()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeForceFailure::tick()\r\n{\r\n\tif ( m_children.size() > 0 )\r\n\t{\r\n\t\tBT_RESULT result = m_children[0]->tick();\r\n\t\tif ( result == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodeforcefailure.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeForceFailure final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeForceFailure( QVariantMap& blackboard );\r\n\t~BT_NodeForceFailure();\r\n\r\n\tBT_RESULT tick();\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodeforcesuccess.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodeforcesuccess.h\"\r\n\r\nBT_NodeForceSuccess::BT_NodeForceSuccess( QVariantMap& blackboard ) :\r\n\tBT_Node( \"ForceSuccess\", blackboard )\r\n{\r\n}\r\n\r\nBT_NodeForceSuccess::~BT_NodeForceSuccess()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeForceSuccess::tick()\r\n{\r\n\tif ( m_children.size() > 0 )\r\n\t{\r\n\t\tBT_RESULT result = m_children[0]->tick();\r\n\t\tif ( result == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::SUCCESS;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodeforcesuccess.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeForceSuccess final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeForceSuccess( QVariantMap& blackboard );\r\n\t~BT_NodeForceSuccess();\r\n\r\n\tBT_RESULT tick();\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodeinverter.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodeinverter.h\"\r\n\r\nBT_NodeInverter::BT_NodeInverter( QString name, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard )\r\n{\r\n}\r\n\r\nBT_NodeInverter::~BT_NodeInverter()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeInverter::tick()\r\n{\r\n\tif ( m_children.size() > 0 )\r\n\t{\r\n\t\tBT_RESULT result = m_children[0]->tick();\r\n\t\tif ( result == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\tm_status = BT_RESULT::RUNNING;\r\n\t\t\treturn m_status;\r\n\t\t}\r\n\t\telse if ( result == BT_RESULT::FAILURE )\r\n\t\t{\r\n\t\t\tm_status = BT_RESULT::SUCCESS;\r\n\t\t\treturn m_status;\r\n\t\t}\r\n\t}\r\n\tm_status = BT_RESULT::FAILURE;\r\n\treturn m_status;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodeinverter.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeInverter final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeInverter( QString name, QVariantMap& blackboard );\r\n\t~BT_NodeInverter();\r\n\r\n\tBT_RESULT tick();\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_noderepeat.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_noderepeat.h\"\r\n\r\n#include <QDebug>\r\n\r\nBT_NodeRepeat::BT_NodeRepeat( QString name, int num, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard ),\r\n\tm_num( num )\r\n{\r\n}\r\n\r\nBT_NodeRepeat::~BT_NodeRepeat()\r\n{\r\n}\r\n\r\nQVariantMap BT_NodeRepeat::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Name\", m_name );\r\n\tout.insert( \"ID\", m_index );\r\n\tout.insert( \"Status\", (unsigned char)m_status );\r\n\tout.insert( \"Num\", m_num );\r\n\r\n\tQVariantList childs;\r\n\tfor ( auto child : m_children )\r\n\t{\r\n\t\tchilds.append( child->serialize() );\r\n\t}\r\n\tout.insert( \"Childs\", childs );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid BT_NodeRepeat::deserialize( QVariantMap in )\r\n{\r\n\tif ( m_name != in.value( \"Name\" ).toString() )\r\n\t{\r\n\t\tqDebug() << \"error loading behavior tree state - nodes don't match\";\r\n\t}\r\n\tm_index  = in.value( \"ID\" ).toInt();\r\n\tm_status = (BT_RESULT)in.value( \"Status\" ).toInt();\r\n\tm_num    = in.value( \"Num\" ).toInt();\r\n\r\n\tauto vcl  = in.value( \"Childs\" ).toList();\r\n\tint index = 0;\r\n\tif ( vcl.size() == m_children.size() )\r\n\t{\r\n\r\n\t\tfor ( auto child : m_children )\r\n\t\t{\r\n\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//tree changed between saving and loading, this will have undetermined results\r\n\t\t// TODO throw exception or make config option to allow or deny loading this\r\n\t\tif ( vcl.size() < m_children.size() )\r\n\t\t{\r\n\t\t\tfor ( auto vcm : vcl )\r\n\t\t\t{\r\n\t\t\t\tm_children[index++]->deserialize( vcm.toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto child : m_children )\r\n\t\t\t{\r\n\t\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nBT_RESULT BT_NodeRepeat::tick()\r\n{\r\n\twhile ( m_index < m_num )\r\n\t{\r\n\t\tif ( m_children.size() > 0 )\r\n\t\t{\r\n\t\t\tBT_RESULT result = m_children[0]->tick();\r\n\t\t\tif ( result == BT_RESULT::RUNNING )\r\n\t\t\t{\r\n\t\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t\t}\r\n\t\t\telse if ( result == BT_RESULT::FAILURE )\r\n\t\t\t{\r\n\t\t\t\tm_index = 0;\r\n\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t}\r\n\t\t}\r\n\t\t++m_index;\r\n\t}\r\n\tm_index = 0;\r\n\treturn BT_RESULT::SUCCESS;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_noderepeat.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeRepeat final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeRepeat( QString name, int num, QVariantMap& blackboard );\r\n\t~BT_NodeRepeat();\r\n\r\n\tQVariantMap serialize();\r\n\tvoid deserialize( QVariantMap in );\r\n\r\n\tBT_RESULT tick();\r\n\r\nprivate:\r\n\tint m_num = 0;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_noderepeatuntilsuccess.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_noderepeatuntilsuccess.h\"\r\n\r\n#include <QDebug>\r\n\r\nBT_NodeRepeatUntilSuccess::BT_NodeRepeatUntilSuccess( QString name, int num, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard ),\r\n\tm_num( num )\r\n{\r\n}\r\n\r\nBT_NodeRepeatUntilSuccess::~BT_NodeRepeatUntilSuccess()\r\n{\r\n}\r\n\r\nQVariantMap BT_NodeRepeatUntilSuccess::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Name\", m_name );\r\n\tout.insert( \"ID\", m_index );\r\n\tout.insert( \"Status\", (unsigned char)m_status );\r\n\tout.insert( \"Num\", m_num );\r\n\r\n\tQVariantList childs;\r\n\tfor ( auto child : m_children )\r\n\t{\r\n\t\tchilds.append( child->serialize() );\r\n\t}\r\n\tout.insert( \"Childs\", childs );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid BT_NodeRepeatUntilSuccess::deserialize( QVariantMap in )\r\n{\r\n\tif ( m_name != in.value( \"Name\" ).toString() )\r\n\t{\r\n\t\tqDebug() << \"error loading behavior tree state - nodes don't match\";\r\n\t}\r\n\tm_index  = in.value( \"ID\" ).toInt();\r\n\tm_status = (BT_RESULT)in.value( \"Status\" ).toInt();\r\n\tm_num    = in.value( \"Num\" ).toInt();\r\n\r\n\tauto vcl  = in.value( \"Childs\" ).toList();\r\n\tint index = 0;\r\n\tif ( vcl.size() == m_children.size() )\r\n\t{\r\n\r\n\t\tfor ( auto child : m_children )\r\n\t\t{\r\n\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//tree changed between saving and loading, this will have undetermined results\r\n\t\t// TODO throw exception or make config option to allow or deny loading this\r\n\t\tif ( vcl.size() < m_children.size() )\r\n\t\t{\r\n\t\t\tfor ( auto vcm : vcl )\r\n\t\t\t{\r\n\t\t\t\tm_children[index++]->deserialize( vcm.toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto child : m_children )\r\n\t\t\t{\r\n\t\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nBT_RESULT BT_NodeRepeatUntilSuccess::tick()\r\n{\r\n\twhile ( m_index < m_num )\r\n\t{\r\n\t\tif ( m_children.size() > 0 )\r\n\t\t{\r\n\t\t\tBT_RESULT result = m_children[0]->tick();\r\n\r\n\t\t\tif ( result == BT_RESULT::RUNNING )\r\n\t\t\t{\r\n\t\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t\t}\r\n\t\t\telse if ( result == BT_RESULT::SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tm_index = 0;\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\t\t}\r\n\t\t++m_index;\r\n\t}\r\n\tm_index = 0;\r\n\treturn BT_RESULT::FAILURE;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_noderepeatuntilsuccess.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeRepeatUntilSuccess final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeRepeatUntilSuccess( QString name, int num, QVariantMap& blackboard );\r\n\t~BT_NodeRepeatUntilSuccess();\r\n\r\n\tQVariantMap serialize();\r\n\tvoid deserialize( QVariantMap in );\r\n\r\n\tBT_RESULT tick();\r\n\r\nprivate:\r\n\tint m_num = 0;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodesequence.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodesequence.h\"\r\n\r\nBT_NodeSequence::BT_NodeSequence( QString name, QVariantMap& blackboard ) :\r\n\tBT_Node( name, blackboard )\r\n{\r\n}\r\n\r\nBT_NodeSequence::~BT_NodeSequence()\r\n{\r\n}\r\n\r\nBT_RESULT BT_NodeSequence::tick()\r\n{\r\n\tm_status = BT_RESULT::RUNNING;\r\n\r\n\tfor ( int index = 0; index < m_children.size(); ++index )\r\n\t{\r\n\t\tBT_RESULT child_status = m_children[index]->tick();\r\n\r\n\t\tif ( child_status == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\t// Suspend execution and return RUNNING.\r\n\t\t\t// At the next tick, index will be the same.\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t\telse if ( child_status == BT_RESULT::FAILURE )\r\n\t\t{\r\n\t\t\t// Suspend execution and return FAILURE.\r\n\t\t\t// index is reset and children are halted.\r\n\t\t\thaltAllChildren();\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t}\r\n\t// all the children returned success. Return SUCCESS too.\r\n\thaltAllChildren();\r\n\treturn BT_RESULT::SUCCESS;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodesequence.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeSequence final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeSequence( QString name, QVariantMap& blackboard );\r\n\t~BT_NodeSequence();\r\n\r\n\tBT_RESULT tick();\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_nodesequencestar.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"bt_nodesequencestar.h\"\r\n\r\n#include <QDebug>\r\n\r\nBT_NodeSequenceStar::BT_NodeSequenceStar( QString name, QVariantMap& blackboard, bool resetOnFailure ) :\r\n\tBT_Node( name, blackboard ),\r\n\tm_resetOnFailure( resetOnFailure )\r\n{\r\n}\r\n\r\nBT_NodeSequenceStar::~BT_NodeSequenceStar()\r\n{\r\n}\r\n\r\nQVariantMap BT_NodeSequenceStar::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Name\", m_name );\r\n\tout.insert( \"ID\", m_index );\r\n\tout.insert( \"Status\", (unsigned char)m_status );\r\n\tout.insert( \"RoF\", m_resetOnFailure );\r\n\r\n\tQVariantList childs;\r\n\tfor ( auto child : m_children )\r\n\t{\r\n\t\tchilds.append( child->serialize() );\r\n\t}\r\n\tout.insert( \"Childs\", childs );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid BT_NodeSequenceStar::deserialize( QVariantMap in )\r\n{\r\n\tif ( m_name != in.value( \"Name\" ).toString() )\r\n\t{\r\n\t\tqDebug() << \"error loading behavior tree state - nodes don't match\";\r\n\t}\r\n\tm_index          = in.value( \"ID\" ).toInt();\r\n\tm_status         = (BT_RESULT)in.value( \"Status\" ).toInt();\r\n\tm_resetOnFailure = in.value( \"RoF\" ).toBool();\r\n\r\n\tauto vcl  = in.value( \"Childs\" ).toList();\r\n\tint index = 0;\r\n\tif ( vcl.size() == m_children.size() )\r\n\t{\r\n\r\n\t\tfor ( auto child : m_children )\r\n\t\t{\r\n\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//tree changed between saving and loading, this will have undetermined results\r\n\t\t// TODO throw exception or make config option to allow or deny loading this\r\n\t\tif ( vcl.size() < m_children.size() )\r\n\t\t{\r\n\t\t\tfor ( auto vcm : vcl )\r\n\t\t\t{\r\n\t\t\t\tm_children[index++]->deserialize( vcm.toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto child : m_children )\r\n\t\t\t{\r\n\t\t\t\tchild->deserialize( vcl[index++].toMap() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nBT_RESULT BT_NodeSequenceStar::tick()\r\n{\r\n\tm_status = BT_RESULT::RUNNING;\r\n\r\n\twhile ( m_index < m_children.size() )\r\n\t{\r\n\t\tBT_RESULT child_status = m_children[m_index]->tick();\r\n\r\n\t\tif ( child_status == BT_RESULT::RUNNING )\r\n\t\t{\r\n\t\t\t// Suspend execution and return RUNNING.\r\n\t\t\t// At the next tick, index will be the same.\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t\telse if ( child_status == BT_RESULT::SUCCESS )\r\n\t\t{\r\n\t\t\t// continue the while loop\r\n\t\t\t++m_index;\r\n\t\t}\r\n\t\telse if ( child_status == BT_RESULT::FAILURE )\r\n\t\t{\r\n\t\t\t// Suspend execution and return FAILURE.\r\n\t\t\t// At the next tick, index will be the same.\r\n\t\t\t//if( m_resetOnFailure )\r\n\t\t\t{\r\n\t\t\t\thaltAllChildren();\r\n\t\t\t\tm_index = 0;\r\n\t\t\t}\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t}\r\n\t// all the children returned success. Return SUCCESS too.\r\n\tm_index = 0;\r\n\thaltAllChildren();\r\n\treturn BT_RESULT::SUCCESS;\r\n}"
  },
  {
    "path": "src/base/behaviortree/bt_nodesequencestar.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"bt_node.h\"\r\n\r\nclass BT_NodeSequenceStar final : public BT_Node\r\n{\r\npublic:\r\n\tBT_NodeSequenceStar( QString name, QVariantMap& blackboard, bool resetOnFailure );\r\n\t~BT_NodeSequenceStar();\r\n\r\n\tQVariantMap serialize();\r\n\tvoid deserialize( QVariantMap in );\r\n\r\n\tBT_RESULT tick();\r\n\r\nprivate:\r\n\tbool m_resetOnFailure = true;\r\n};\r\n"
  },
  {
    "path": "src/base/behaviortree/bt_tree.h",
    "content": "#include \"bt_factory.h\"\r\n#include \"bt_nodeaction.h\"\r\n#include \"bt_nodebbprecondition.h\"\r\n#include \"bt_nodeconditional.h\"\r\n#include \"bt_nodefallback.h\"\r\n#include \"bt_nodefallbackstar.h\"\r\n#include \"bt_nodeforcefailure.h\"\r\n#include \"bt_nodeforcesuccess.h\"\r\n#include \"bt_nodeinverter.h\"\r\n#include \"bt_noderepeat.h\"\r\n#include \"bt_noderepeatuntilsuccess.h\"\r\n#include \"bt_nodesequence.h\"\r\n#include \"bt_nodesequencestar.h\"\r\n"
  },
  {
    "path": "src/base/config.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"config.h\"\r\n\r\n#include \"../base/io.h\"\r\n\r\n#include <QDebug>\r\n#include <QDir>\r\n#include <QFile>\r\n#include <QJsonArray>\r\n#include <QJsonDocument>\r\n#include <QStandardPaths>\r\n\r\nConfig::Config()\r\n{\r\n\tQMutexLocker lock( &m_mutex );\r\n\tIO::createFolders();\r\n\r\n\t//check if Ingnomia folder in /Documents/My Games exist\r\n\tQString folder = IO::getDataFolder();\r\n\tbool ok        = true;\r\n\tQJsonDocument jd;\r\n\r\n\tif ( !IO::loadFile( folder + \"settings/config.json\", jd ) )\r\n\t{\r\n\t\tif( !IO::loadOriginalConfig( jd ) )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_settings = jd.toVariant().toMap();\r\n\r\n\tif( m_settings.keys().size() == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\r\n\t/*\r\n\tif ( !IO::loadFile( folder + \"settings/keybindings.json\", jd ) )\r\n\t{\r\n\t\tif ( QFile::exists( \"keybindings.json\" ) )\r\n\t\t{\r\n\t\t\tQFile::copy( \"keybindings.json\", folder + \"settings/keybindings.json\" );\r\n\t\t}\r\n\t}\r\n\t*/\r\n\t// add values to exisiting confings\r\n\tif ( !m_settings.contains( \"XpMod\" ) )\r\n\t{\r\n\t\tm_settings.insert( \"XpMod\", 250. );\r\n\t}\r\n\r\n\tif ( !m_settings.contains( \"fow\" ) )\r\n\t{\r\n\t\tm_settings.insert( \"fow\", true );\r\n\t}\r\n\r\n\tif ( !m_settings.contains( \"AutoSaveInterval\" ) )\r\n\t{\r\n\t\tm_settings.insert( \"AutoSaveInterval\", 3 );\r\n\t}\r\n\tif ( !m_settings.contains( \"uiscale\" ) )\r\n\t{\r\n\t\tm_settings.insert( \"uiscale\", 1.0 );\r\n\t}\r\n\tm_settings.insert( \"dataPath\", QCoreApplication::applicationDirPath() + \"/content\" );\r\n\r\n\tm_valid = true;\r\n\r\n}\r\n\r\nConfig::~Config()\r\n{\r\n}\r\n\r\nQVariant Config::get( QString key )\r\n{\r\n\tQMutexLocker lock( &m_mutex );\r\n\tif ( m_settings.contains( key ) )\r\n\t{\r\n\t\tQVariant out = m_settings[key];\r\n\t\treturn out;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn QVariant();\r\n\t}\r\n}\r\n\r\nvoid Config::set( QString key, QVariant value )\r\n{\r\n\tQMutexLocker lock( &m_mutex );\r\n\tconst auto oldValue = m_settings[key];\r\n\tif (oldValue != value)\r\n\t{\r\n\t\tm_settings[key] = value;\r\n\t\tIO::saveConfig();\r\n\r\n\t\tqDebug() << \"Update config\" << key << \"=\" << value << \"(was\" << oldValue << \")\";\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/base/config.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef CONFIG_H_\r\n#define CONFIG_H_\r\n\r\n#include <QHash>\r\n#include <QMutex>\r\n#include <QString>\r\n#include <QVariant>\r\n#include <QVariantMap>\r\n\r\nclass Config\r\n{\r\nprivate:\r\n\tQVariantMap m_settings;\r\n\tbool m_valid = false;\r\n\tQMutex m_mutex;\r\n\r\npublic:\r\n\tConfig();\r\n\t~Config();\r\n\r\n\tQVariant get( QString key );\r\n\tvoid set( QString key, QVariant value );\r\n\r\n\tQVariantMap& object()\r\n\t{\r\n\t\treturn m_settings;\r\n\t}\r\n\tvoid setObject( QVariantMap obj )\r\n\t{\r\n\t\tm_settings = obj;\r\n\t}\r\n\r\n\tbool valid()\r\n\t{\r\n\t\treturn m_valid;\r\n\t}\r\n};\r\n\r\n#endif /* CONFIG_H_ */\r\n"
  },
  {
    "path": "src/base/counter.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMap>\r\n\r\ntemplate <class T>\r\nclass Counter\r\n{\r\npublic:\r\n\tvoid add( T id )\r\n\t{\r\n\t\tunsigned int val = m_counts.value( id );\r\n\t\t++val;\r\n\t\tm_counts.insert( id, val );\r\n\t}\r\n\r\n\tQList<T> keys()\r\n\t{\r\n\t\treturn m_counts.keys();\r\n\t}\r\n\r\n\tunsigned int count( T key )\r\n\t{\r\n\t\treturn m_counts.value( key );\r\n\t}\r\n\r\n\tvoid reset()\r\n\t{\r\n\t\tm_counts.clear();\r\n\t}\r\n\r\nprivate:\r\n\tQMap<T, unsigned int> m_counts;\r\n};"
  },
  {
    "path": "src/base/crashhandler.cpp",
    "content": "#include \"crashhandler.h\"\n\n#include \"../version.h\"\n#include \"io.h\"\n\n#if defined( PROJECT_VERSION) && defined( BUILD_ID )\n#define BUILD_VERSION PROJECT_VERSION \"-\" BUILD_ID\n#endif\n\n#if defined( HAVE_BUGSPLAT ) && defined( BUGSPLAT_DB ) && defined( BUILD_VERSION )\n#define USE_BUGSPLAT 1\n#endif\n\n#ifdef USE_BUGSPLAT\n#include <BugSplat.h>\n\n#define WIDEN2( x ) L##x\n#define WIDEN( x )  WIDEN2( x )\n\nvoid setupCrashHandler()\n{\n\tstatic MiniDmpSender* mpSender = new MiniDmpSender( WIDEN( BUGSPLAT_DB ), WIDEN( PROJECT_NAME ), WIDEN( BUILD_VERSION ), NULL, MDSF_USEGUARDMEMORY | MDSF_LOGFILE | MDSF_DETECTHANGS | MDSF_SUSPENDALLTHREADS | MDSF_PREVENTHIJACKING );\n\t// The following calls add support for collecting crashes for abort(), vectored exceptions, out of memory,\n\t// pure virtual function calls, and for invalid parameters for OS functions.\n\t// These calls should be used for each module that links with a separate copy of the CRT.\n\tSetGlobalCRTExceptionBehavior();\n\tSetPerThreadCRTExceptionBehavior(); // This call needed in each thread of your app\n\n\t// A guard buffer of 20mb is needed to catch OutOfMemory crashes\n\tmpSender->setGuardByteBufferSize( 20 * 1024 * 1024 );\n\n\t// Include main log file\n\tQString logFile = IO::getDataFolder() + \"/log.txt\";\n\tmpSender->sendAdditionalFile( logFile.replace( '/', '\\\\' ).toStdWString().c_str() );\n}\n#else\nvoid setupCrashHandler()\n{\n}\n#endif // USE_BUGSPLAT"
  },
  {
    "path": "src/base/crashhandler.h",
    "content": "#pragma once\nvoid setupCrashHandler();"
  },
  {
    "path": "src/base/db.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"db.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../game/item.h\"\r\n\r\n#include <QDebug>\r\n#include <QMutexLocker>\r\n#include <QSqlError>\r\n#include <QSqlField>\r\n#include <QSqlQuery>\r\n#include <QSqlRecord>\r\n#include <QThread>\r\n\r\nQMutex DB::m_mutex;\r\nint DB::accessCounter = 0;\r\nCounter<QString> DB::m_counter;\r\nQMap<Qt::HANDLE, QSqlDatabase> DB::m_connections;\r\n\r\n\r\nQHash<QString, QSharedPointer<DBS::Workshop>> DB::m_workshops;\r\nQHash<QString, QSharedPointer<DBS::Job>> DB::m_jobs;\r\n\r\nvoid DB::init()\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\r\n\tQFile file( Global::cfg->get( \"dataPath\" ).toString() + \"/db/\" + \"ingnomia.db.sql\" );\r\n    file.open(QIODevice::ReadOnly | QIODevice::Text);\r\n    QString sql = file.readAll();\r\n    file.close();\r\n\r\n\tQSqlQuery destQuery( getDB() );\r\n\r\n\tauto statements = sql.split( \";\" );\r\n\tfor( auto s: statements )\r\n\t{\r\n\t\tif ( !destQuery.exec( s ) )\r\n\t\t{\r\n\t\t\tqDebug() << destQuery.lastError();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid DB::initStructs()\r\n{\r\n\tm_workshops.clear();\r\n\tauto rows = DB::selectRows( \"Workshops\" );\r\n\tfor( const auto& row : rows )\r\n\t{\r\n\t\tQSharedPointer<DBS::Workshop> ws( new DBS::Workshop );\r\n\t\tws->ID = row.value( \"ID\" ).toString();\r\n\t\tws->Crafts = row.value( \"Crafts\" ).toString().split( \"|\" );\r\n\t\tws->GUI = row.value( \"GUI\" ).toString();\r\n\t\tws->InputTile = Position( row.value( \"InputTile\" ) );\r\n\t\tws->OutputTile = row.value( \"OutputTile\" ).toString();\r\n\t\tws->Size = row.value( \"Size\" ).toString();\r\n\t\tws->NoAutoGenerate = row.value( \"NoAutoGenerate\" ).toBool();\r\n\t\tws->Icon = row.value( \"Icon\" ).toString();\r\n\t\tws->Tab = row.value( \"Tab\" ).toString();\r\n\t\t\r\n\t\tauto crows = DB::selectRows( \"Workshops_Components\", ws->ID );\r\n\t\tfor( const auto& crow : crows )\r\n\t\t{\r\n\t\t\tDBS::Workshop_Component wsc;\r\n\t\t\twsc.Amount = crow.value( \"Amount\" ).toInt();\r\n\t\t\twsc.ItemID = crow.value( \"ItemID\" ).toString();\r\n\t\t\twsc.MaterialItem = crow.value( \"MaterialItem\" ).toString();\r\n\t\t\twsc.Offset = Position( crow.value( \"Offset\" ) );\r\n\t\t\twsc.Required = crow.value( \"Required\" ).toString();\r\n\t\t\twsc.Forbidden = crow.value( \"Forbidden\" ).toString();\r\n\t\t\twsc.SpriteID = crow.value( \"SpriteID\" ).toString();\r\n\t\t\twsc.SpriteID2 = crow.value( \"SpriteID2\" ).toString();\r\n\t\t\twsc.Type = crow.value( \"Type\" ).toString();\r\n\t\t\twsc.WallRotation = crow.value( \"WallRotation\" ).toString();\r\n\t\t\twsc.IsFloor = crow.value( \"IsFloor\" ).toBool();\r\n\t\t\tws->components.append( wsc );\r\n\t\t}\r\n\t\t\r\n\t\tm_workshops.insert( ws->ID, ws );\r\n\t}\r\n\r\n\tm_jobs.clear();\r\n\trows = DB::selectRows( \"Jobs\" );\r\n\tfor( const auto& row : rows )\r\n\t{\r\n\t\tQSharedPointer<DBS::Job> job( new DBS::Job );\r\n\t\tjob->ID = row.value( \"ID\" ).toString();\r\n\t\tjob->ConstructionType = row.value( \"ConstructionType\" ).toString();\r\n\t\tjob->MayTrapGnome = row.value( \"MayTrapGnome\" ).toBool();\r\n\t\tjob->RequiredToolItemID = row.value( \"RequiredToolItemID\" ).toString();\r\n\t\tjob->RequiredToolLevel = row.value( \"RequiredToolLevel\" ).toString();\r\n\t\tjob->SkillGain = row.value( \"SkillGain\" ).toString();\r\n\t\tjob->SkillID = row.value( \"SkillID\" ).toString();\r\n\t\tjob->TechGain = row.value( \"TechGain\" ).toString();\r\n\t\tfor( auto spos : row.value( \"WorkPosition\" ).toString().split( \"|\" ) )\r\n\t\t{\r\n\t\t\tjob->WorkPositions.append( Position( spos ) );\r\n\t\t}\r\n\t\tauto trows = DB::selectRows( \"Jobs_Tasks\" );\r\n\t\tfor( const auto& trow : trows )\r\n\t\t{\r\n\t\t\tDBS::Job_Task jt;\r\n\t\t\tjt.ConstructionID = trow.value( \"ConstructionID\" ).toString();\r\n\t\t\tjt.Duration = trow.value( \"Duration\" ).toInt();\r\n\t\t\tjt.Material = trow.value( \"Material\" ).toString();\r\n\t\t\tjt.Offset = Position( trow.value( \"Offset\" ) );\r\n\t\t\tjt.Task = trow.value( \"Task\" ).toString();\r\n\t\t\tjob->tasks.append( jt );\r\n\t\t}\r\n\t\tauto srows = DB::selectRows( \"Jobs_SpriteID\" );\r\n\t\tfor( const auto& srow : srows )\r\n\t\t{\r\n\t\t\tDBS::Job_SpriteID js;\r\n\t\t\tjs.Offset = Position( srow.value( \"Offset\" ) );\r\n\t\t\tjs.Rotate = srow.value( \"Rotate\" ).toBool();\r\n\t\t\tjs.SpriteID = srow.value( \"SpriteID\" ).toString();\r\n\t\t\tjs.Type = srow.value( \"Type\" ).toString();\r\n\t\t\tjob->sprites.append( js );\r\n\t\t}\r\n\t\tm_jobs.insert( job->ID, job );\r\n\t}\r\n}\r\n\r\nQSqlDatabase& DB::getDB()\r\n{\r\n\tauto thread = QThread::currentThreadId();\r\n\tif ( !m_connections.contains( thread ) )\r\n\t{\r\n\t\tauto db = QSqlDatabase::addDatabase( \"QSQLITE\", QString::number( reinterpret_cast<long long>( thread ) ) );\r\n\t\tdb.setConnectOptions( \"QSQLITE_OPEN_URI;QSQLITE_ENABLE_SHARED_CACHE\" );\r\n\t\tdb.setDatabaseName( \"file:game?mode=memory&cache=shared\" );\r\n\t\tif ( !db.open() )\r\n\t\t{\r\n\t\t\tqDebug() << \"Error: create in memory db\";\r\n\t\t\tabort();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tqDebug() << \"Memory DB: connection ok\";\r\n\t\t}\r\n\t\tm_connections[thread] = db;\r\n\t}\r\n\treturn m_connections[thread];\r\n}\r\n\r\nint DB::getAccessCounter()\r\n{\r\n\tint tmp       = accessCounter;\r\n\taccessCounter = 0;\r\n\treturn tmp;\r\n}\r\n\r\nQVariant DB::execQuery( QString queryString )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( queryString ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << queryString;\r\n\t}\r\n\r\n\treturn QVariant();\r\n}\r\n\r\nQVariantList DB::execQuery2( QString queryString )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tQVariantList out;\r\n\tif ( query.exec( queryString ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tout.append( query.value( 0 ) );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << queryString;\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQSqlQuery DB::execQuery3( QString queryString, bool& ok )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( queryString ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tok = true;\r\n\t\treturn query;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << queryString;\r\n\t}\r\n\r\n\tok = false;\r\n\treturn query;\r\n}\r\n\r\nQVariant DB::select( QString selectCol, QString table, QString whereVal )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE ID = \" + \"\\\"\" + whereVal + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE ID = \" + \"\\\"\" + whereVal + \"\\\"\";\r\n\t}\r\n\r\n\treturn QVariant();\r\n}\r\n\r\nQVariant DB::select( QString selectCol, QString table, int whereVal )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE rowid = \" + \"\\\"\" + QString::number( whereVal ) + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE rowid = \" + \"\\\"\" + QString::number( whereVal ) + \"\\\"\";\r\n\t}\r\n\r\n\treturn QVariant();\r\n}\r\n\r\nQVariantList DB::select2( QString selectCol, QString table, QString whereCol, QString whereVal )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tQVariantList out;\r\n\tif ( query.exec( \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tout.append( query.value( 0 ) );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\"\";\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQVariantList DB::select2( QString selectCol, QString table, QString whereCol, int whereVal )\r\n{\r\n\treturn select2( selectCol, table, whereCol, QString::number( whereVal ) );\r\n}\r\n\r\nQVariantList DB::select2( QString selectCol, QString table, QString whereCol, float whereVal )\r\n{\r\n\treturn select2( selectCol, table, whereCol, QString::number( whereVal ) );\r\n}\r\n\r\nQVariant DB::select3( QString selectCol, QString table, QString whereCol, QString whereVal, QString whereCol2, QString whereVal2 )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tQVariant out;\r\n\tif ( query.exec( \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\" AND \\\"\" + whereCol2 + \"\\\" = \\\"\" + whereVal2 + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT \\\"\" + selectCol + \"\\\" FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\" AND \\\"\" + whereCol2 + \"\\\" = \\\"\" + whereVal2 + \"\\\"\";\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQStringList DB::ids( QString table )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQStringList out;\r\n\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT ID FROM \" + table ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tout.append( query.value( 0 ).toString() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT ID FROM \" + table;\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQStringList DB::ids( QString table, QString whereCol, QString whereVal )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQStringList out;\r\n\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT ID FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tout.append( query.value( 0 ).toString() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << getDB().tables();\r\n\t\tqDebug() << \"SELECT ID FROM \" + table;\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nint DB::numRows( QString table )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT COUNT(*) FROM \" + table ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 ).toInt();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT COUNT(*) FROM \" + table;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint DB::numRows( QString table, QString id )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT COUNT(*) FROM \" + table + \" WHERE ID = \\\"\" + id + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 ).toInt();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT COUNT(*) FROM \" + table + \" WHERE ID = \\\"\" + id + \"\\\"\";\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint DB::numRows2( QString table, QString id )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT COUNT(*) FROM \" + table + \" WHERE BaseSprite = \\\"\" + id + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\treturn query.value( 0 ).toInt();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT COUNT(*) FROM \" + table + \" WHERE BaseSprite = \\\"\" + id + \"\\\"\";\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQVariantMap DB::selectRow( QString table, QString whereVal )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT * FROM \" + table + \" WHERE ID = \\\"\" + whereVal + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tif ( query.next() )\r\n\t\t{\r\n\t\t\tauto record = getDB().record( table );\r\n\t\t\tint count   = record.count();\r\n\r\n\t\t\tQVariantMap out;\r\n\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t{\r\n\t\t\t\tout.insert( record.field( i ).name(), query.value( record.field( i ).name() ) );\r\n\t\t\t}\r\n\t\t\treturn out;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT * FROM \" + table + \" WHERE ID = \\\"\" + whereVal + \"\\\"\";\r\n\t}\r\n\r\n\treturn QVariantMap();\r\n}\r\n\r\nQList<QVariantMap> DB::selectRows( QString table, QString whereCol, QString whereVal )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQList<QVariantMap> out;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT * FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tQVariantMap result;\r\n\t\t\tauto record = getDB().record( table );\r\n\t\t\tint count   = record.count();\r\n\r\n\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t{\r\n\t\t\t\tresult.insert( record.field( i ).name(), query.value( record.field( i ).name() ) );\r\n\t\t\t}\r\n\t\t\tout.append( result );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT * FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\"\";\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<QVariantMap> DB::selectRows( QString table, QString whereCol, QString whereVal, QString whereCol2, QString whereVal2 )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQSqlQuery query( getDB() );\r\n\tQList<QVariantMap> out;\r\n\tif ( query.exec( \"SELECT * FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\" AND \\\"\" + whereCol2 + \"\\\" = \\\"\" + whereVal2 + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tQVariantMap result;\r\n\t\t\tauto record = getDB().record( table );\r\n\t\t\tint count   = record.count();\r\n\r\n\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t{\r\n\t\t\t\tresult.insert( record.field( i ).name(), query.value( record.field( i ).name() ) );\r\n\t\t\t}\r\n\t\t\tout.append( result );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT * FROM \" + table + \" WHERE \\\"\" + whereCol + \"\\\" = \\\"\" + whereVal + \"\\\" AND \\\"\" + whereCol2 + \"\\\" = \\\"\" + whereVal2 + \"\\\"\";\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\n\r\nQList<QVariantMap> DB::selectRows( QString table )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQList<QVariantMap> out;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT * FROM \" + table ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tQVariantMap result;\r\n\t\t\tauto record = getDB().record( table );\r\n\t\t\tint count   = record.count();\r\n\r\n\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t{\r\n\t\t\t\tresult.insert( record.field( i ).name(), query.value( record.field( i ).name() ) );\r\n\t\t\t}\r\n\t\t\tout.append( result );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT * FROM \" + table;\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<QVariantMap> DB::selectRows( QString table, QString id )\r\n{\r\n\tQMutexLocker lock( &DB::m_mutex );\r\n\t++accessCounter;\r\n\tQList<QVariantMap> out;\r\n\tQSqlQuery query( getDB() );\r\n\tif ( query.exec( \"SELECT * FROM \" + table + \" WHERE ID = \\\"\" + id + \"\\\"\" ) )\r\n\t{\r\n\t\tm_counter.add( query.lastQuery() );\r\n\t\tauto record = query.record();\r\n\t\tint count   = record.count();\r\n\t\twhile ( query.next() )\r\n\t\t{\r\n\t\t\tQVariantMap result;\r\n\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t{\r\n\t\t\t\tresult.insert( record.field( i ).name(), query.value( record.field( i ).name() ) );\r\n\t\t\t}\r\n\t\t\tout.append( result );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"sql error:  \" << query.lastError();\r\n\t\tqDebug() << \"SELECT * FROM \" + table + \" WHERE ID = \\\"\" + id + \"\\\"\";\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nCounter<QString>& DB::getQueryCounter()\r\n{\r\n\treturn m_counter;\r\n}\r\n\r\nQStringList DB::tables()\r\n{\r\n\treturn getDB().tables();\r\n}\r\n\r\nbool DB::updateRow( QString table, QVariantMap values )\r\n{\r\n\tvalues.remove( \"Mod\" );\r\n\tQString id = values.value( \"ID\" ).toString();\r\n\r\n\tQString query = \"UPDATE \" + table + \" SET \";\r\n\tfor ( auto key : values.keys() )\r\n\t{\r\n\t\tif ( key != \"ID\" )\r\n\t\t{\r\n\t\t\tquery += key + \" = '\";\r\n\t\t\tquery += values[key].toString();\r\n\t\t\tquery += \"', \";\r\n\t\t}\r\n\t}\r\n\tquery.chop( 2 );\r\n\tquery += \" WHERE ID = \";\r\n\tquery += \"'\";\r\n\tquery += values.value( \"ID\" ).toString();\r\n\tquery += \"', \";\r\n\r\n\tquery.chop( 2 );\r\n\r\n\tbool ok = false;\r\n\tDB::execQuery3( query, ok );\r\n\treturn ok;\r\n}\r\n\r\nbool DB::addRow( QString table, QVariantMap values )\r\n{\r\n\tvalues.remove( \"Mod\" );\r\n\tQString query = \"INSERT INTO \" + table + \" ( \";\r\n\r\n\tQString query2 = \"VALUES ( \";\r\n\tfor ( auto key : values.keys() )\r\n\t{\r\n\t\tquery += key;\r\n\t\tquery += \", \";\r\n\r\n\t\tquery2 += \"'\";\r\n\t\tquery2 += values[key].toString();\r\n\t\tquery2 += \"', \";\r\n\t}\r\n\tquery.chop( 2 );\r\n\tquery += \" ) \";\r\n\tquery2.chop( 2 );\r\n\tquery2 += \" )\";\r\n\r\n\t//qDebug() << query + query2;\r\n\r\n\tbool ok = false;\r\n\tDB::execQuery3( query + query2, ok );\r\n\treturn ok;\r\n}\r\n\r\nbool DB::removeRows( QString table, QString id )\r\n{\r\n\tQString query = \"DELETE FROM $TABLE WHERE ID = $ID\";\r\n\tquery.replace( \"$TABLE\", table );\r\n\tquery.replace( \"$ID\", id );\r\n\r\n\tbool ok = false;\r\n\tDB::execQuery3( query, ok );\r\n\treturn ok;\r\n}\r\n\r\nbool DB::addTranslation( QString id, QString text )\r\n{\r\n\tQString query = \"INSERT INTO Translation ( ID, Text ) VALUES ( \\\"%1\\\", \\\"%2\\\" )\";\r\n\tquery         = query.arg( id, text );\r\n\tbool ok;\r\n\tDB::execQuery3( query, ok );\r\n\treturn ok;\r\n}\r\n\r\nQSharedPointer<DBS::Workshop> DB::workshop( QString id )\r\n{\r\n\tif( DB::m_workshops.contains( id ) )\r\n\t{\r\n\t\treturn DB::m_workshops.value( id );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQSharedPointer<DBS::Job> DB::job( QString id )\r\n{\r\n\tif( DB::m_jobs.contains( id ) )\r\n\t{\r\n\t\treturn DB::m_jobs.value( id );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQList<QString> DB::jobIds()\r\n{\r\n\treturn DB::m_jobs.keys();\r\n}"
  },
  {
    "path": "src/base/db.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/counter.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/dbstructs.h\"\r\n#include \"../base/position.h\"\r\n\r\n#include <QList>\r\n#include <QMutex>\r\n#include <QSqlDatabase>\r\n#include <QVariant>\r\n\r\ntypedef DBHelper DBH;\r\n\r\nclass Item;\r\n\r\nclass DB\r\n{\r\npublic:\r\n\tstatic void init();\r\n\tstatic void initStructs();\r\n\r\n\tstatic QVariant execQuery( QString query );\r\n\tstatic QVariantList execQuery2( QString query );\r\n\tstatic QSqlQuery execQuery3( QString query, bool& ok );\r\n\r\n\tstatic QVariant select( QString selectCol, QString table, QString whereVal );\r\n\tstatic QVariant select( QString selectCol, QString table, int whereVal );\r\n\r\n\tstatic QVariantList select2( QString selectCol, QString table, QString whereCol, QString whereVal );\r\n\tstatic QVariantList select2( QString selectCol, QString table, QString whereCol, int whereVal );\r\n\tstatic QVariantList select2( QString selectCol, QString table, QString whereCol, float whereVal );\r\n\r\n\tstatic QVariant select3( QString selectCol, QString table, QString whereCol, QString whereVal, QString whereCol2, QString whereVal2 );\r\n\t\r\n\tstatic QStringList ids( QString table );\r\n\tstatic QStringList ids( QString table, QString whereCol, QString whereVal );\r\n\tstatic int numRows( QString table );\r\n\tstatic int numRows( QString table, QString id );\r\n\tstatic int numRows2( QString table, QString bsid );\r\n\r\n\tstatic QVariantMap selectRow( QString table, QString whereVal );\r\n\tstatic QList<QVariantMap> selectRows( QString table, QString whereCol, QString whereVal );\r\n\tstatic QList<QVariantMap> selectRows( QString table, QString whereCol, QString whereVal, QString whereCol2, QString whereVal2 );\r\n\tstatic QList<QVariantMap> selectRows( QString table );\r\n\tstatic QList<QVariantMap> selectRows( QString table, QString id );\r\n\r\n\tstatic int getAccessCounter();\r\n\tstatic Counter<QString>& getQueryCounter();\r\n\r\n\tstatic QStringList tables();\r\n\r\n\tstatic bool updateRow( QString table, QVariantMap values );\r\n\tstatic bool addRow( QString table, QVariantMap values );\r\n\tstatic bool removeRows( QString table, QString id );\r\n\tstatic bool addTranslation( QString id, QString text );\r\n\r\n\tstatic QSharedPointer<DBS::Workshop> workshop( QString id );\r\n\tstatic QSharedPointer<DBS::Job> job( QString id );\r\n\tstatic QList<QString> jobIds();\r\n\r\nprivate:\r\n\tstatic QSqlDatabase& getDB();\r\n\r\n\tstatic QMutex m_mutex;\r\n\r\n\tstatic int accessCounter;\r\n\r\n\tstatic Counter<QString> m_counter;\r\n\r\n\tstatic QMap<Qt::HANDLE, QSqlDatabase> m_connections;\r\n\r\n\tstatic QHash<QString, QSharedPointer<DBS::Workshop>> m_workshops;\r\n\tstatic QHash<QString, QSharedPointer<DBS::Job>> m_jobs;\r\n\r\n\tDB()  = delete;\r\n\t~DB() = delete;\r\n};\r\n"
  },
  {
    "path": "src/base/dbhelper.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"dbhelper.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n\r\nQMap<QString, QString> DBHelper::m_spriteIDCache;\r\nQMap<QString, bool> DBHelper::m_spriteIsRandomCache;\r\nQMap<QString, bool> DBHelper::m_spriteHasAnimCache;\r\nQMap<QString, QString> DBHelper::m_materialColorCache;\r\nQMap<QString, int> DBHelper::m_materialToolLevelCache;\r\nQMap<int, bool> DBHelper::m_itemIsContainerCache;\r\nQMap<int, QString> DBHelper::m_qualitySIDCache;\r\nQMap<int, float> DBHelper::m_qualityModCache;\r\nQMap<QString, QString> DBHelper::m_itemGroupCache;\r\nQMap<QString, QMap<QString, QMultiMap<QString, QString>>> DBHelper::m_workshopCraftResults;\r\n\r\nQMutex DBHelper::m_mutex;\r\n\r\n/*\r\nQStringList DBHelper::getWorkPositions( QString jobID )\r\n{\r\n\tQString wps = DB::select( \"WorkPosition\", \"Jobs\", jobID ).toString();\r\n\treturn wps.split( \"|\" );\r\n}\r\n*/\r\n\r\nQString DBH::spriteID( QString itemID )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tif ( m_spriteIDCache.contains( itemID ) )\r\n\t{\r\n\t\treturn m_spriteIDCache.value( itemID );\r\n\t}\r\n\tQString spriteID = DB::select( \"SpriteID\", \"Items\", itemID ).toString();\r\n\tm_spriteIDCache.insert( itemID, spriteID );\r\n\treturn spriteID;\r\n}\r\n\r\nbool DBHelper::spriteIsRandom( QString spriteID )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tif ( m_spriteIsRandomCache.contains( spriteID ) )\r\n\t{\r\n\t\treturn m_spriteIsRandomCache.value( spriteID );\r\n\t}\r\n\tbool isRandom = DB::select( \"HasRandom\", \"Sprites\", spriteID ).toBool();\r\n\tm_spriteIsRandomCache.insert( spriteID, isRandom );\r\n\treturn isRandom;\r\n}\r\n\r\nbool DBHelper::spriteHasAnim( QString spriteID )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tif ( m_spriteHasAnimCache.contains( spriteID ) )\r\n\t{\r\n\t\treturn m_spriteHasAnimCache.value( spriteID );\r\n\t}\r\n\tbool hasAnim = DB::select( \"Anim\", \"Sprites\", spriteID ).toBool();\r\n\tm_spriteHasAnimCache.insert( spriteID, hasAnim );\r\n\treturn hasAnim;\r\n}\r\n\r\nQString DBHelper::materialColor( QString materialID )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tif ( m_materialColorCache.contains( materialID ) )\r\n\t{\r\n\t\treturn m_materialColorCache.value( materialID );\r\n\t}\r\n\tQString color = DB::select( \"Color\", \"Materials\", materialID ).toString();\r\n\tm_materialColorCache.insert( materialID, color );\r\n\treturn color;\r\n}\r\n\r\nint DBHelper::materialToolLevel( QString material )\r\n{\r\n\tif ( m_materialToolLevelCache.contains( material ) )\r\n\t{\r\n\t\treturn m_materialToolLevelCache.value( material );\r\n\t}\r\n\tint tl = DB::select( \"ToolLevel\", \"MaterialToToolLevel\", material ).toInt();\r\n\tif ( tl == 0 )\r\n\t{\r\n\t\ttl = DB::select( \"ToolLevel\", \"MaterialToToolLevel\", DB::select( \"Type\", \"Materials\", material ).toString() ).toInt();\r\n\t}\r\n\tm_materialToolLevelCache.insert( material, tl );\r\n\treturn tl;\r\n}\r\n\r\nint DBH::materialUID( QString material )\r\n{\r\n\tif( !GameState::materialSID2ID.contains( material ) )\r\n\t{\r\n\t\tGameState::materialID2SID.insert( GameState::materialSID2ID.size(), material );\r\n\t\tGameState::materialSID2ID.insert( material, GameState::materialSID2ID.size() );\r\n\t}\r\n\treturn GameState::materialSID2ID.value( material );\r\n}\r\n\r\nQString DBH::materialSID( int material )\r\n{\r\n\tif ( GameState::materialID2SID.contains( material ) )\r\n\t{\r\n\t\treturn GameState::materialID2SID.value( material );\r\n\t}\r\n\tqDebug() << \"***ERROR*** DBH::materialSID : no entry for material:\" << material;\r\n\treturn \"NONE\";\r\n}\r\n\r\nint DBH::itemUID( QString item )\r\n{\r\n\tif( !GameState::itemSID2ID.contains( item ) )\r\n\t{\r\n\t\tGameState::itemID2SID.insert( GameState::itemSID2ID.size(), item );\r\n\t\tGameState::itemSID2ID.insert( item, GameState::itemSID2ID.size() );\r\n\t}\r\n\treturn GameState::itemSID2ID.value( item );\r\n}\r\n\r\nQString DBH::itemSID( int item )\r\n{\r\n\tif ( GameState::itemID2SID.contains( item ) )\r\n\t{\r\n\t\treturn GameState::itemID2SID.value( item );\r\n\t}\r\n\tqDebug() << \"***ERROR*** DBH::itemSID : no entry for item:\" << item;\r\n\treturn \"NONE\";\r\n}\r\n\r\n\r\nbool DBHelper::itemIsContainer( int item )\r\n{\r\n\tif ( m_itemIsContainerCache.contains(item) )\r\n\t{\r\n\t\treturn m_itemIsContainerCache.value( item );\r\n\t}\r\n\tbool isContainer = DB::select( \"IsContainer\", \"Items\", DBH::itemSID( item ) ).toBool();\r\n\tm_itemIsContainerCache.insert( item, isContainer );\r\n\treturn isContainer;\r\n}\r\n\r\nint DBH::rowID( QString table, QString id )\r\n{\r\n\treturn DB::execQuery( \"SELECT rowid FROM \" + table + \" WHERE ID = \\\"\" + id + \"\\\"\" ).toInt();\r\n}\r\n\r\nQString DBH::id( QString table, int rowID )\r\n{\r\n\treturn DB::execQuery( \"SELECT ID FROM \" + table + \" WHERE rowid = \\\"\" + QString::number( rowID ) + \"\\\"\" ).toString();\r\n}\r\n\r\nQString DBH::qualitySID( int rank )\r\n{\r\n\tif ( m_qualitySIDCache.contains( rank ) )\r\n\t{\r\n\t\treturn m_qualitySIDCache.value( rank );\r\n\t}\r\n\tQString qualitySID = DB::execQuery( \"SELECT ID FROM Quality WHERE Rank = \\\"\" + QString::number( rank ) + \"\\\"\" ).toString();\r\n\tm_qualitySIDCache.insert( rank, qualitySID );\r\n\treturn qualitySID;\r\n}\r\n\r\nfloat DBHelper::qualityMod( int rank )\r\n{\r\n\tif ( m_qualityModCache.contains(rank) )\r\n\t{\r\n\t\treturn m_qualityModCache.value( rank );\r\n\t}\r\n\tauto modifiers = DB::select2( \"Modifier\", \"Quality\", \"Rank\", rank );\r\n\tfloat modifier = 1.0;\r\n\tif ( modifiers.size() )\r\n\t{\r\n\t\tmodifier = modifiers.first().toFloat();\r\n\t}\r\n\tm_qualityModCache.insert( rank, modifier );\r\n\treturn modifier;\r\n}\r\n\r\nQMap<QString, QMultiMap<QString, QString>> DBHelper::workshopPossibleCraftResults( QString workshopId )\r\n{\r\n\tif ( m_workshopCraftResults.contains( workshopId ) )\r\n\t{\r\n\t\treturn m_workshopCraftResults.value( workshopId );\r\n\t}\r\n\r\n\tQMap<QString, QMultiMap<QString, QString>> workshopProduces;\r\n\r\n\tauto dbws = DB::workshop( workshopId );\r\n\tif( !dbws )\r\n\t{\r\n\t\t// this should never be reached\r\n\t\treturn workshopProduces;\r\n\t}\r\n\tconst auto craftIds = dbws->Crafts;\r\n\r\n\tfor ( const auto& craftId : craftIds )\r\n\t{\r\n\t\tQMultiMap<QString, QString> craftVariants;\r\n\t\tauto itemSID = DB::select( \"ItemID\", \"Crafts\", craftId ).toString();\r\n\t\t// can this workshop craft an item of that material?\r\n\t\tauto possibleResultMatTypes = DB::select( \"ResultMaterialTypes\", \"Crafts\", craftId ).toString().split( \"|\" );\r\n\t\tfor ( const auto& materialType : possibleResultMatTypes )\r\n\t\t{\r\n\t\t\tcraftVariants.insertMulti( materialType, craftId );\r\n\t\t}\r\n\t\tworkshopProduces.insert( itemSID, craftVariants );\r\n\t}\r\n\r\n\tm_workshopCraftResults.insert( workshopId, workshopProduces );\r\n\treturn workshopProduces;\r\n}\r\n\r\nQString DBH::itemGroup( QString itemID )\r\n{\r\n\tif ( m_itemGroupCache.contains( itemID ) )\r\n\t{\r\n\t\treturn m_itemGroupCache.value( itemID );\r\n\t}\r\n\tQString itemGroup = DB::select( \"ItemGroup\", \"Items\", itemID ).toString();\r\n\tm_itemGroupCache.insert( itemID, itemGroup );\r\n\treturn itemGroup;\r\n}"
  },
  {
    "path": "src/base/dbhelper.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMap>\r\n#include <QString>\r\n#include <QStringList>\r\n\r\nclass DBHelper\r\n{\r\npublic:\r\n\t//static QStringList getWorkPositions( QString jobID );\r\n\r\n\tstatic QString spriteID( QString itemID );\r\n\tstatic bool spriteIsRandom( QString spriteID );\r\n\tstatic bool spriteHasAnim( QString spriteID );\r\n\tstatic QString materialColor( QString materialID );\r\n\r\n\tstatic int materialToolLevel( QString material );\r\n\r\n\tstatic int materialUID( QString material );\r\n\tstatic QString materialSID( int material );\r\n\r\n\tstatic int itemUID( QString item );\r\n\tstatic QString itemSID( int item );\r\n\tstatic bool itemIsContainer( int item );\r\n\r\n\tstatic int rowID( QString table, QString id );\r\n\tstatic QString id( QString table, int rowID );\r\n\r\n\tstatic QString qualitySID( int rank );\r\n\tstatic float qualityMod( int rank );\r\n\r\n\tstatic QString itemGroup( QString itemID );\r\n\r\n\t// itemSID => [ materialType => craftID ]\r\n\tstatic QMap<QString, QMultiMap<QString, QString>> workshopPossibleCraftResults( QString workshopId );\r\n\r\nprivate:\r\n\tDBHelper()  = delete;\r\n\t~DBHelper() = delete;\r\n\r\n\tstatic QMap<QString, QString> m_spriteIDCache;\r\n\tstatic QMap<QString, bool> m_spriteIsRandomCache;\r\n\tstatic QMap<QString, bool> m_spriteHasAnimCache;\r\n\tstatic QMap<QString, QString> m_materialColorCache;\r\n\r\n\tstatic QMap<QString, int> m_materialToolLevelCache;\r\n\tstatic QMap<int, bool> m_itemIsContainerCache;\r\n\tstatic QMap<int, QString> m_qualitySIDCache;\r\n\tstatic QMap<int, float> m_qualityModCache;\r\n\tstatic QMap<QString, QString> m_itemGroupCache;\r\n\r\n\tstatic QMap<QString, QMap<QString, QMultiMap<QString, QString>>> m_workshopCraftResults;\r\n\r\n\tstatic QMutex m_mutex;\r\n};\r\n"
  },
  {
    "path": "src/base/dbstructs.h",
    "content": "#include \"../base/position.h\"\r\n\r\n#include <QString>\r\n\r\n\r\n\r\nnamespace DBS\r\n{\r\n\r\nstruct Actions {\r\n\tQString ID;\r\n\tQString Job;\r\n\tQString ConstructionType;\r\n\tbool ConstructionSelect;\r\n\tbool IsFloor;\r\n\tbool Multi;\r\n\tbool MultiZ;\r\n\tbool Rotate;\r\n};\r\n\r\nstruct Actions_Tiles {\r\n\tQString ID;\r\n\tQString Offset;\r\n\tQString SpriteID;\r\n\tbool IsFloor;\r\n\tQString Required;\r\n\tQString Forbidden;\r\n};\r\n\r\nstruct AI {\r\n\tQString ID;\r\n\tQString BehaviorTree;\r\n};\r\n\r\nstruct Anatomy {\r\n\tQString ID;\r\n\tint Blood;\r\n\tQString Root;\r\n\tQString LayerOrder;\r\n};\r\n\r\nstruct Anatomy_Parts {\r\n\tQString ID;\r\n\tQString ID2;\r\n\tQString Parent;\r\n\tbool IsInside;\r\n\tQString Height;\r\n\tQString Side;\r\n\tQString Facing;\r\n\tint HP;\r\n\tbool IsVital;\r\n};\r\n\r\nstruct Animals {\r\n\tQString ID;\r\n\tbool AllowInWild;\r\n\tbool Aquatic;\r\n\tQString BehaviorTree;\r\n\tQString Biome;\r\n\tbool Embark;\r\n\tQString Food;\r\n\tint GestationDays;\r\n\tbool Pasture;\r\n\tint PastureSize;\r\n\tQString Prey;\r\n\tbool IsMulti;\r\n};\r\n\r\nstruct Animals_OnButcher {\r\n\tQString ID;\r\n\tint Amount;\r\n\tQString ItemID;\r\n\tQString Type;\r\n};\r\n\r\nstruct Animals_States {\r\n\tQString ID;\r\n\tQString ID2;\r\n\tQString SpriteID;\r\n\tint DaysToNextState;\r\n\tbool Immobile;\r\n\tQString BehaviorTree;\r\n\tbool IsAggro;\r\n\tint Attack;\r\n\tint Damage;\r\n\tQString Anatomy;\r\n};\r\n\r\nstruct Animals_States_Behavior {\r\n\tQString ID;\r\n\tQString ID2;\r\n\tQString RequiredGender;\r\n\tint Amount;\r\n\tQString CreatureID;\r\n\tint DaysBetween;\r\n\tint EatTime;\r\n\tQString EggID;\r\n\tint FoodValue;\r\n\tfloat HungerPerTick;\r\n\tQString ItemID;\r\n\tfloat Speed;\r\n};\r\n\r\nstruct Attributes {\r\n\tQString ID;\r\n};\r\n\r\nstruct Automaton_Cores {\r\n\tQString ID;\r\n\tQString BehaviorTree;\r\n};\r\n\r\nstruct Automaton_Cores_Skills {\r\n\tQString ID;\r\n\tQString SkillID;\r\n\tint SkillValue;\r\n};\r\n\r\nstruct BaseItems {\r\n\tQString ID;\r\n};\r\n\r\nstruct BaseSprites {\r\n\tQString ID;\r\n\tQString SourceRectangle;\r\n\tQString Tilesheet;\r\n};\r\n\r\nstruct Constructions {\r\n\tQString ID;\r\n\tbool oConstruction;\r\n\tbool Rotation;\r\n\tQString Type;\r\n\tQString Category;\r\n};\r\n\r\nstruct Constructions_Components {\r\n\tQString ID;\r\n\tint Amount;\r\n\tQString ItemID;\r\n\tQString MaterialTypes;\r\n\tQString Materials;\r\n};\r\n\r\nstruct Constructions_IntermediateSprites {\r\n\tQString ID;\r\n\tQString Offset;\r\n\tfloat Percent;\r\n\tQString SpriteID;\r\n\tQString Type;\r\n};\r\n\r\nstruct Constructions_Sprites {\r\n\tQString ID;\r\n\tQString Offset;\r\n\tQString SpriteID;\r\n\tQString SpriteIDOverride;\r\n\tQString Type;\r\n};\r\n\r\nstruct ConstructionTypes {\r\n\tQString ID;\r\n};\r\n\r\nstruct Containers {\r\n\tQString ID;\r\n\tbool Buildable;\r\n\tint Capacity;\r\n\tbool RequireSame;\r\n\tQString Type;\r\n\tQString Item;\r\n};\r\n\r\nstruct Containers_Components {\r\n\tQString ID;\r\n\tQString ItemID;\r\n};\r\n\r\nstruct Containers_Tiles {\r\n\tQString ID;\r\n\tbool Construction;\r\n\tbool Job;\r\n\tQString Offset;\r\n\tQString SpriteID;\r\n\tbool Stockpile;\r\n};\r\n\r\nstruct Crafts {\r\n\tQString ID;\r\n\tint Amount;\r\n\tQString ConversionMaterial;\r\n\tQString ItemID;\r\n\tint ProductionTime;\r\n\tQString ResultMaterial;\r\n\tQString ResultMaterialTypes;\r\n\tQString SkillID;\r\n};\r\n\r\nstruct Crafts_Components {\r\n\tQString ID;\r\n\tQString AllowedMaterial;\r\n\tQString AllowedMaterialType;\r\n\tint Amount;\r\n\tQString ItemID;\r\n\tbool RequireSame;\r\n};\r\n\r\nstruct Crafts_Prereqs {\r\n\tQString ID;\r\n\tQString Category;\r\n\tQString TechGroup;\r\n\tfloat Value;\r\n};\r\n\r\nstruct Crafts_SkillGain {\r\n\tQString ID;\r\n\tfloat Value;\r\n};\r\n\r\nstruct Crafts_TechGain {\r\n\tQString ID;\r\n\tQString TechID;\r\n\tfloat Value;\r\n};\r\n\r\nstruct Creature_Layouts {\r\n\tQString ID;\r\n\tQString Offset;\r\n\tQString Sprite;\r\n};\r\n\r\nstruct Creature_Parts {\r\n\tQString ID;\r\n\tQString Part;\r\n\tQString BaseSprite;\r\n\tint Order;\r\n\tQString Tint;\r\n\tQString Conceales;\r\n};\r\n\r\nstruct EmbeddedMaterials {\r\n\tQString ID;\r\n\tint Highest;\r\n\tint Lowest;\r\n\tQString Type;\r\n\tQString WallSprite;\r\n};\r\n\r\nstruct Events {\r\n\tQString ID;\r\n\tQString Trigger_;\r\n\tint TriggerCount;\r\n\tQString TriggerUnit;\r\n\tint NotBeforeDay;\r\n\tbool NotInPeaceful;\r\n};\r\n\r\nstruct Events_Expires {\r\n\tQString ID;\r\n\tint After;\r\n\tQString Unit;\r\n\tQString Title;\r\n\tQString Message;\r\n};\r\n\r\nstruct Events_Init {\r\n\tQString ID;\r\n\tQString Title;\r\n\tQString Message;\r\n\tfloat Min;\r\n\tfloat Max;\r\n\tbool Pause;\r\n\tQString Require;\r\n\tQString Location;\r\n};\r\n\r\nstruct Events_OnFailure {\r\n\tQString ID;\r\n\tQString Message;\r\n\tQString Title;\r\n};\r\n\r\nstruct Events_OnSuccess {\r\n\tQString ID;\r\n\tQString Action;\r\n\tbool CenterCamera;\r\n\tQString Count;\r\n\tQString Message;\r\n\tbool Pause;\r\n\tQString Title;\r\n};\r\n\r\nstruct FarmUtils {\r\n\tQString ID;\r\n\tbool Buildable;\r\n\tQString Item;\r\n};\r\n\r\nstruct Food_Values {\r\n\tQString ID;\r\n\tQString MaterialID;\r\n\tfloat Fruit;\r\n\tfloat Vegetable;\r\n\tfloat Meat;\r\n\tfloat Dairy;\r\n\tfloat Grain;\r\n};\r\n\r\nstruct FormationPerks {\r\n\tQString ID;\r\n};\r\n\r\nstruct Furniture {\r\n\tQString ID;\r\n\tbool Buildable;\r\n\tQString Item;\r\n};\r\n\r\nstruct Gamestart {\r\n\tint Amount;\r\n\tQString Color;\r\n\tQString ItemID;\r\n\tQString MaterialID;\r\n\tQString Offset;\r\n\tQString Type;\r\n};\r\n\r\nstruct HairColors {\r\n\tQString ID;\r\n\tQString Color;\r\n};\r\n\r\nstruct Hydraulics {\r\n\tQString ID;\r\n\tbool Buildable;\r\n\tQString Item;\r\n\tQString Sprite;\r\n};\r\n\r\nstruct ItemGrouping {\r\n\tQString ID;\r\n\tQString Color;\r\n\tQString SpriteID;\r\n};\r\n\r\nstruct ItemGrouping_Groups {\r\n\tQString ID;\r\n\tQString GroupID;\r\n\tQString SpriteID;\r\n};\r\n\r\nstruct Items {\r\n\tQString ID;\r\n\tQString SpriteID;\r\n\tQString Category;\r\n\tQString ItemGroup;\r\n\tint StackSize;\r\n\tbool HasQuality;\r\n\tint Value;\r\n\tint EatValue;\r\n\tint DrinkValue;\r\n\tbool IsContainer;\r\n\tbool IsTool;\r\n\tint LightIntensity;\r\n\tbool HasComponents;\r\n\tQString AllowedMaterialTypes;\r\n\tQString AllowedMaterials;\r\n\tQString AllowedContainers;\r\n\tQString CarryContainer;\r\n\tint AttackValue;\r\n\tint BurnValue;\r\n};\r\n\r\nstruct Items_Components {\r\n\tQString ID;\r\n\tQString ItemID;\r\n\tbool NoMaterial;\r\n};\r\n\r\nstruct Items_Tiles {\r\n\tQString ID;\r\n\tQString Forbidden;\r\n\tQString Required;\r\n\tQString Location;\r\n\tQString Offset;\r\n};\r\n\r\nstruct Job_SpriteID {\r\n\tPosition Offset;\r\n\tbool Rotate;\r\n\tQString SpriteID;\r\n\tQString Type;\r\n};\r\n\r\nstruct Job_Task {\r\n\tQString ConstructionID;\r\n\tint Duration;\r\n\tQString Material;\r\n\tPosition Offset;\r\n\tQString Task;\r\n};\r\n\r\nstruct Job {\r\n\tQString ID;\r\n\tQString ConstructionType;\r\n\tbool MayTrapGnome;\r\n\tQString RequiredToolItemID;\r\n\tQString RequiredToolLevel;\r\n\tQString SkillGain;\r\n\tQString SkillID;\r\n\tQString TechGain;\r\n\tQList<Position> WorkPositions;\r\n\tQList<Job_Task> tasks;\r\n\tQList<Job_SpriteID>sprites;\r\n};\r\n\r\nstruct Lairs {\r\n\tQString ID;\r\n\tQString Type;\r\n\tQString Size;\r\n\tQString Layout;\r\n};\r\n\r\nstruct Lairs_Spawns {\r\n\tQString ID;\r\n\tQString Type;\r\n\tQString Offset;\r\n\tint Level;\r\n\tint Rotation;\r\n\tint Gender;\r\n};\r\n\r\nstruct Lairs_Tiles {\r\n\tQString ID;\r\n\tQString Offset;\r\n\tQString Type;\r\n};\r\n\r\nstruct Magic {\r\n\tQString ID;\r\n\tQString Color;\r\n\tQString Spells;\r\n};\r\n\r\nstruct Materials {\r\n\tQString ID;\r\n\tQString Color;\r\n\tfloat Strength;\r\n\tQString Type;\r\n\tfloat Value;\r\n};\r\n\r\nstruct MaterialToToolLevel {\r\n\tQString ID;\r\n\tint RequiredToolLevel;\r\n\tint ToolLevel;\r\n};\r\n\r\nstruct Mechanism {\r\n\tQString ID;\r\n\tQString GUI;\r\n\tbool Buildable;\r\n\tQString Item;\r\n\tQString Sprite;\r\n\tint MaxFuel;\r\n\tint ProducePower;\r\n\tint ConsumePower;\r\n\tbool Anim;\r\n\tQString WallSpriteOn;\r\n\tQString WallSpriteOff;\r\n\tQString FloorSpriteOn;\r\n\tQString FloorSpriteOff;\r\n\tQString EffectOn;\r\n\tQString EffectOff;\r\n};\r\n\r\nstruct Missions {\r\n\tQString ID;\r\n\tint TypeInt;\r\n\tint MinGnomes;\r\n\tint MaxGnomes;\r\n\tQString Target;\r\n\tQString Actions;\r\n};\r\n\r\nstruct Monsters {\r\n\tQString ID;\r\n\tQString BehaviorTree;\r\n\tQString Food;\r\n};\r\n\r\nstruct Monsters_Levels {\r\n\tQString ID;\r\n\tint Level;\r\n\tQString Sprite;\r\n};\r\n\r\nstruct MoveSpeed {\r\n\tQString Creature;\r\n\tint Skill;\r\n\tint Speed;\r\n};\r\n\r\nstruct Namerules {\r\n\tQString ID;\r\n};\r\n\r\nstruct Namerules_Rule {\r\n\tQString ID;\r\n\tQString Part;\r\n};\r\n\r\nstruct Names {\r\n\tQString ID;\r\n\tQString Gender;\r\n};\r\n\r\nstruct Needs {\r\n\tQString ID;\r\n\tQString BarColor;\r\n\tfloat DecayPerMinute;\r\n\tfloat GainFromSleep;\r\n\tfloat Max_;\r\n\tQString Creature;\r\n};\r\n\r\nstruct Needs_States {\r\n\tQString ID;\r\n\tQString Action;\r\n\tQString ID2;\r\n\tint Priority;\r\n\tQString ThoughtBubble;\r\n\tfloat Threshold;\r\n};\r\n\r\nstruct Needs_States_Modifiers {\r\n\tQString ID;\r\n\tQString Attribute;\r\n\tQString Type;\r\n\tfloat Value_;\r\n};\r\n\r\nstruct Plants {\r\n\tQString ID;\r\n\tbool AllowInWild;\r\n\tQString FruitItemID;\r\n\tQString GrowsIn;\r\n\tQString GrowsInSeason;\r\n\tQString IsKilledInSeason;\r\n\tbool IsLarge;\r\n\tQString LosesFruitInSeason;\r\n\tQString Material;\r\n\tint NumFruitsPerSeason;\r\n\tQString SeedItemID;\r\n\tQString ToolButtonSprite;\r\n\tQString Type;\r\n};\r\n\r\nstruct Plants_OnFell {\r\n\tQString ID;\r\n\tQString ItemID;\r\n\tQString MaterialID;\r\n\tint Random;\r\n};\r\n\r\nstruct Plants_OnHarvest {\r\n\tQString ID;\r\n\tQString Action;\r\n};\r\n\r\nstruct Plants_OnHarvest_HarvestedItem {\r\n\tQString ID;\r\n\tfloat Chance;\r\n\tQString ItemID;\r\n\tQString MaterialID;\r\n};\r\n\r\nstruct Plants_States {\r\n\tQString ID;\r\n\tbool Fell;\r\n\tfloat GrowTime;\r\n\tfloat GrowTimeDeviation;\r\n\tbool arvest;\r\n\tQString ID2;\r\n\tQString Layout;\r\n\tQString SpriteID;\r\n};\r\n\r\nstruct PositionPerks {\r\n\tQString ID;\r\n};\r\n\r\nstruct Quality {\r\n\tQString ID;\r\n\tint Rank;\r\n\tfloat Modifier;\r\n};\r\n\r\nstruct RandomMetals {\r\n\tQString ID;\r\n\tint Copper;\r\n\tint Tin;\r\n\tint Malachite;\r\n\tint Iron;\r\n\tint Lead;\r\n\tint Silver;\r\n\tint Gold;\r\n\tint Platinum;\r\n};\r\n\r\nstruct Seasons {\r\n\tQString ID;\r\n\tQString NextSeason;\r\n\tint NumDays;\r\n\tQString SunRiseFirst;\r\n\tQString SunsetFirst;\r\n};\r\n\r\nstruct SkillGroups {\r\n\tQString ID;\r\n\tQString Color;\r\n\tint Position;\r\n\tQString SkillID;\r\n\tQString Text;\r\n};\r\n\r\nstruct Skills {\r\n\tQString ID;\r\n\tQString RequiredToolItemID;\r\n\tQString SkillGroup;\r\n};\r\n\r\nstruct Sounds {\r\n\tQString ID;\r\n\tQString SoundFile;\r\n};\r\n\r\nstruct Spells {\r\n\tQString ID;\r\n\tQString EffectRequirements;\r\n\tQString Effects;\r\n\tQString Radius;\r\n\tQString SkillID;\r\n};\r\n\r\nstruct Sprites {\r\n\tQString ID;\r\n\tbool Anim;\r\n\tQString BaseSprite;\r\n\tbool HasRandom;\r\n\tQString Offset;\r\n\tbool Rot90;\r\n\tQString Tint;\r\n\tQString DefaultMaterial;\r\n\tbool HasTransp;\r\n};\r\n\r\nstruct Sprites_ByMaterials {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString Effect;\r\n\tQString MaterialID;\r\n\tQString Sprite;\r\n};\r\n\r\nstruct Sprites_ByMaterialTypes {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString MaterialType;\r\n\tQString Sprite;\r\n};\r\n\r\nstruct Sprites_Combine {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString Offset;\r\n\tQString Sprite;\r\n\tQString Tint;\r\n};\r\n\r\nstruct Sprites_Frames {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n};\r\n\r\nstruct Sprites_Random {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString Sprite;\r\n\tfloat Weight;\r\n};\r\n\r\nstruct Sprites_Rotations {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString Effect;\r\n\tQString Rotation;\r\n\tQString Sprite;\r\n};\r\n\r\nstruct Sprites_Seasons {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString Season;\r\n};\r\n\r\nstruct Sprites_Seasons_Rotations {\r\n\tQString ID;\r\n\tQString BaseSprite;\r\n\tQString Rotation;\r\n};\r\n\r\nstruct Tech {\r\n\tQString ID;\r\n};\r\n\r\nstruct TerrainMaterials {\r\n\tQString ID;\r\n\tQString FloorSprite;\r\n\tint Highest;\r\n\tint Lowest;\r\n\tQString ShortWallSprite;\r\n\tQString Type;\r\n\tQString WallSprite;\r\n};\r\n\r\nstruct Time {\r\n\tQString ID;\r\n\tint Value_;\r\n};\r\n\r\nstruct Traders {\r\n\tQString ID;\r\n};\r\n\r\nstruct Traders_Items {\r\n\tQString ID;\r\n\tQString Gender;\r\n\tQString Item;\r\n\tQString Material;\r\n\tint Max_;\r\n\tint Min_;\r\n\tQString Type;\r\n\tint Value_;\r\n};\r\n\r\nstruct Translation {\r\n\tQString ID;\r\n\tQString Text;\r\n};\r\n\r\nstruct TreeLayouts {\r\n\tQString ID;\r\n};\r\n\r\nstruct TreeLayouts_Layout {\r\n\tQString ID;\r\n\tbool FruitPos;\r\n\tQString Offset;\r\n\tQString Rotation;\r\n\tQString SpriteID;\r\n};\r\n\r\nstruct Uniform {\r\n\tQString ID;\r\n\tint Sides;\r\n};\r\n\r\nstruct Uniform_Slots {\r\n\tQString ID;\r\n\tQString Type;\r\n\tQString ItemID;\r\n\tQString MaterialType;\r\n};\r\n\r\nstruct Uniforms {\r\n\tint ID;\r\n\tQString Name;\r\n\tbool UserDefined;\r\n};\r\n\r\nstruct Utility {\r\n\tQString ID;\r\n\tbool Buildable;\r\n\tQString Item;\r\n};\r\n\r\nstruct Words {\r\n\tQString Word;\r\n};\r\n\r\nstruct Words_ActionNoun {\r\n\tQString Plural;\r\n\tQString Word;\r\n};\r\n\r\nstruct Words_Adjective {\r\n\tQString Word;\r\n};\r\n\r\nstruct Words_Noun {\r\n\tQString Plural;\r\n\tQString Word;\r\n};\r\n\r\nstruct Words_Numbers {\r\n\tQString Word;\r\n\tint Number;\r\n};\r\n\r\nstruct Words_Verb {\r\n\tQString PastParticiple;\r\n\tQString PresentParticiple;\r\n\tQString SimplePast;\r\n\tQString SimplePresent;\r\n\tQString Word;\r\n};\r\n\r\nstruct Workshop_Component {\r\n\tint Amount = 0;\r\n\tQString ItemID;\r\n\tQString MaterialItem;\r\n\tPosition Offset;\r\n\tQString Required;\r\n\tQString Forbidden;\r\n\tQString SpriteID;\r\n\tQString SpriteID2;\r\n\tQString Type;\r\n\tQString WallRotation;\r\n\tbool IsFloor = false;\r\n};\r\n\r\nstruct Workshop {\r\n\tQString ID;\r\n\tQStringList Crafts;\r\n\tQString GUI;\r\n\tPosition InputTile;\r\n\tPosition OutputTile;\r\n\tQString Size;\r\n\tbool NoAutoGenerate = false;\r\n\tQString Icon;\r\n\tQString Tab;\r\n\r\n\tQList<Workshop_Component> components;\r\n};\r\n\r\n}"
  },
  {
    "path": "src/base/enums.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QObject>\r\n\r\nenum Connection : unsigned int\r\n{\r\n\tnoCon     = 0,\r\n\tnorth     = 0x01,\r\n\tnortheast = 0x02,\r\n\teast      = 0x04,\r\n\tsoutheast = 0x08,\r\n\tsouth     = 0x10,\r\n\tsouthwest = 0x20,\r\n\twest      = 0x40,\r\n\tnorthwest = 0x80,\r\n\tup        = 0x100,\r\n\tdown      = 0x200,\r\n\tupnorth   = 0x400,\r\n\tupeast    = 0x800,\r\n\tupsouth   = 0x1000,\r\n\tupwest    = 0x2000,\r\n\tdownnorth = 0x4000,\r\n\tdowneast  = 0x8000,\r\n\tdownsouth = 0x10000,\r\n\tdownwest  = 0x20000\r\n};\r\n\r\n\r\nenum class ScheduleActivity : unsigned char {\r\n\tNone,\r\n\tEat,\r\n\tSleep,\r\n\tTraining\r\n};\r\nQ_DECLARE_METATYPE( ScheduleActivity )\r\n\r\nenum DBSkillIds : int\r\n{\r\n\tSK_Mining,\r\n\tSK_Masonry,\r\n\tSK_Stonecarving,\r\n\tSK_Woodcutting,\r\n\tSK_Carpentry,\r\n\tSK_Woodcarving,\r\n\tSK_Smelting,\r\n\tSK_Blacksmithing,\r\n\tSK_Metalworking,\r\n\tSK_WeaponCrafting,\r\n\tSK_ArmorCrafting,\r\n\tSK_Gemcutting,\r\n\tSK_JewelryMaking,\r\n\tSK_Weaving,\r\n\tSK_Tailoring,\r\n\tSK_Dyeing,\r\n\tSK_Pottery,\r\n\tSK_Leatherworking,\r\n\tSK_Bonecarving,\r\n\tSK_Prospecting,\r\n\tSK_Tinkering,\r\n\tSK_Machining,\r\n\tSK_Engineering,\r\n\tSK_Mechanic,\r\n\tSK_AnimalHusbandry,\r\n\tSK_Butchery,\r\n\tSK_Fishing,\r\n\tSK_Horticulture,\r\n\tSK_Farming,\r\n\tSK_Cooking,\r\n\tSK_Brewing,\r\n\tSK_Construction,\r\n\tSK_Hauling,\r\n\tSK_Unarmed,\r\n\tSK_Melee,\r\n\tSK_Ranged,\r\n\tSK_Thrown,\r\n\tSK_Dodge,\r\n\tSK_Block,\r\n\tSK_Armor,\r\n\tSK_Crossbow,\r\n\tSK_Gun,\r\n\tSK_Medic,\r\n\tSK_Caretaking,\r\n\tSK_MagicNature,\r\n\tSK_MagicGeomancy\r\n};\r\n\r\nenum CreaturePart : unsigned char\r\n{\r\n\tKCP_NONE,\r\n\tCP_HEAD,\r\n\tCP_TORSO,\r\n\tCP_LEFT_ARM,\r\n\tCP_RIGHT_ARM,\r\n\tCP_LEFT_HAND,\r\n\tCP_RIGHT_HAND,\r\n\r\n\tCP_LEFT_FRONT_LEG,\r\n\tCP_RIGHT_FRONT_LEG,\r\n\tCP_LEFT_FRONT_FOOT,\r\n\tCP_RIGHT_FRONT_FOOT,\r\n\r\n\tCP_LEFT_WING,\r\n\tCP_RIGHT_WING,\r\n\r\n\tCP_LEFT_LEG,\r\n\tCP_RIGHT_LEG,\r\n\tCP_LEFT_FOOT,\r\n\tCP_RIGHT_FOOT,\r\n\r\n\tCP_BRAIN,\r\n\tCP_LEFT_EYE,\r\n\tCP_RIGHT_EYE,\r\n\tCP_HEART,\r\n\tCP_LEFT_LUNG,\r\n\tCP_RIGHT_LUNG,\r\n\r\n\tCP_HAIR,\r\n\tCP_FACIAL_HAIR,\r\n\tCP_CLOTHING,\r\n\tCP_BOOTS,\r\n\tCP_HAT,\r\n\tCP_BACK,\r\n\r\n\tCP_ARMOR_HEAD,\r\n\tCP_ARMOR_TORSO,\r\n\tCP_ARMOR_ARM,\r\n\tCP_ARMOR_HAND,\r\n\tCP_ARMOR_LEG,\r\n\tCP_ARMOR_FOOT,\r\n\r\n\tCP_ARMOR_LEFT_ARM,\r\n\tCP_ARMOR_RIGHT_ARM,\r\n\tCP_ARMOR_LEFT_HAND,\r\n\tCP_ARMOR_RIGHT_HAND,\r\n\tCP_ARMOR_LEFT_FOOT,\r\n\tCP_ARMOR_RIGHT_FOOT,\r\n\tCP_LEFT_HAND_HELD,\r\n\tCP_RIGHT_HAND_HELD\r\n};\r\n\r\nenum DamageType : unsigned char\r\n{\r\n\tDT_BLUNT,\r\n\tDT_SLASH,\r\n\tDT_PIERCING\r\n};\r\n\r\nenum AnatomyHeight : unsigned char\r\n{\r\n\tAH_LOW,\r\n\tAH_MIDDLE,\r\n\tAH_HIGH\r\n};\r\n\r\nenum AnatomySide : unsigned char\r\n{\r\n\tAS_CENTER = 0x00,\r\n\tAS_FRONT  = 0x01,\r\n\tAS_BACK   = 0x02,\r\n\tAS_LEFT   = 0x04,\r\n\tAS_RIGHT  = 0x08\r\n};\r\n\r\nenum AnatomyStatus : unsigned int\r\n{\r\n\tAS_HEALTHY     = 0,\r\n\tAS_WOUNDED     = 0x01,\r\n\tAS_UNCONSCIOUS = 0x02,\r\n\tAS_DEAD        = 0x04,\r\n\tAS_HALFBLIND   = 0x08,\r\n\tAS_BLIND       = 0x10,\r\n\r\n};\r\n\r\nenum class GameSpeed\r\n{\r\n\tNormal,\r\n\tFast\r\n};\r\nQ_DECLARE_METATYPE( GameSpeed )\r\n\r\nenum class ButtonSelection\r\n{\r\n\tNone,\r\n\tBuild,\r\n\tMine,\r\n\tAgriculture,\r\n\tDesignation,\r\n\tJob,\r\n\tMagic\r\n};\r\n\r\nenum class BuildSelection\r\n{\r\n\tNone,\r\n\tWorkshop,\r\n\tWall,\r\n\tFloor,\r\n\tStairs,\r\n\tRamps,\r\n\tContainers,\r\n\tFence,\r\n\tFurniture,\r\n\tUtility\r\n};\r\nQ_DECLARE_METATYPE( BuildSelection )\r\n\r\nenum class ShownInfo\r\n{\r\n\tNone,\r\n\tTileInfo,\r\n\tStockpile,\r\n\tWorkshop,\r\n\tAgriculture,\r\n\tPopulation,\r\n\tCreatureInfo,\r\n\tDebug,\r\n\tNeighbors,\r\n\tMilitary,\r\n\tInventory\r\n};\r\n\r\nenum class BuildItemType\r\n{\r\n\tWorkshop,\r\n\tItem,\r\n\tTerrain\r\n};\r\nQ_DECLARE_METATYPE( BuildItemType )"
  },
  {
    "path": "src/base/filter.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"filter.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/inventory.h\"\r\n\r\n#include \"../gui/eventconnector.h\"\r\n\r\n#pragma region Filter\r\nFilter::Filter()\r\n{\r\n\tupdate();\r\n}\r\n\r\nFilter::Filter( QVariantMap in )\r\n{\r\n\tupdate();\r\n\r\n\tQVariantList ffl = in.value( \"Items\" ).toList();\r\n\tfor ( const auto& vf : ffl )\r\n\t{\r\n\t\tQString entry = vf.toString();\r\n\t\tsetActiveSimple( entry );\r\n\t}\r\n}\r\n\r\nQVariantMap Filter::serialize()\r\n{\r\n\tQVariantMap out;\r\n\r\n\tQVariantList filter;\r\n\tfor ( const auto& entry : getActiveSimple() )\r\n\t{\r\n\t\tfilter.append( entry );\r\n\t}\r\n\tout.insert( \"Items\", filter );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Filter::clear()\r\n{\r\n\tm_categories.clear();\r\n\tupdate();\r\n}\r\n\r\nvoid Filter::update()\r\n{\r\n\tif( !Global::eventConnector || !Global::eventConnector->game() ) return;\r\n\r\n\tauto inv = Global::eventConnector->game()->inv();\r\n\r\n\tQStringList keys = DB::ids( \"ItemGrouping\" );\r\n\r\n\tfor ( const auto& category : keys )\r\n\t{\r\n\t\tif ( !m_categories.contains( category ) )\r\n\t\t{\r\n\t\t\tm_categories.insert( category, FilterCategory() );\r\n\t\t}\r\n\t}\r\n\tfor ( const auto& category : inv->categories() )\r\n\t{\r\n\t\tfor ( const auto& group : inv->groups( category ) )\r\n\t\t{\r\n\t\t\tm_categories[category].addGroup( group );\r\n\t\t}\r\n\t}\r\n\tfor ( const auto& category : inv->categories() )\r\n\t{\r\n\t\tfor ( const auto& group : inv->groups( category ) )\r\n\t\t{\r\n\t\t\tfor ( const auto& item : inv->items( category, group ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& material : inv->materials( category, group, item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\taddItem( category, group, item, material );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_activeDirty       = true;\r\n\tm_activeSimpleDirty = true;\r\n}\r\n\r\nvoid Filter::addItem( QString category, QString group, QString item, QString material )\r\n{\r\n\tm_categories[category].addItem( group, item, material );\r\n\tm_activeDirty       = true;\r\n\tm_activeSimpleDirty = true;\r\n}\r\n\r\nQStringList Filter::categories()\r\n{\r\n\treturn m_categories.keys();\r\n}\r\n\r\nQStringList Filter::groups( QString category )\r\n{\r\n\treturn m_categories[category].groups();\r\n}\r\n\r\nQStringList Filter::items( QString category, QString group )\r\n{\r\n\treturn m_categories[category].items( group );\r\n}\r\n\r\nQStringList Filter::materials( QString category, QString group, QString item )\r\n{\r\n\treturn m_categories[category].materials( group, item );\r\n}\r\n\r\nvoid Filter::setCheckState( QString category, bool state )\r\n{\r\n\tm_categories[category].setCheckState( state );\r\n\tm_activeDirty       = true;\r\n\tm_activeSimpleDirty = true;\r\n}\r\n\r\nvoid Filter::setCheckState( QString category, QString group, bool state )\r\n{\r\n\tm_categories[category].setCheckState( group, state );\r\n\tm_activeDirty       = true;\r\n\tm_activeSimpleDirty = true;\r\n}\r\n\r\nvoid Filter::setCheckState( QString category, QString group, QString item, bool state )\r\n{\r\n\tm_categories[category].setCheckState( group, item, state );\r\n\tm_activeDirty       = true;\r\n\tm_activeSimpleDirty = true;\r\n}\r\n\r\nvoid Filter::setCheckState( QString category, QString group, QString item, QString material, bool state )\r\n{\r\n\t//qDebug() << category << group << item << material << state;\r\n\tm_categories[category].setCheckState( group, item, material, state );\r\n\tm_activeDirty       = true;\r\n\tm_activeSimpleDirty = true;\r\n}\r\n\r\nbool Filter::getCheckState( QString category, QString group, QString item, QString material )\r\n{\r\n\treturn m_categories[category].getCheckState( group, item, material );\r\n}\r\n\r\nconst QSet<QPair<QString, QString>>& Filter::getActive()\r\n{\r\n\tif ( m_activeDirty )\r\n\t{\r\n\t\tm_active.clear();\r\n\r\n\t\tfor ( const auto& category : categories() )\r\n\t\t{\r\n\t\t\tfor ( const auto& group : groups( category ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& item : items( category, group ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( const auto& material : materials( category, group, item ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( getCheckState( category, group, item, material ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tQPair<QString, QString> i( item, material );\r\n\t\t\t\t\t\t\tm_active.insert( i );\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\tm_activeDirty = false;\r\n\t}\r\n\treturn m_active;\r\n}\r\n\r\nQSet<QString> Filter::getActiveSimple()\r\n{\r\n\tif ( m_activeSimpleDirty )\r\n\t{\r\n\t\tm_activeSimple.clear();\r\n\t\tfor ( const auto& category : categories() )\r\n\t\t{\r\n\t\t\tfor ( const auto& group : groups( category ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& item : items( category, group ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( const auto& material : materials( category, group, item ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( getCheckState( category, group, item, material ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_activeSimple.insert( item + \"_\" + material );\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\tm_activeSimpleDirty = false;\r\n\t}\r\n\treturn m_activeSimple;\r\n}\r\n\r\nvoid Filter::setActiveSimple( QString val )\r\n{\r\n\tQStringList lv = val.split( \"_\" );\r\n\tif ( lv.size() == 2 )\r\n\t{\r\n\t\tfor ( const auto& category : categories() )\r\n\t\t{\r\n\t\t\tfor ( const auto& group : groups( category ) )\r\n\t\t\t{\r\n\t\t\t\tif ( materials( category, group, lv[0] ).contains( lv[1] ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t//if( Global::debugMode ) qDebug() << \"set \" << category << group << lv[0] << lv[1] << true;\r\n\t\t\t\t\tsetCheckState( category, group, lv[0], lv[1], true );\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\n#pragma endregion Filter\r\n\r\n#pragma region FilterCategory\r\nvoid FilterCategory::addItem( QString group, QString item, QString material )\r\n{\r\n\tm_groups[group].addItem( item, material );\r\n}\r\n\r\nvoid FilterCategory::addGroup( QString group )\r\n{\r\n\tif ( !m_groups.contains( group ) )\r\n\t{\r\n\t\tm_groups.insert( group, FilterGroup() );\r\n\t}\r\n}\r\n\r\nQStringList FilterCategory::groups()\r\n{\r\n\treturn m_groups.keys();\r\n}\r\n\r\nQStringList FilterCategory::items( QString group )\r\n{\r\n\treturn m_groups[group].items();\r\n}\r\n\r\nQStringList FilterCategory::materials( QString group, QString item )\r\n{\r\n\treturn m_groups[group].materials( item );\r\n}\r\n\r\nvoid FilterCategory::setCheckState( bool state )\r\n{\r\n\tfor ( const auto& key : m_groups.keys() )\r\n\t{\r\n\t\tm_groups[key].setCheckState( state );\r\n\t}\r\n}\r\n\r\nvoid FilterCategory::setCheckState( QString group, bool state )\r\n{\r\n\tm_groups[group].setCheckState( state );\r\n}\r\n\r\nvoid FilterCategory::setCheckState( QString group, QString item, bool state )\r\n{\r\n\tm_groups[group].setCheckState( item, state );\r\n}\r\n\r\nvoid FilterCategory::setCheckState( QString group, QString item, QString material, bool state )\r\n{\r\n\tm_groups[group].setCheckState( item, material, state );\r\n}\r\n\r\nbool FilterCategory::getCheckState( QString group, QString item, QString material )\r\n{\r\n\treturn m_groups[group].getCheckState( item, material );\r\n}\r\n#pragma endregion FilterCategory\r\n\r\n#pragma region FilterGroup\r\nvoid FilterGroup::addItem( QString item, QString material )\r\n{\r\n\tm_items[item].addItem( material );\r\n}\r\n\r\nQStringList FilterGroup::items()\r\n{\r\n\treturn m_items.keys();\r\n}\r\n\r\nQStringList FilterGroup::materials( QString item )\r\n{\r\n\tif ( m_items.contains( item ) )\r\n\t{\r\n\t\treturn m_items[item].materials();\r\n\t}\r\n\treturn QStringList();\r\n}\r\n\r\nvoid FilterGroup::setCheckState( bool state )\r\n{\r\n\tfor ( const auto& key : m_items.keys() )\r\n\t{\r\n\t\tm_items[key].setCheckState( state );\r\n\t}\r\n}\r\n\r\nvoid FilterGroup::setCheckState( QString item, bool state )\r\n{\r\n\tm_items[item].setCheckState( state );\r\n}\r\n\r\nvoid FilterGroup::setCheckState( QString item, QString material, bool state )\r\n{\r\n\tif ( m_items.contains( item ) )\r\n\t{\r\n\t\tm_items[item].setCheckState( material, state );\r\n\t}\r\n}\r\n\r\nbool FilterGroup::getCheckState( QString item, QString material )\r\n{\r\n\treturn m_items[item].getCheckState( material );\r\n}\r\n\r\n#pragma endregion FilterGroup\r\n\r\n#pragma region FilterItem\r\n\r\nvoid FilterItem::addItem( QString material )\r\n{\r\n\tif ( m_materials.empty() )\r\n\t{\r\n\t\tm_materials.insert( material, false );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Inherit active state from silblings, if alle known are already active\r\n\t\tbool allActive = true;\r\n\t\tfor ( const auto& material : m_materials )\r\n\t\t{\r\n\t\t\tallActive = allActive && material;\r\n\t\t}\r\n\t\tm_materials.insert( material, allActive );\r\n\t}\r\n}\r\n\r\nQStringList FilterItem::materials()\r\n{\r\n\treturn m_materials.keys();\r\n}\r\n\r\nvoid FilterItem::setCheckState( bool state )\r\n{\r\n\tfor ( const auto& key : m_materials.keys() )\r\n\t{\r\n\t\tm_materials[key] = state;\r\n\t}\r\n}\r\n\r\nvoid FilterItem::setCheckState( QString material, bool state )\r\n{\r\n\tif ( m_materials.contains( material ) )\r\n\t{\r\n\t\tm_materials[material] = state;\r\n\t}\r\n}\r\n\r\nbool FilterItem::getCheckState( QString material )\r\n{\r\n\treturn m_materials[material];\r\n}\r\n#pragma endregion FilterItem"
  },
  {
    "path": "src/base/filter.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QDebug>\r\n#include <QMap>\r\n#include <QString>\r\n\r\nclass FilterItem\r\n{\r\npublic:\r\n\tvoid addItem( QString material );\r\n\r\n\tQStringList materials();\r\n\r\n\tvoid setCheckState( bool state );\r\n\tvoid setCheckState( QString material, bool state );\r\n\r\n\tbool getCheckState( QString material );\r\n\r\nprivate:\r\n\tQMap<QString, bool> m_materials;\r\n};\r\n\r\nclass FilterGroup\r\n{\r\npublic:\r\n\tvoid addItem( QString item, QString material );\r\n\r\n\tQStringList items();\r\n\tQStringList materials( QString item );\r\n\r\n\tvoid setCheckState( bool state );\r\n\tvoid setCheckState( QString item, bool state );\r\n\tvoid setCheckState( QString item, QString material, bool state );\r\n\r\n\tbool getCheckState( QString item, QString material );\r\n\r\nprivate:\r\n\tQMap<QString, FilterItem> m_items;\r\n};\r\n\r\nclass FilterCategory\r\n{\r\npublic:\r\n\tvoid addItem( QString group, QString item, QString material );\r\n\tvoid addGroup( QString group );\r\n\r\n\tQStringList groups();\r\n\tQStringList items( QString group );\r\n\tQStringList materials( QString group, QString item );\r\n\r\n\tvoid setCheckState( bool state );\r\n\tvoid setCheckState( QString group, bool state );\r\n\tvoid setCheckState( QString group, QString item, bool state );\r\n\tvoid setCheckState( QString group, QString item, QString material, bool state );\r\n\r\n\tbool getCheckState( QString group, QString item, QString material );\r\n\r\nprivate:\r\n\tQMap<QString, FilterGroup> m_groups;\r\n};\r\n\r\nclass Filter\r\n{\r\npublic:\r\n\tFilter();\r\n\tFilter( QVariantMap in );\r\n\r\n\tQVariantMap serialize();\r\n\r\n\tvoid clear();\r\n\r\n\tvoid addItem( QString category, QString group, QString item, QString material );\r\n\r\n\tQStringList categories();\r\n\tQStringList groups( QString catgory );\r\n\tQStringList items( QString category, QString group );\r\n\tQStringList materials( QString category, QString group, QString item );\r\n\r\n\tvoid setCheckState( QString category, bool state );\r\n\tvoid setCheckState( QString category, QString group, bool state );\r\n\tvoid setCheckState( QString category, QString group, QString item, bool state );\r\n\tvoid setCheckState( QString category, QString group, QString item, QString material, bool state );\r\n\r\n\tbool getCheckState( QString category, QString group, QString item, QString material );\r\n\r\n\tconst QSet<QPair<QString, QString>>& getActive();\r\n\tQSet<QString> getActiveSimple();\r\n\tvoid setActiveSimple( QString val );\r\n\r\n\tvoid update();\r\n\r\nprivate:\r\n\tQMap<QString, FilterCategory> m_categories;\r\n\r\n\tbool m_activeDirty       = true;\r\n\tbool m_activeSimpleDirty = true;\r\n\tQSet<QPair<QString, QString>> m_active;\r\n\tQSet<QString> m_activeSimple;\r\n};\r\n"
  },
  {
    "path": "src/base/gamestate.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"gamestate.h\"\r\n#include \"../base/db.h\"\r\n\r\n#include <QDebug>\r\n#include <QDir>\r\n#include <QFile>\r\n\r\nint GameState::alarm        = 0;\r\nunsigned int GameState::alarmRoomID = 0;\r\n\r\nbool GameState::daylight    = true;\r\nbool GameState::initialSave = false;\r\nQVariantList GameState::itemFilter;\r\n\r\nQVariantMap GameState::military; // military manager\r\n\r\nQVariantList GameState::neighbors; // neighbor manager\r\n\r\nPosition GameState::origin;\r\nQVariantList GameState::squads;\r\n\r\nQVariantList GameState::stockOverlay;\r\n\r\nQVariantMap GameState::techs;\r\n\r\nQString GameState::version = \"uninitialized\";\r\n\r\nint GameState::flatness = 0;\r\n\r\nint GameState::minute = 0;\r\nint GameState::hour   = 0;\r\nint GameState::day    = 1;\r\nint GameState::season = 0; // zero based, 0-numSeasons, typically 4 can be modded\r\nint GameState::year   = 1;\r\n\r\nQString GameState::seasonString         = \"uninitialized\";\r\nQString GameState::currentDayTime       = \"uninitialized\";\r\nQString GameState::currentYearAndSeason = \"uninitialized\";\r\n\r\nbool GameState::dayChanged    = true;\r\nbool GameState::hourChanged   = true;\r\nbool GameState::minuteChanged = true;\r\nbool GameState::seasonChanged = true;\r\n\r\nint GameState::nextSunrise = 0;\r\nint GameState::sunrise     = 0;\r\nint GameState::sunset      = 0;\r\n\r\nint GameState::groundLevel     = 100;\r\nQString GameState::kingdomName = \"uninitialized\";\r\n\r\nunsigned int GameState::nextID = 1;\r\n\r\nbool GameState::peaceful = false;\r\n\r\nquint64 GameState::tick = 1;\r\n\r\nint GameState::numAnimals   = 0;\r\nint GameState::numGnomes    = 0;\r\nint GameState::oceanSize    = 0;\r\nint GameState::plantDensity = 0;\r\nint GameState::treeDensity  = 0;\r\nint GameState::riverSize    = 0;\r\nint GameState::rivers       = 0;\r\nQString GameState::seed     = \"uninitialized\";\r\n\r\nQVariantList GameState::startingItems;\r\n\r\nunsigned int GameState::startingZone = 0;\r\n\r\nint GameState::maxAnimalsPerType = 500;\r\nQVariantMap GameState::allowedAnimals;\r\nQVariantMap GameState::allowedPlants;\r\nQVariantMap GameState::allowedTrees;\r\n\r\nQVariantList GameState::addedMaterials;\r\nQVariantMap GameState::addedTranslations;\r\n\r\nint GameState::moveX = 0;\r\nint GameState::moveY = 0;\r\nfloat GameState::scale = 0.0;\r\nint GameState::viewLevel = 100;\r\n\r\nQList<GuiWatchedItem> GameState::watchedItemList;\r\n\r\nQHash<QString, int> GameState::materialSID2ID;\r\nQHash<int, QString> GameState::materialID2SID;\r\nQHash<QString, int> GameState::itemSID2ID;\r\nQHash<int, QString> GameState::itemID2SID;\r\n\r\n\r\nbool GameState::init()\r\n{\r\n\tGameState::materialSID2ID.clear();\r\n\tGameState::materialID2SID.clear();\r\n\r\n\tGameState::watchedItemList.clear();\r\n\r\n\tnextID = 1000000;\r\n\treturn true;\r\n}\r\n\r\nvoid GameState::serialize( QVariantMap& out )\r\n{\r\n\tout.insert( \"alarm\", alarm );\r\n\tout.insert( \"alarmRoomID\", alarmRoomID );\r\n\t\r\n\tout.insert( \"daylight\", daylight );\r\n\tout.insert( \"initialSave\", initialSave );\r\n\tout.insert( \"itemFilter\", itemFilter );\r\n\r\n\tout.insert( \"military\", military );\r\n\tout.insert( \"neighbors\", neighbors );\r\n\r\n\tout.insert( \"origin\", origin.toString() );\r\n\tout.insert( \"squads\", squads );\r\n\r\n\tout.insert( \"stockOverlay\", stockOverlay );\r\n\r\n\tout.insert( \"techs\", techs );\r\n\r\n\tout.insert( \"version\", version );\r\n\r\n\tout.insert( \"flatness\", flatness );\r\n\t\r\n\tout.insert( \"day\", day );\r\n\tout.insert( \"hour\", hour );\r\n\tout.insert( \"minute\", minute );\r\n\tout.insert( \"season\", season );\r\n\tout.insert( \"year\", year );\r\n\r\n\tout.insert( \"seasonString\", seasonString );\r\n\r\n\tout.insert( \"dayChanged\", dayChanged );\r\n\tout.insert( \"hourChanged\", hourChanged );\r\n\tout.insert( \"minuteChanged\", minuteChanged );\r\n\tout.insert( \"seasonChanged\", seasonChanged );\r\n\r\n\tout.insert( \"nextSunrise\", nextSunrise );\r\n\tout.insert( \"sunrise\", sunrise );\r\n\tout.insert( \"sunset\", sunset );\r\n\t\r\n\tout.insert( \"groundLevel\", groundLevel );\r\n\tout.insert( \"kingdomName\", kingdomName );\r\n\t\r\n\tout.insert( \"peaceful\", peaceful );\r\n\r\n\tout.insert( \"tick\", tick );\r\n\r\n\tout.insert( \"nextID\", nextID );\r\n\r\n\tout.insert( \"numAnimals\", numAnimals );\r\n\tout.insert( \"numGnomes\", numGnomes );\r\n\tout.insert( \"oceanSize\", oceanSize );\r\n\tout.insert( \"plantDensity\", plantDensity );\r\n\tout.insert( \"treeDensity\", treeDensity );\r\n\tout.insert( \"riverSize\", riverSize );\r\n\tout.insert( \"rivers\", rivers );\r\n\tout.insert( \"seed\", seed );\r\n\r\n\tout.insert( \"startingItems\", startingItems );\r\n\r\n\tout.insert( \"startingZone\", startingZone );\r\n\t\r\n\tout.insert( \"maxAnimalsPerType\", maxAnimalsPerType );\r\n\tout.insert( \"allowedAnimals\", allowedAnimals );\r\n\tout.insert( \"allowedPlants\", allowedPlants );\r\n\tout.insert( \"allowedTrees\", allowedTrees );\r\n\r\n\tout.insert( \"addedMaterials\", addedMaterials );\r\n\tout.insert( \"addedTranslations\", addedTranslations );\r\n\t\r\n\tout.insert( \"dimX\", Global::dimX );\r\n\tout.insert( \"dimY\", Global::dimY );\r\n\tout.insert( \"dimZ\", Global::dimZ );\r\n\r\n\tout.insert( \"moveX\", moveX );\r\n\tout.insert( \"moveY\", moveY );\r\n\tout.insert( \"scale\", scale );\r\n\tout.insert( \"viewLevel\", viewLevel );\r\n\r\n\tQVariantList qwil;\r\n\tfor( const auto& gwi : GameState::watchedItemList )\r\n\t{\r\n\t\tQVariantMap qwi;\r\n\t\tqwi.insert( \"category\", gwi.category );\r\n\t\tqwi.insert( \"group\", gwi.group );\r\n\t\tqwi.insert( \"item\", gwi.item );\r\n\t\tqwi.insert( \"material\", gwi.material );\r\n\t\tqwil.append( qwi );\r\n\t}\r\n\tout.insert( \"watchedItems\", qwil );\r\n\r\n\tQVariantMap vmIDs;\r\n\tfor( auto key : GameState::materialSID2ID.keys() )\r\n\t{\r\n\t\tvmIDs.insert( key, materialSID2ID.value( key ) );\r\n\t}\r\n\tout.insert( \"mats2ids\", vmIDs );\r\n\r\n\tQVariantMap viIDs;\r\n\tfor( auto key : GameState::itemSID2ID.keys() )\r\n\t{\r\n\t\tviIDs.insert( key, itemSID2ID.value( key ) );\r\n\t}\r\n\tout.insert( \"items2ids\", viIDs );\r\n\r\n}\r\n\r\nvoid GameState::load( QVariantMap& vals )\r\n{\r\n\t// compatibility with older saves\r\n\tQVariantMap tmp;\r\n\tfor ( auto key : vals.keys() )\r\n\t{\r\n\t\tQString newKey = key;\r\n\t\tnewKey[0]      = key[0].toLower();\r\n\r\n\t\ttmp.insert( newKey, vals.value( key ) );\r\n\t}\r\n\r\n\tGlobal::dimX = tmp.value( \"dimX\" ).toInt();\r\n\tGlobal::dimY = tmp.value( \"dimY\" ).toInt();\r\n\tGlobal::dimZ = tmp.value( \"dimZ\" ).toInt();\r\n\r\n\talarm       = tmp.value( \"alarm\" ).toInt();\r\n\talarmRoomID = tmp.value( \"alarmRoomID\" ).toUInt();\r\n\r\n\tdaylight    = tmp.value( \"daylight\" ).toBool();\r\n\tinitialSave = tmp.value( \"initialSave\" ).toBool();\r\n\titemFilter  = tmp.value( \"itemFilter\" ).toList();\r\n\r\n\tmilitary  = tmp.value( \"military\" ).toMap();   // military manager\r\n\tneighbors = tmp.value( \"neighbors\" ).toList(); // neighbor manager\r\n\r\n\torigin = Position( tmp.value( \"origin\" ) );\r\n\tsquads = tmp.value( \"squads\" ).toList();\r\n\r\n\tstockOverlay = tmp.value( \"stockOverlay\" ).toList();\r\n\r\n\t//TODO old format has them as single entries\r\n\tif( tmp.contains( \"techWood\" ) )\r\n\t{\r\n\t\tGameState::techs.clear();\r\n\t\tfor( auto t : DB::ids( \"Tech\" ) )\r\n\t\t{\r\n\t\t\tGameState::techs.insert( t, tmp.value( t ).toInt() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttechs = tmp.value( \"techs\" ).toMap();\r\n\t}\r\n\r\n\tversion  = tmp.value( \"version\" ).toString();\r\n\tflatness = tmp.value( \"flatness\" ).toInt();\r\n\r\n\t//old version has prefix game_ for the next values\r\n\tif ( tmp.contains( \"game_day\" ) )\r\n\t{\r\n\t\tday    = tmp.value( \"game_day\" ).toInt();\r\n\t\thour   = tmp.value( \"game_hour\" ).toInt();\r\n\t\tminute = tmp.value( \"game_minute\" ).toInt();\r\n\t\tseason = tmp.value( \"game_season\" ).toInt();\r\n\t\tyear   = tmp.value( \"game_year\" ).toInt();\r\n\r\n\t\tnextSunrise = tmp.value( \"game_nextSunrise\" ).toInt();\r\n\t\tsunrise     = tmp.value( \"game_sunrise\" ).toInt();\r\n\t\tsunset      = tmp.value( \"game_sunset\" ).toInt();\r\n\r\n\t\tdayChanged    = tmp.value( \"game_dayChanged\" ).toBool();\r\n\t\thourChanged   = tmp.value( \"game_hourChanged\" ).toBool();\r\n\t\tminuteChanged = tmp.value( \"game_minuteChanged\" ).toBool();\r\n\t\tseasonChanged = tmp.value( \"game_seasonChanged\" ).toBool();\r\n\r\n\t\tseasonString = tmp.value( \"season\" ).toString();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tday    = tmp.value( \"day\" ).toInt();\r\n\t\thour   = tmp.value( \"hour\" ).toInt();\r\n\t\tminute = tmp.value( \"minute\" ).toInt();\r\n\t\tseason = tmp.value( \"season\" ).toInt();\r\n\t\tyear   = tmp.value( \"year\" ).toInt();\r\n\r\n\t\tnextSunrise = tmp.value( \"nextSunrise\" ).toInt();\r\n\t\tsunrise     = tmp.value( \"sunrise\" ).toInt();\r\n\t\tsunset      = tmp.value( \"sunset\" ).toInt();\r\n\r\n\t\tdayChanged    = tmp.value( \"dayChanged\" ).toBool();\r\n\t\thourChanged   = tmp.value( \"hourChanged\" ).toBool();\r\n\t\tminuteChanged = tmp.value( \"minuteChanged\" ).toBool();\r\n\t\tseasonChanged = tmp.value( \"seasonChanged\" ).toBool();\r\n\r\n\t\tseasonString = tmp.value( \"seasonString\" ).toString();\r\n\t}\r\n\r\n\tgroundLevel = tmp.value( \"groundLevel\" ).toInt();\r\n\tkingdomName = tmp.value( \"kingdomName\" ).toString();\r\n\r\n\tpeaceful = tmp.value( \"peaceful\" ).toBool();\r\n\r\n\ttick = tmp.value( \"tick\" ).value<quint64>();\r\n\r\n\tnumAnimals   = tmp.value( \"numAnimals\" ).toInt();\r\n\tnumGnomes    = tmp.value( \"numGnomes\" ).toInt();\r\n\toceanSize    = tmp.value( \"oceanSize\" ).toInt();\r\n\tplantDensity = tmp.value( \"plantDensity\" ).toInt();\r\n\ttreeDensity  = tmp.value( \"treeDensity\" ).toInt();\r\n\triverSize    = tmp.value( \"riverSize\" ).toInt();\r\n\trivers       = tmp.value( \"rivers\" ).toInt();\r\n\tseed         = tmp.value( \"seed\" ).toString();\r\n\r\n\tstartingItems = tmp.value( \"startingItems\" ).toList();\r\n\r\n\tstartingZone = tmp.value( \"startingZone\" ).toInt();\r\n\r\n\tnextID = tmp.value( \"nextID\" ).toUInt();\r\n\r\n\tmaxAnimalsPerType = tmp.value( \"maxAnimalsPerType\" ).toInt();\r\n\tallowedAnimals    = tmp.value( \"allowedAnimals\" ).toMap();\r\n\tallowedPlants     = tmp.value( \"allowedPlants\" ).toMap();\r\n\tallowedTrees      = tmp.value( \"allowedTrees\" ).toMap();\r\n\r\n\taddedMaterials    = tmp.value( \"addedMaterials\" ).toList();\r\n\taddedTranslations = tmp.value( \"addedTranslations\" ).toMap();\r\n\r\n\tmoveX = tmp.value( \"moveX\" ).toInt();\r\n\tmoveY = tmp.value( \"moveY\" ).toInt();\r\n\tscale = qMax( tmp.value( \"scale\" ).toFloat(), 1.0f );\r\n\tviewLevel = qMax( tmp.value( \"viewLevel\" ).toInt(), 100 );\r\n\r\n\tGameState::watchedItemList.clear();\r\n\tauto qwil = tmp.value( \"watchedItems\" ).toList();\r\n\tfor( auto qval : qwil )\r\n\t{\r\n\t\tQVariantMap qwi = qval.toMap();\r\n\t\tGuiWatchedItem gwi{ qwi.value( \"category\" ).toString(), qwi.value( \"group\" ).toString(), qwi.value( \"item\" ).toString(), qwi.value( \"material\" ).toString() };\r\n\t\tGameState::watchedItemList.append( gwi );\r\n\t}\r\n\r\n\titemSID2ID.clear();\r\n\titemID2SID.clear();\r\n\tQVariantMap viIDs= tmp.value( \"items2ids\" ).toMap();\r\n\r\n\tif( viIDs.isEmpty() )\r\n\t{\r\n\t\tfor( auto id : DB::ids( \"Items\" ) )\r\n\t\t{\r\n\t\t\tint rowid = DBH::rowID( \"Items\", id );\r\n\t\t\titemID2SID.insert( rowid, id );\r\n\t\t\titemSID2ID.insert( id, rowid );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( auto key : viIDs.keys() )\r\n\t\t{\r\n\t\t\titemID2SID.insert( viIDs.value( key ).toInt(), key );\r\n\t\t\titemSID2ID.insert( key, viIDs.value( key ).toInt() );\r\n\t\t}\r\n\t}\r\n\r\n\tmaterialSID2ID.clear();\r\n\tmaterialID2SID.clear();\r\n\tQVariantMap vmIDs= tmp.value( \"mats2ids\" ).toMap();\r\n\r\n\tif( vmIDs.isEmpty() )\r\n\t{\r\n\t\tfor( auto id : DB::ids( \"Materials\" ) )\r\n\t\t{\r\n\t\t\tint rowid = DBH::rowID( \"Materials\", id );\r\n\t\t\tmaterialID2SID.insert( rowid, id );\r\n\t\t\tmaterialSID2ID.insert( id, rowid );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( auto key : vmIDs.keys() )\r\n\t\t{\r\n\t\t\tmaterialID2SID.insert( vmIDs.value( key ).toInt(), key );\r\n\t\t\tmaterialSID2ID.insert( key, vmIDs.value( key ).toInt() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int GameState::createID()\r\n{\r\n\treturn nextID++;\r\n}\r\n"
  },
  {
    "path": "src/base/gamestate.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef GAMESTATE_H_\r\n#define GAMESTATE_H_\r\n\r\n#include \"../base/position.h\"\r\n#include \"../gui/aggregatorinventory.h\"\r\n\r\n#include <QHash>\r\n#include <QString>\r\n#include <QVariant>\r\n#include <QVariantMap>\r\n\r\n#include <initializer_list>\r\n\r\nclass GameState\r\n{\r\nprivate:\r\n\tbool m_acceptChangeSets = false;\r\n\r\npublic:\r\n\tGameState() = delete;\r\n\t~GameState() = delete;\r\n\r\n\tstatic unsigned int createID();\r\n\r\n\tstatic bool init();\r\n\r\n\tstatic void serialize( QVariantMap& out );\r\n\tstatic void load( QVariantMap& in );\r\n\r\n\tstatic int alarm;\r\n\tstatic unsigned int alarmRoomID;\r\n\t\r\n\tstatic bool daylight;\r\n\tstatic bool initialSave;\r\n\tstatic QVariantList itemFilter;\r\n\r\n\tstatic QVariantMap military; // military manager\r\n\tstatic QVariantList neighbors; // neighbor manager\r\n\r\n\tstatic Position origin;\r\n\tstatic QVariantList squads;\r\n\r\n\tstatic QVariantList stockOverlay;\r\n\r\n\tstatic QVariantMap techs;\r\n\r\n\tstatic QString version;\r\n\r\n\tstatic int flatness;\r\n\t\r\n\tstatic int day;\r\n\tstatic int hour;\r\n\tstatic int minute;\r\n\tstatic int season;\r\n\tstatic int year;\r\n\r\n\tstatic QString seasonString;\r\n\tstatic QString currentDayTime;\r\n\tstatic QString currentYearAndSeason;\r\n\r\n\tstatic bool dayChanged;\r\n\tstatic bool hourChanged;\r\n\tstatic bool minuteChanged;\r\n\tstatic bool seasonChanged;\r\n\r\n\tstatic int nextSunrise;\r\n\tstatic int sunrise;\r\n\tstatic int sunset;\r\n\t\r\n\tstatic int groundLevel;\r\n\tstatic QString kingdomName;\r\n\t\r\n\tstatic bool peaceful;\r\n\r\n\tstatic quint64 tick;\r\n\r\n\tstatic int numAnimals;\r\n\tstatic int numGnomes;\r\n\tstatic int oceanSize;\r\n\tstatic int plantDensity;\r\n\tstatic int treeDensity;\r\n\tstatic int riverSize;\r\n\tstatic int rivers;\r\n\tstatic QString seed;\r\n\r\n\tstatic QVariantList startingItems;\r\n\r\n\tstatic unsigned int startingZone;\r\n\t\r\n\tstatic int maxAnimalsPerType;\r\n\tstatic QVariantMap allowedAnimals;\r\n\tstatic QVariantMap allowedPlants;\r\n\tstatic QVariantMap allowedTrees;\r\n\r\n\tstatic QVariantList addedMaterials;\r\n\tstatic QVariantMap addedTranslations;\r\n\r\n\tstatic int moveX;\r\n\tstatic int moveY;\r\n\tstatic float scale;\r\n\tstatic int viewLevel;\r\n\r\n\tstatic QList<GuiWatchedItem> watchedItemList;\r\n\r\n\tstatic QHash<QString, int> materialSID2ID;\r\n\tstatic QHash<int, QString> materialID2SID;\r\n\tstatic QHash<QString, int> itemSID2ID;\r\n\tstatic QHash<int, QString> itemID2SID;\r\n\r\nprivate:\r\n\tstatic unsigned int nextID;\r\n\r\n};\r\n\r\n#endif /* GAMESTATE_H_ */\r\n"
  },
  {
    "path": "src/base/global.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"global.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/io.h\"\r\n#include \"../base/logger.h\"\r\n#include \"../base/util.h\"\r\n\r\n#include <QDebug>\r\n#include <QFile>\r\n#include <QJsonArray>\r\n#include <QJsonDocument>\r\n#include <QStandardPaths>\r\n\r\nEventConnector* Global::eventConnector = nullptr;\r\nUtil* Global::util = nullptr;\r\nSelection* Global::sel = nullptr;\r\nNewGameSettings* Global::newGameSettings = nullptr;\r\nConfig* Global::cfg = nullptr;\r\n\r\nLogger Global::m_logger;\r\n\r\nbool Global::wallsLowered = false;\r\nbool Global::showAxles    = false;\r\nbool Global::showDesignations = true;\r\nbool Global::showJobs = true;\r\n\r\nunsigned int Global::waterSpriteUID  = 0;\r\nunsigned int Global::undiscoveredUID = 0;\r\n\r\nQVariantMap Global::copiedStockpileSettings;\r\n\r\nQMap<QString, QVariantMap> Global::m_windowParams;\r\n\r\nQMap<QString, QSet<QString>> Global::allowedInContainer;\r\n\r\nQHash<Qt::Key, Noesis::Key> Global::keyConvertMap;\r\n\r\nint Global::dimX     = 100;\r\nint Global::dimY     = 100;\r\nint Global::dimZ     = 100;\r\n\r\nint Global::zWeight = 20;\r\n\r\ndouble Global::xpMod = 250.;\r\n\r\nbool Global::debugMode = false;\r\nbool Global::debugOpenGL = false;\r\nbool Global::debugSound = false;\r\n\r\nQMap<QString, QDomElement> Global::m_behaviorTrees;\r\n\r\nQStringList Global::needIDs;\r\nQMap<QString, float> Global::needDecays;\r\n\r\nunsigned int Global::dirtUID = 0;\r\n\r\nQMap<QString, CreaturePart> Global::creaturePartLookUp;\r\nQMap<CreaturePart, QString> Global::creaturePartToString;\r\n\r\nQSet<QString> Global::craftable;\r\n\r\nvoid Global::reset()\r\n{\r\n\tqDebug() << \"*** Global reset\";\r\n\r\n\tGameState::stockOverlay.clear();\r\n\tGameState::squads.clear();\r\n\r\n\tGlobal::xpMod = Global::cfg->get( \"XpMod\" ).toDouble();\r\n\r\n\tm_logger.reset();\r\n\r\n\twallsLowered = false;\r\n\tshowAxles    = false;\r\n\r\n\t//m_keyBindings.update();\r\n\r\n\tif ( !loadBehaviorTrees() )\r\n\t{\r\n\t\tqCritical() << \"failed to load behavior trees\";\r\n\t\tabort();\r\n\t}\r\n\r\n\tneedIDs.clear();\r\n\tneedDecays.clear();\r\n\r\n\tfor ( auto row : DB::selectRows( \"Needs\" ) )\r\n\t{\r\n\t\tif ( row.value( \"Creature\" ).toString() == \"Gnome\" )\r\n\t\t{\r\n\t\t\tauto need = row.value( \"ID\" ).toString();\r\n\t\t\tneedIDs.append( need );\r\n\t\t\tneedDecays.insert( need, row.value( \"DecayPerMinute\" ).toFloat() );\r\n\t\t}\r\n\t}\r\n\r\n\tGlobal::dirtUID = DBH::materialUID( \"Dirt\" );\r\n\r\n\tGlobal::cfg->set( \"renderCreatures\", true );\r\n\r\n\tcreaturePartLookUp.insert( \"Head\", CP_HEAD );\r\n\tcreaturePartLookUp.insert( \"Torso\", CP_TORSO );\r\n\tcreaturePartLookUp.insert( \"LeftArm\", CP_LEFT_ARM );\r\n\tcreaturePartLookUp.insert( \"RightArm\", CP_RIGHT_ARM );\r\n\tcreaturePartLookUp.insert( \"LeftHand\", CP_LEFT_HAND );\r\n\tcreaturePartLookUp.insert( \"RightHand\", CP_RIGHT_HAND );\r\n\tcreaturePartLookUp.insert( \"LeftLeg\", CP_LEFT_LEG );\r\n\tcreaturePartLookUp.insert( \"RightLeg\", CP_RIGHT_LEG );\r\n\tcreaturePartLookUp.insert( \"LeftFoot\", CP_LEFT_FOOT );\r\n\tcreaturePartLookUp.insert( \"RightFoot\", CP_RIGHT_FOOT );\r\n\r\n\tcreaturePartLookUp.insert( \"LeftFrontLeg\", CP_LEFT_FRONT_LEG );\r\n\tcreaturePartLookUp.insert( \"LegFrontLeg\", CP_RIGHT_FRONT_LEG );\r\n\tcreaturePartLookUp.insert( \"LeftFrontFoot\", CP_LEFT_FRONT_FOOT );\r\n\tcreaturePartLookUp.insert( \"RightFrontFoot\", CP_RIGHT_FRONT_FOOT );\r\n\r\n\tcreaturePartLookUp.insert( \"LeftWing\", CP_RIGHT_WING );\r\n\tcreaturePartLookUp.insert( \"RightWing\", CP_RIGHT_WING );\r\n\r\n\tcreaturePartLookUp.insert( \"Brain\", CP_BRAIN );\r\n\tcreaturePartLookUp.insert( \"LeftEye\", CP_LEFT_EYE );\r\n\tcreaturePartLookUp.insert( \"RightEye\", CP_RIGHT_EYE );\r\n\tcreaturePartLookUp.insert( \"Heart\", CP_HEART );\r\n\tcreaturePartLookUp.insert( \"LeftLung\", CP_LEFT_LUNG );\r\n\tcreaturePartLookUp.insert( \"RightLung\", CP_RIGHT_LUNG );\r\n\r\n\tcreaturePartLookUp.insert( \"Hair\", CP_HAIR );\r\n\tcreaturePartLookUp.insert( \"Facial\", CP_FACIAL_HAIR );\r\n\tcreaturePartLookUp.insert( \"Clothing\", CP_CLOTHING );\r\n\tcreaturePartLookUp.insert( \"Boots\", CP_BOOTS );\r\n\tcreaturePartLookUp.insert( \"Hat\", CP_HAT );\r\n\tcreaturePartLookUp.insert( \"Back\", CP_BACK );\r\n\r\n\tcreaturePartLookUp.insert( \"HeadArmor\", CP_ARMOR_HEAD );\r\n\tcreaturePartLookUp.insert( \"ChestArmor\", CP_ARMOR_TORSO );\r\n\tcreaturePartLookUp.insert( \"LeftArmArmor\", CP_ARMOR_LEFT_ARM );\r\n\tcreaturePartLookUp.insert( \"RightArmArmor\", CP_ARMOR_RIGHT_ARM );\r\n\tcreaturePartLookUp.insert( \"LeftHandArmor\", CP_ARMOR_LEFT_HAND );\r\n\tcreaturePartLookUp.insert( \"RightHandArmor\", CP_ARMOR_RIGHT_HAND );\r\n\tcreaturePartLookUp.insert( \"LeftFootArmor\", CP_ARMOR_LEFT_FOOT );\r\n\tcreaturePartLookUp.insert( \"RightFootArmor\", CP_ARMOR_RIGHT_FOOT );\r\n\tcreaturePartLookUp.insert( \"LeftHandHeld\", CP_LEFT_HAND_HELD );\r\n\tcreaturePartLookUp.insert( \"RightHandHeld\", CP_RIGHT_HAND_HELD );\r\n\r\n\tcreaturePartLookUp.insert( \"ArmArmor\", CP_ARMOR_ARM );\r\n\tcreaturePartLookUp.insert( \"HandArmor\", CP_ARMOR_HAND );\r\n\tcreaturePartLookUp.insert( \"FootArmor\", CP_ARMOR_FOOT );\r\n\tcreaturePartLookUp.insert( \"LegArmor\", CP_ARMOR_LEG );\r\n\r\n\tcreaturePartToString.insert( CP_HEAD, \"Head\" );\r\n\tcreaturePartToString.insert( CP_TORSO, \"Torso\" );\r\n\tcreaturePartToString.insert( CP_LEFT_ARM, \"LeftArm\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_ARM, \"RightArm\" );\r\n\tcreaturePartToString.insert( CP_LEFT_HAND, \"LeftHand\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_HAND, \"RightHand\" );\r\n\tcreaturePartToString.insert( CP_LEFT_LEG, \"LeftLeg\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_LEG, \"LegLeg\" );\r\n\tcreaturePartToString.insert( CP_LEFT_FOOT, \"LeftFoot\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_FOOT, \"RightFoot\" );\r\n\r\n\tcreaturePartToString.insert( CP_LEFT_FRONT_LEG, \"LeftFrontLeg\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_FRONT_LEG, \"LegFrontLeg\" );\r\n\tcreaturePartToString.insert( CP_LEFT_FRONT_FOOT, \"LeftFrontFoot\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_FRONT_FOOT, \"RightFrontFoot\" );\r\n\r\n\tcreaturePartToString.insert( CP_LEFT_WING, \"LeftWing\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_WING, \"RightWing\" );\r\n\r\n\tcreaturePartToString.insert( CP_BRAIN, \"Brain\" );\r\n\tcreaturePartToString.insert( CP_LEFT_EYE, \"LeftEye\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_EYE, \"RightEye\" );\r\n\tcreaturePartToString.insert( CP_HEART, \"Heart\" );\r\n\tcreaturePartToString.insert( CP_LEFT_LUNG, \"LeftLung\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_LUNG, \"RightLung\" );\r\n\r\n\tcreaturePartToString.insert( CP_HAIR, \"Hair\" );\r\n\tcreaturePartToString.insert( CP_FACIAL_HAIR, \"Facial\" );\r\n\tcreaturePartToString.insert( CP_CLOTHING, \"Clothing\" );\r\n\tcreaturePartToString.insert( CP_BOOTS, \"Boots\" );\r\n\tcreaturePartToString.insert( CP_HAT, \"Hat\" );\r\n\tcreaturePartToString.insert( CP_BACK, \"Back\" );\r\n\r\n\tcreaturePartToString.insert( CP_ARMOR_HEAD, \"HeadArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_TORSO, \"ChestArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_LEFT_ARM, \"LeftArmArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_RIGHT_ARM, \"RightArmArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_LEFT_HAND, \"LeftHandArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_RIGHT_HAND, \"RightHandArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_LEFT_FOOT, \"LeftFootArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_RIGHT_FOOT, \"RightFootArmor\" );\r\n\tcreaturePartToString.insert( CP_LEFT_HAND_HELD, \"LeftHandHeld\" );\r\n\tcreaturePartToString.insert( CP_RIGHT_HAND_HELD, \"RightHandHeld\" );\r\n\r\n\tcreaturePartToString.insert( CP_ARMOR_ARM, \"ArmArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_HAND, \"HandArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_FOOT, \"FootArmor\" );\r\n\tcreaturePartToString.insert( CP_ARMOR_LEG, \"LegArmor\" );\r\n\r\n\tcraftable.clear();\r\n\tauto rows = DB::selectRows( \"Crafts\" );\r\n\tfor( const auto& row : rows )\r\n\t{\r\n\t\tcraftable.insert( row.value( \"ItemID\" ).toString() );\r\n\t}\r\n}\r\n\r\nLogger& Global::logger()\r\n{\r\n\treturn m_logger;\r\n}\r\n\r\n/*\r\nKeyBindings& Global::keyBindings()\r\n{\r\n\treturn m_keyBindings;\r\n}\r\n*/\r\n\r\nbool Global::loadBehaviorTrees()\r\n{\r\n\tm_behaviorTrees.clear();\r\n\r\n\tfor ( auto id : DB::ids( \"AI\" ) )\r\n\t{\r\n\t\tQString xmlName = DB::select( \"BehaviorTree\", \"AI\", id ).toString();\r\n\r\n\t\tQDomDocument xml;\r\n\t\t// Load xml file as raw data\r\n\t\tQFile f( Global::cfg->get( \"dataPath\" ).toString() + \"/ai/\" + xmlName );\r\n\t\tif ( !f.open( QIODevice::ReadOnly ) )\r\n\t\t{\r\n\t\t\t// Error while loading file\r\n\t\t\tqDebug() << \"Error while loading file xmlName\";\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// Set data into the QDomDocument before processing\r\n\t\txml.setContent( &f );\r\n\t\tf.close();\r\n\r\n\t\tQDomElement root = xml.documentElement();\r\n\t\tm_behaviorTrees.insert( id, root );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQDomElement Global::behaviorTree( QString id )\r\n{\r\n\treturn m_behaviorTrees.value( id );\r\n}\r\n\r\nbool Global::addBehaviorTree( QString id, QString path )\r\n{\r\n\tQDomDocument xml;\r\n\t// Load xml file as raw data\r\n\tQFile f( path );\r\n\tif ( !f.open( QIODevice::ReadOnly ) )\r\n\t{\r\n\t\t// Error while loading file\r\n\t\tqDebug() << \"Error while loading file xmlName\";\r\n\t\treturn false;\r\n\t}\r\n\t// Set data into the QDomDocument before processing\r\n\txml.setContent( &f );\r\n\tf.close();\r\n\r\n\tQDomElement root = xml.documentElement();\r\n\tm_behaviorTrees.insert( id, root );\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid Global::initKeyConvert()\r\n{\r\n\tkeyConvertMap.clear();\r\n\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_None );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_Cancel, Noesis::Key_Cancel );\r\n\tkeyConvertMap.insert( Qt::Key_Backspace, Noesis::Key_Back );\r\n\tkeyConvertMap.insert( Qt::Key_Tab, Noesis::Key_Tab );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_LineFeed );\r\n\tkeyConvertMap.insert( Qt::Key_Clear, Noesis::Key_Clear );\r\n\tkeyConvertMap.insert( Qt::Key_Return, Noesis::Key_Return );\r\n\tkeyConvertMap.insert( Qt::Key_Enter, Noesis::Key_Enter );\r\n\tkeyConvertMap.insert( Qt::Key_Pause, Noesis::Key_Pause );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_Capital );\r\n\tkeyConvertMap.insert( Qt::Key_CapsLock, Noesis::Key_CapsLock );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_Escape, Noesis::Key_Escape );\r\n\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_ImeConvert );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_ImeNonConvert );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_ImeAccept );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_ImeModeChange );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_Space, Noesis::Key_Space );\r\n\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_Prior );\r\n\tkeyConvertMap.insert( Qt::Key_PageUp, Noesis::Key_PageUp );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_Next );\r\n\tkeyConvertMap.insert( Qt::Key_PageDown, Noesis::Key_PageDown );\r\n\tkeyConvertMap.insert( Qt::Key_End, Noesis::Key_End );\r\n\tkeyConvertMap.insert( Qt::Key_Home, Noesis::Key_Home );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_Left, Noesis::Key_Left );\r\n\tkeyConvertMap.insert( Qt::Key_Up, Noesis::Key_Up );\r\n\tkeyConvertMap.insert( Qt::Key_Right, Noesis::Key_Right );\r\n\tkeyConvertMap.insert( Qt::Key_Down, Noesis::Key_Down );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_Select, Noesis::Key_Select );\r\n\tkeyConvertMap.insert( Qt::Key_Print, Noesis::Key_Print );\r\n\tkeyConvertMap.insert( Qt::Key_Execute, Noesis::Key_Execute );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_Snapshot );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_PrintScreen );\r\n\tkeyConvertMap.insert( Qt::Key_Insert, Noesis::Key_Insert );\r\n\tkeyConvertMap.insert( Qt::Key_Delete, Noesis::Key_Delete );\r\n\tkeyConvertMap.insert( Qt::Key_Help, Noesis::Key_Help );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_0, Noesis::Key_D0 );\r\n\tkeyConvertMap.insert( Qt::Key_1, Noesis::Key_D1 );\r\n\tkeyConvertMap.insert( Qt::Key_2, Noesis::Key_D2 );\r\n\tkeyConvertMap.insert( Qt::Key_3, Noesis::Key_D3 );\r\n\tkeyConvertMap.insert( Qt::Key_4, Noesis::Key_D4 );\r\n\tkeyConvertMap.insert( Qt::Key_5, Noesis::Key_D5 );\r\n\tkeyConvertMap.insert( Qt::Key_6, Noesis::Key_D6 );\r\n\tkeyConvertMap.insert( Qt::Key_7, Noesis::Key_D7 );\r\n\tkeyConvertMap.insert( Qt::Key_8, Noesis::Key_D8 );\r\n\tkeyConvertMap.insert( Qt::Key_9, Noesis::Key_D9 );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_A, Noesis::Key_A );\r\n\tkeyConvertMap.insert( Qt::Key_B, Noesis::Key_B );\r\n\tkeyConvertMap.insert( Qt::Key_C, Noesis::Key_C );\r\n\tkeyConvertMap.insert( Qt::Key_D, Noesis::Key_D );\r\n\tkeyConvertMap.insert( Qt::Key_E, Noesis::Key_E );\r\n\tkeyConvertMap.insert( Qt::Key_F, Noesis::Key_F );\r\n\tkeyConvertMap.insert( Qt::Key_G, Noesis::Key_G );\r\n\tkeyConvertMap.insert( Qt::Key_H, Noesis::Key_H );\r\n\tkeyConvertMap.insert( Qt::Key_I, Noesis::Key_I );\r\n\tkeyConvertMap.insert( Qt::Key_J, Noesis::Key_J );\r\n\tkeyConvertMap.insert( Qt::Key_K, Noesis::Key_K );\r\n\tkeyConvertMap.insert( Qt::Key_L, Noesis::Key_L );\r\n\tkeyConvertMap.insert( Qt::Key_M, Noesis::Key_M );\r\n\tkeyConvertMap.insert( Qt::Key_N, Noesis::Key_N );\r\n\tkeyConvertMap.insert( Qt::Key_O, Noesis::Key_O );\r\n\tkeyConvertMap.insert( Qt::Key_P, Noesis::Key_P );\r\n\tkeyConvertMap.insert( Qt::Key_Q, Noesis::Key_Q );\r\n\tkeyConvertMap.insert( Qt::Key_R, Noesis::Key_R );\r\n\tkeyConvertMap.insert( Qt::Key_S, Noesis::Key_S );\r\n\tkeyConvertMap.insert( Qt::Key_T, Noesis::Key_T );\r\n\tkeyConvertMap.insert( Qt::Key_U, Noesis::Key_U );\r\n\tkeyConvertMap.insert( Qt::Key_V, Noesis::Key_V );\r\n\tkeyConvertMap.insert( Qt::Key_W, Noesis::Key_W );\r\n\tkeyConvertMap.insert( Qt::Key_X, Noesis::Key_X );\r\n\tkeyConvertMap.insert( Qt::Key_Y, Noesis::Key_Y );\r\n\tkeyConvertMap.insert( Qt::Key_Z, Noesis::Key_Z );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_ApplicationLeft, Noesis::Key_LWin );\r\n\tkeyConvertMap.insert( Qt::Key_ApplicationRight, Noesis::Key_RWin );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_Apps );\r\n\tkeyConvertMap.insert( Qt::Key_Sleep, Noesis::Key_Sleep );\r\n\t/*\r\n\tkeyConvertMap.insert( Qt::Key_0, Noesis::Key_NumPad0 );\r\n\tkeyConvertMap.insert( Qt::Key_1, Noesis::Key_NumPad1 );\r\n\tkeyConvertMap.insert( Qt::Key_2, Noesis::Key_NumPad2 );\r\n\tkeyConvertMap.insert( Qt::Key_3, Noesis::Key_NumPad3 );\r\n\tkeyConvertMap.insert( Qt::Key_4, Noesis::Key_NumPad4 );\r\n\tkeyConvertMap.insert( Qt::Key_5, Noesis::Key_NumPad5 );\r\n\tkeyConvertMap.insert( Qt::Key_6, Noesis::Key_NumPad6 );\r\n\tkeyConvertMap.insert( Qt::Key_7, Noesis::Key_NumPad7 );\r\n\tkeyConvertMap.insert( Qt::Key_8, Noesis::Key_NumPad8 );\r\n\tkeyConvertMap.insert( Qt::Key_9, Noesis::Key_NumPad9 );\r\n\t*/\r\n\tkeyConvertMap.insert( Qt::Key_multiply, Noesis::Key_Multiply );\r\n\tkeyConvertMap.insert( Qt::Key_Plus, Noesis::Key_Add );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_Separator );\r\n\tkeyConvertMap.insert( Qt::Key_Minus, Noesis::Key_Subtract );\r\n\tkeyConvertMap.insert( Qt::Key_Colon, Noesis::Key_Decimal );\r\n\tkeyConvertMap.insert( Qt::Key_division, Noesis::Key_Divide );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_F1, Noesis::Key_F1 );\r\n\tkeyConvertMap.insert( Qt::Key_F2, Noesis::Key_F2 );\r\n\tkeyConvertMap.insert( Qt::Key_F3, Noesis::Key_F3 );\r\n\tkeyConvertMap.insert( Qt::Key_F4, Noesis::Key_F4 );\r\n\tkeyConvertMap.insert( Qt::Key_F5, Noesis::Key_F5 );\r\n\tkeyConvertMap.insert( Qt::Key_F6, Noesis::Key_F6 );\r\n\tkeyConvertMap.insert( Qt::Key_F7, Noesis::Key_F7 );\r\n\tkeyConvertMap.insert( Qt::Key_F8, Noesis::Key_F8 );\r\n\tkeyConvertMap.insert( Qt::Key_F9, Noesis::Key_F9 );\r\n\tkeyConvertMap.insert( Qt::Key_F10, Noesis::Key_F10 );\r\n\tkeyConvertMap.insert( Qt::Key_F11, Noesis::Key_F11 );\r\n\tkeyConvertMap.insert( Qt::Key_F12, Noesis::Key_F12 );\r\n\tkeyConvertMap.insert( Qt::Key_F13, Noesis::Key_F13 );\r\n\tkeyConvertMap.insert( Qt::Key_F14, Noesis::Key_F14 );\r\n\tkeyConvertMap.insert( Qt::Key_F15, Noesis::Key_F15 );\r\n\tkeyConvertMap.insert( Qt::Key_F16, Noesis::Key_F16 );\r\n\tkeyConvertMap.insert( Qt::Key_F17, Noesis::Key_F17 );\r\n\tkeyConvertMap.insert( Qt::Key_F18, Noesis::Key_F18 );\r\n\tkeyConvertMap.insert( Qt::Key_F19, Noesis::Key_F19 );\r\n\tkeyConvertMap.insert( Qt::Key_F20, Noesis::Key_F20 );\r\n\tkeyConvertMap.insert( Qt::Key_F21, Noesis::Key_F21 );\r\n\tkeyConvertMap.insert( Qt::Key_F22, Noesis::Key_F22 );\r\n\tkeyConvertMap.insert( Qt::Key_F23, Noesis::Key_F23 );\r\n\tkeyConvertMap.insert( Qt::Key_F24, Noesis::Key_F24 );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_NumLock, Noesis::Key_NumLock );\r\n\tkeyConvertMap.insert( Qt::Key_ScrollLock, Noesis::Key_Scroll );\r\n\r\n\tkeyConvertMap.insert( Qt::Key_Shift, Noesis::Key_LeftShift );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_RightShift );\r\n\tkeyConvertMap.insert( Qt::Key_Control, Noesis::Key_LeftCtrl );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_RightCtrl );\r\n\tkeyConvertMap.insert( Qt::Key_Alt, Noesis::Key_LeftAlt );\r\n\tkeyConvertMap.insert( Qt::Key_AltGr, Noesis::Key_RightAlt );\r\n\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_PageLeft );\r\n\t//keyConvertMap.insert( Qt::Key_, Noesis::Key_PageRight );\r\n}\r\n\r\nNoesis::Key Global::keyConvert( Qt::Key key )\r\n{\r\n\tif ( keyConvertMap.isEmpty() )\r\n\t{\r\n\t\tinitKeyConvert();\r\n\t}\r\n\tif ( keyConvertMap.contains( key ) )\r\n\t{\r\n\t\treturn keyConvertMap.value( key );\r\n\t}\r\n\treturn Noesis::Key_None;\r\n}"
  },
  {
    "path": "src/base/global.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/enums.h\"\r\n#include \"../base/logger.h\"\r\n\r\n#include <NsGui/InputEnums.h>\r\n\r\n#include <QDomElement>\r\n#include <QMap>\r\n#include <QSet>\r\n#include <QString>\r\n#include <QVariant>\r\n#include <QtGlobal>\r\n\r\nclass EventConnector;\r\nclass Util;\r\nclass Logger;\r\nclass Selection;\r\nclass NewGameSettings;\r\nclass Config;\r\n\r\nclass Global\r\n{\r\npublic:\r\n\tGlobal()  = delete;\r\n\t~Global() = delete;\r\n\r\n\tstatic void reset();\r\n\r\n\tstatic Logger& logger();\r\n\r\n\tstatic QDomElement behaviorTree( QString id );\r\n\r\n\t//static KeyBindings& keyBindings();\r\n\tstatic bool wallsLowered;\r\n\tstatic bool showDesignations;\r\n\tstatic bool showJobs;\r\n\tstatic bool showAxles;\r\n\r\n\tstatic unsigned int waterSpriteUID;\r\n\tstatic unsigned int undiscoveredUID;\r\n\r\n\tstatic QVariantMap copiedStockpileSettings;\r\n\r\n\tstatic QMap<QString, QVariantMap> m_windowParams;\r\n\r\n\tstatic int dimX;\r\n\tstatic int dimY;\r\n\tstatic int dimZ;\r\n\tstatic int zWeight;\r\n\tstatic double xpMod;\r\n\tstatic bool debugMode;\r\n\tstatic bool debugOpenGL;\r\n\tstatic bool debugSound;\r\n\r\n\tstatic QMap<QString, QSet<QString>> allowedInContainer;\r\n\r\n\tstatic QStringList needIDs;\r\n\tstatic QMap<QString, float> needDecays;\r\n\r\n\tstatic unsigned int dirtUID;\r\n\r\n\tstatic bool addBehaviorTree( QString id, QString path );\r\n\r\n\tstatic QHash<Qt::Key, Noesis::Key> keyConvertMap;\r\n\r\n\tstatic QMap<QString, CreaturePart> creaturePartLookUp;\r\n\tstatic QMap<CreaturePart, QString> creaturePartToString;\r\n\r\n\tstatic Noesis::Key keyConvert( Qt::Key key );\r\n\r\n\tstatic QSet<QString> craftable;\r\n\r\n\tstatic EventConnector* eventConnector;\r\n\tstatic Util* util;\r\n\tstatic Selection* sel;\r\n\tstatic NewGameSettings* newGameSettings;\r\n\tstatic Config* cfg;\r\n\r\nprivate:\r\n\tstatic Logger m_logger;\r\n\r\n\t//static KeyBindings m_keyBindings;\r\n\r\n\tstatic QMap<QString, QDomElement> m_behaviorTrees;\r\n\tstatic bool loadBehaviorTrees();\r\n\tstatic void initKeyConvert();\r\n};\r\n"
  },
  {
    "path": "src/base/io.cpp",
    "content": "/*\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"io.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/eventmanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/fluidmanager.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/gnomefactory.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/itemhistory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/neighbormanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/room.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/stockpile.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QDir>\r\n#include <QDirIterator>\r\n#include <QElapsedTimer>\r\n#include <QJsonArray>\r\n#include <QJsonDocument>\r\n#include <QJsonObject>\r\n#include <QJsonValue>\r\n#include <QSaveFile>\r\n#include <QStandardPaths>\r\n\r\n#include <unordered_set>\r\n\r\nIO::IO( Game* game, QObject* parent ) :\r\n\tg( game ),\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nIO::~IO()\r\n{\r\n}\r\n\r\nbool IO::saveCompatible( QString folder )\r\n{\r\n\tint vi = versionInt( folder );\r\n\tif ( vi < 741 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::saveGameExists()\r\n{\r\n\tQString folder = getDataFolder() + \"/save/\";\r\n\r\n\tif ( !QDir( folder ).exists() || QDir( folder ).isEmpty() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::saveConfig()\r\n{\r\n\tQString folder = getDataFolder() + \"/settings/\";\r\n\r\n\tQVariantMap cm   = Global::cfg->object();\r\n\tQJsonDocument jd = QJsonDocument::fromVariant( cm );\r\n\r\n\tIO::saveFile( folder + \"config.json\", jd );\r\n\r\n\treturn true;\r\n}\r\n\r\nQString IO::getDataFolder()\r\n{\r\n#ifdef _WIN32\r\n\treturn QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation ) + \"/My Games/Ingnomia\";\r\n#else\r\n\t// corresponds to ~/.local/share/<APPNAME> on Linux\r\n\treturn QStandardPaths::writableLocation( QStandardPaths::AppDataLocation ) + \"/Ingnomia\";\r\n#endif\r\n}\r\n\r\nQString IO::getTempFolder()\r\n{\r\n\treturn getDataFolder() + \"/tmp/\";\r\n}\r\n\r\nbool IO::createFolders()\r\n{\r\n\tQString folder = getDataFolder() + \"/\";\r\n\tif ( !QDir( folder ).exists() )\r\n\t{\r\n\t\tQDir().mkpath( folder );\r\n\t}\r\n\tQString modFolder = folder + \"mods/\";\r\n\tif ( !QDir( modFolder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( modFolder );\r\n\t}\r\n\tQString saveFolder = folder + \"save/\";\r\n\tif ( !QDir( saveFolder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( saveFolder );\r\n\t}\r\n\tQString ssFolder = folder + \"screenshots/\";\r\n\tif ( !QDir( ssFolder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( ssFolder );\r\n\t}\r\n\tQString settingsFolder = folder + \"settings/\";\r\n\tif ( !QDir( settingsFolder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( settingsFolder );\r\n\t}\r\n\tQString tmpFolder = folder + \"tmp/\";\r\n\tif ( !QDir( tmpFolder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( tmpFolder );\r\n\t}\r\n\r\n\tQString exePath = QCoreApplication::applicationDirPath();\r\n\r\n\tif ( !QFile::exists( folder + \"settings/profs.json\" ) && QFile::exists( exePath + \"/content/JSON/profs.json\" ) )\r\n\t{\r\n\t\tQFile::copy( exePath + \"/content/JSON/profs.json\", folder + \"settings/profs.json\" );\r\n\t}\r\n\tif ( !QFile::exists( folder + \"settings/config.json\" ) && QFile::exists( exePath + \"/content/JSON/config.json\" ) )\r\n\t{\r\n\t\tQFile::copy( exePath + \"/content/JSON/config.json\", folder + \"settings/config.json\" );\r\n\t}\r\n\tif ( !QFile::exists( folder + \"settings/newgame.json\" ) && QFile::exists( exePath + \"/content/JSON/newgame.json\" ) )\r\n\t{\r\n\t\tQFile::copy( exePath + \"/content/JSON/newgame.json\", folder + \"settings/newgame.json\" );\r\n\t}\r\n\t/*\r\n\tif ( !QFile::exists( folder + \"settings/keybindings.json\" ) && QFile::exists( exePath + \"/content/JSON/keybindings.json\" ) )\r\n\t{\r\n\t\tQFile::copy( exePath + \"/content/JSON/keybindings.json\", folder + \"settings/keybindings.json\" );\r\n\t}\r\n\t*/\r\n\r\n\tfolder = getDataFolder() + \"/save/\";\r\n\r\n\treturn QDir( folder ).exists();\r\n}\r\n\r\nbool IO::loadOriginalConfig( QJsonDocument& jd )\r\n{\r\n\tqDebug() << \"load standard config\";\r\n\tQString exePath = QCoreApplication::applicationDirPath();\r\n\treturn IO::loadFile( exePath + \"/content/JSON/config.json\", jd );\r\n}\r\n\r\nQString IO::save( bool autosave )\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\tQString folder = getDataFolder() + \"/save/\";\r\n\r\n\tif ( !QDir( folder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( folder );\r\n\t}\r\n\tQString name = GameState::kingdomName;\r\n\tname         = name.simplified();\r\n\tname.replace( \" \", \"\" );\r\n\tfolder += name;\r\n\tfolder += \"/\";\r\n\r\n\tif ( !QDir( folder ).exists() )\r\n\t{\r\n\t\tQDir().mkdir( folder );\r\n\t}\r\n\tint slot = 0;\r\n\r\n\tif ( autosave )\r\n\t{\r\n\t\tfolder += \"autosave\";\r\n\t}\r\n\telse\r\n\t{\r\n\r\n\t\tQDirIterator directories( folder, QDir::Dirs | QDir::NoDotAndDotDot );\r\n\t\tQStringList dirs;\r\n\t\twhile ( directories.hasNext() )\r\n\t\t{\r\n\t\t\tdirectories.next();\r\n\t\t\tdirs.push_back( directories.filePath() );\r\n\t\t}\r\n\r\n\t\tfor ( auto sdir : dirs )\r\n\t\t{\r\n\t\t\tif ( sdir.endsWith( \"/\" ) )\r\n\t\t\t{\r\n\t\t\t\tsdir.remove( sdir.size() - 1, 1 );\r\n\t\t\t}\r\n\t\t\tQString slotDir = sdir.split( \"/\" ).last();\r\n\r\n\t\t\tbool ok;\r\n\t\t\tint num = slotDir.toInt( &ok );\r\n\t\t\tif ( ok )\r\n\t\t\t{\r\n\t\t\t\tslot = qMax( slot, num );\r\n\t\t\t}\r\n\t\t}\r\n\t\t++slot;\r\n\t\tfolder += QString::number( slot );\r\n\t}\r\n\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << folder;\r\n\tQString oldFolder;\r\n\tif ( QDir( folder ).exists() )\r\n\t{\r\n\t\toldFolder = folder + \".backup\";\r\n\t\tQDir().rename( folder, oldFolder );\r\n\t}\r\n\tQDir().mkdir( folder );\r\n\t\r\n\tfolder += \"/\";\r\n\r\n\tIO::saveWorld( folder );\r\n\tIO::saveFile( folder + \"sprites.json\", IO::jsonArraySprites() );\r\n\tIO::saveFile( folder + \"game.json\", IO::jsonArrayGame() );\r\n\tIO::saveFile( folder + \"config.json\", IO::jsonArrayConfig() );\r\n\r\n\tIO::saveItems( folder );\r\n\r\n\tIO::saveFile( folder + \"wallconstructions.json\", IO::jsonArrayWallConstructions() );\r\n\tIO::saveFile( folder + \"floorconstructions.json\", IO::jsonArrayFloorConstructions() );\r\n\r\n\tIO::saveFile( folder + \"stockpiles.json\", IO::jsonArrayStockpiles() );\r\n\tIO::saveFile( folder + \"jobs.json\", IO::jsonArrayJobs() );\r\n\tIO::saveFile( folder + \"jobsprites.json\", IO::jsonArrayJobSprites() );\r\n\r\n\tIO::saveFile( folder + \"gnomes.json\", IO::jsonArrayGnomes() );\r\n\r\n\tIO::saveMonsters( folder );\r\n\r\n\tIO::savePlants( folder );\r\n\tIO::saveAnimals( folder );\r\n\r\n\tIO::saveFile( folder + \"farms.json\", IO::jsonArrayFarms() );\r\n\tIO::saveFile( folder + \"workshops.json\", IO::jsonArrayWorkshops() );\r\n\r\n\tIO::saveFile( folder + \"rooms.json\", IO::jsonArrayRooms() );\r\n\tIO::saveFile( folder + \"doors.json\", IO::jsonArrayDoors() );\r\n\r\n\tIO::saveFile( folder + \"itemhistory.json\", IO::jsonArrayItemHistory() );\r\n\tIO::saveFile( folder + \"events.json\", IO::jsonArrayEvents() );\r\n\r\n\tIO::saveFile( folder + \"mechanisms.json\", IO::jsonArrayMechanisms() );\r\n\tIO::saveFile( folder + \"pipes.json\", IO::jsonArrayPipes() );\r\n\r\n\tqDebug() << \"saving game took: \" + QString::number( timer.elapsed() ) + \" ms\";\r\n\r\n\tif (!oldFolder.isEmpty())\r\n\t{\r\n\t\tQDir( oldFolder ).removeRecursively();\r\n\t\tqDebug() << \"Savegame backup removed\";\r\n\t}\r\n\r\n\treturn folder;\r\n}\r\n\r\nbool IO::load( QString folder )\r\n{\r\n\tif ( !folder.endsWith( \"/\" ) )\r\n\t{\r\n\t\tfolder += \"/\";\r\n\t}\r\n\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\tIO::version = versionInt( folder );\r\n\r\n\tQJsonDocument jd;\r\n\r\n\tloadFile( folder + \"game.json\", jd );\r\n\tIO::loadGame( jd );\r\n\r\n\tGlobal::util->initAllowedInContainer();\r\n\r\n\tloadFile( folder + \"sprites.json\", jd );\r\n\tIO::loadSprites( jd );\r\n\temit signalStatus( \"Start loading world..\" );\r\n\tif ( !IO::loadWorld( folder ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tg->w()->afterLoad();\r\n\temit signalStatus( \"Loading world done\" );\r\n\tIO::loadItems( folder );\r\n\temit signalStatus( \"Loading items done\" );\r\n\tloadFile( folder + \"floorconstructions.json\", jd );\r\n\tIO::loadFloorConstructions( jd );\r\n\tloadFile( folder + \"wallconstructions.json\", jd );\r\n\tIO::loadWallConstructions( jd );\r\n\temit signalStatus( \"Loading constructions done\" );\r\n\tloadFile( folder + \"jobs.json\", jd );\r\n\tIO::loadJobs( jd );\r\n\tloadFile( folder + \"jobsprites.json\", jd );\r\n\tIO::loadJobSprites( jd );\r\n\temit signalStatus( \"Loading jobs done\" );\r\n\tloadFile( folder + \"workshops.json\", jd );\r\n\tIO::loadWorkshops( jd );\r\n\tloadFile( folder + \"farms.json\", jd );\r\n\tIO::loadFarms( jd );\r\n\tloadFile( folder + \"stockpiles.json\", jd );\r\n\tIO::loadStockpiles( jd );\r\n\tloadFile( folder + \"mechanisms.json\", jd );\r\n\tIO::loadMechanisms( jd );\r\n\tloadFile( folder + \"pipes.json\", jd );\r\n\tIO::loadPipes( jd );\r\n\t// anything that has local jobs needs to be loaded before this\r\n\tloadFile( folder + \"gnomes.json\", jd );\r\n\tIO::loadGnomes( jd );\r\n\tloadFile( folder + \"monsters.json\", jd );\r\n\tIO::loadMonsters( folder );\r\n\tIO::loadPlants( folder );\r\n\tIO::loadAnimals( folder );\r\n\temit signalStatus( \"Loading gnomes, plants and animals done\" );\r\n\tloadFile( folder + \"rooms.json\", jd );\r\n\tIO::loadRooms( jd );\r\n\tloadFile( folder + \"doors.json\", jd );\r\n\tIO::loadDoors( jd );\r\n\tloadFile( folder + \"itemhistory.json\", jd );\r\n\tIO::loadItemHistory( jd );\r\n\tloadFile( folder + \"events.json\", jd );\r\n\tIO::loadEvents( jd );\r\n\r\n\tloadFile( folder + \"config.json\", jd );\r\n\tIO::loadConfig( jd );\r\n\r\n\tsanitize();\r\n\r\n\tqDebug() << \"loading game took: \" + QString::number( timer.elapsed() ) + \" ms\";\r\n\treturn true;\r\n}\r\n\r\nvoid IO::sanitize()\r\n{\r\n\t// Migration for 0.7.5 games where gnomes had stored their own ID in job field of items\r\n\t{\r\n\t\tstd::unordered_set<unsigned int> legacyJobs;\r\n\r\n\t\tstd::unordered_map<unsigned int, unsigned int> carriedItems;\r\n\t\tstd::unordered_map<unsigned int, unsigned int> constructedItems;\r\n\t\tfor ( const auto& gnome : g->gm()->gnomes() )\r\n\t\t{\r\n\t\t\t{\r\n\t\t\t\tconst auto& c = gnome->inventoryItems();\r\n\t\t\t\tfor ( const auto& itemID : c )\r\n\t\t\t\t{\r\n\t\t\t\t\tassert( carriedItems.count( itemID ) == 0 );\r\n\t\t\t\t\tcarriedItems[itemID] = gnome->id();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t{\r\n\t\t\t\tconst auto& c = gnome->carriedItems();\r\n\t\t\t\tfor ( const auto& itemID : c )\r\n\t\t\t\t{\r\n\t\t\t\t\tassert( carriedItems.count( itemID ) == 0 );\r\n\t\t\t\t\tcarriedItems[itemID] = gnome->id();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfor ( const auto& claim : gnome->claimedItems() )\r\n\t\t\t{\r\n\t\t\t\t// Special exemption in case this is legacy type reservation\r\n\t\t\t\tlegacyJobs.emplace( gnome->id() );\r\n\t\t\t}\r\n\r\n\t\t\tfor ( const auto& itemID : gnome->equipment().wornItems() )\r\n\t\t\t{\r\n\t\t\t\tassert( carriedItems.count( itemID ) == 0 );\r\n\t\t\t\tcarriedItems[itemID] = gnome->id();\r\n\t\t\t}\r\n\t\t}\r\n\t\t{\r\n\t\t\tconst auto& constructions = g->w()->wallConstructions();\r\n\t\t\tfor ( auto it = constructions.cbegin(); it != constructions.cend(); ++it )\r\n\t\t\t{\r\n\t\t\t\tconst auto& construction = it.value();\r\n\t\t\t\tif ( construction.contains( \"Item\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto itemID = construction[\"Item\"].toInt();\r\n\t\t\t\t\tassert( constructedItems.count( itemID ) == 0 );\r\n\t\t\t\t\tconstructedItems[itemID] = 0;\r\n\t\t\t\t}\r\n\t\t\t\t// Items can be either item type IDs or actual item IDs\r\n\t\t\t\tif ( construction.contains( \"FromParts\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto vItem : construction.value( \"Items\" ).toList() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto itemID = vItem.toInt();\r\n\t\t\t\t\t\tassert( constructedItems.count( itemID ) == 0 );\r\n\t\t\t\t\t\tconstructedItems[itemID] = 0;\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\t{\r\n\t\t\tconst auto& constructions = g->w()->floorConstructions();\r\n\t\t\tfor ( auto it = constructions.cbegin(); it != constructions.cend(); ++it )\r\n\t\t\t{\r\n\t\t\t\tconst auto& construction = it.value();\r\n\t\t\t\tif ( construction.contains( \"Item\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto itemID = construction[\"Item\"].toInt();\r\n\t\t\t\t\tassert( constructedItems.count( itemID ) == 0 );\r\n\t\t\t\t\tconstructedItems[itemID] = 0;\r\n\t\t\t\t}\r\n\t\t\t\t// Items can be either item type IDs or actual item IDs\r\n\t\t\t\tif ( construction.contains( \"FromParts\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto vItem : construction.value( \"Items\" ).toList() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto itemID = vItem.toInt();\r\n\t\t\t\t\t\tassert( constructedItems.count( itemID ) == 0 );\r\n\t\t\t\t\t\tconstructedItems[itemID] = 0;\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\tfor ( const auto& workshop : g->wsm()->workshops() )\r\n\t\t{\r\n\t\t\tfor ( const auto& item : workshop->sourceItems() )\r\n\t\t\t{\r\n\t\t\t\tconstructedItems[item.toInt()] = workshop->id();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor ( auto& item : g->inv()->allItems() )\r\n\t\t{\r\n\t\t\tconst auto job = item.isInJob();\r\n\t\t\tif ( job && !legacyJobs.count( job ) && !g->jm()->getJob( job ) )\r\n\t\t\t{\r\n\t\t\t\titem.setInJob( 0 );\r\n\t\t\t\tqWarning() << \"item \" + QString::number( item.id() ) + \" \" + item.itemSID() + \" had illegal job\";\r\n\t\t\t}\r\n\t\t\tconst bool carried    = 0 != carriedItems.count( item.id() );\r\n\t\t\tconst bool construced = 0 != constructedItems.count( item.id() );\r\n\r\n\t\t\tif ( carried && construced )\r\n\t\t\t{\r\n\t\t\t\tqWarning() << \"item \" + QString::number( item.id() ) + \" \" + item.itemSID() + \" is both carried around and installed somewhere simultaniously\";\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\t// Items which should be in world\r\n\t\t\tif ( item.isHeldBy() != 0 && !construced && !carried )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->putDownItem( item.id(), item.getPos() );\r\n\t\t\t\titem.setIsConstructed( false );\r\n\t\t\t\tqWarning() << \"item \" + QString::number( item.id() ) + \" \" + item.itemSID() + \" found lost in space\";\r\n\t\t\t}\r\n\t\t\tif ( carried )\r\n\t\t\t{\r\n\t\t\t\tauto realOwner = carriedItems[item.id()];\r\n\t\t\t\tif ( item.isHeldBy() != realOwner )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->pickUpItem( item.id(), realOwner );\r\n\t\t\t\t}\r\n\t\t\t\tif ( item.isConstructed() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setConstructed( item.id(), false );\r\n\t\t\t\t\tqWarning() << \"item \" + QString::number( item.id() ) + \" \" + item.itemSID() + \" found constructed on a gnome\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// Items in world\r\n\t\t\tif ( !carried && !construced )\r\n\t\t\t{\r\n\t\t\t\tif ( item.isConstructed() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setConstructed( item.id(), false );\r\n\t\t\t\t\titem.setIsConstructed( false );\r\n\t\t\t\t\tg->inv()->putDownItem( item.id(), item.getPos() );\r\n\t\t\t\t\tqWarning() << \"item \" + QString::number( item.id() ) + \" \" + item.itemSID() + \" found glued to the floor\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t// Items in construction\r\n\t\t\tif ( construced )\r\n\t\t\t{\r\n\t\t\t\tauto realOwner = constructedItems[item.id()];\r\n\t\t\t\tif ( item.isHeldBy() != realOwner )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( realOwner != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->pickUpItem( item.id(), realOwner );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->putDownItem( item.id(), item.getPos() );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif ( !item.isConstructed() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setConstructed( item.id(), true );\r\n\t\t\t\t\tqWarning() << \"item \" + QString::number( item.id() ) + \" \" + item.itemSID() + \" found broken loose\";\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( auto& ws : g->wsm()->workshops() )\r\n\t\t{\r\n\t\t\tfor ( auto& vitem : ws->sourceItems() )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->pickUpItem( vitem.toUInt(), ws->id() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t// Clean out orphaned watch list items\r\n\t{\r\n\t\tconst auto categories = g->inv()->categories();\r\n\t\tfor ( auto it = GameState::watchedItemList.begin(); it != GameState::watchedItemList.end(); )\r\n\t\t{\r\n\t\t\tbool valid = true;\r\n\r\n\t\t\tconst auto groups    = g->inv()->groups( it->category );\r\n\t\t\tconst auto items     = g->inv()->items( it->category, it->group );\r\n\t\t\tconst auto materials = g->inv()->materials( it->category, it->group, it->item );\r\n\r\n\t\t\tif (\r\n\t\t\t\t!categories.contains( it->category ) ||\r\n\t\t\t\t( !it->group.isEmpty() && !groups.contains( it->group ) ) ||\r\n\t\t\t\t( !it->item.isEmpty() && !items.contains( it->item ) ) ||\r\n\t\t\t\t( !it->material.isEmpty() && !materials.contains( it->material ) )\r\n\t\t\t)\r\n\t\t\t{\r\n\t\t\t\tit = GameState::watchedItemList.erase( it );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++it;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQString IO::versionString( QString folder )\r\n{\r\n\tQJsonDocument jd;\r\n\tIO::loadFile( folder + \"/game.json\", jd );\r\n\r\n\tif ( jd.isArray() )\r\n\t{\r\n\t\tQJsonArray ja = jd.array();\r\n\t\tauto vl       = ja.toVariantList();\r\n\t\tif ( vl.size() > 0 )\r\n\t\t{\r\n\t\t\tQVariantMap vm = vl.first().toMap();\r\n\r\n\t\t\tif ( vm.contains( \"Version\" ) )\r\n\t\t\t{\r\n\t\t\t\treturn vm.value( \"Version\" ).toString();\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn vm.value( \"version\" ).toString();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn ( \"0.0.0.0\" );\r\n}\r\n\r\nint IO::versionInt( QString folder )\r\n{\r\n\tQString version = versionString( folder );\r\n\tQStringList vl  = version.split( \".\" );\r\n\tif ( vl.size() == 4 )\r\n\t{\r\n\t\tint vi = vl[0].toInt() * 1000 + vl[1].toInt() * 100 + vl[2].toInt() * 10 + vl[3].toInt();\r\n\t\treturn vi;\r\n\t\tif ( vi < 577 )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQJsonArray IO::jsonArrayConfig()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayConfig\";\r\n\tQJsonArray ja;\r\n\tja.append( QJsonValue::fromVariant( Global::cfg->object() ) );\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadConfig( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tauto map = entry.toMap();\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayGame()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayGame\";\r\n\tGameState::version = Global::cfg->get( \"CurrentVersion\" ).toString();\r\n\r\n\tGameState::initialSave = true;\r\n\r\n\tg->inv()->saveFilter();\r\n\r\n\tGameState::neighbors = g->nm()->serialize();\r\n\tGameState::military  = g->mil()->serialize();\r\n\r\n\tg->mil()->save(); // TODO why this? maybe move it into serialize\r\n\r\n\tQJsonArray ja;\r\n\tQVariantMap out;\r\n\tGameState::serialize( out );\r\n\tja.append( QJsonValue::fromVariant( out ) );\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadGame( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tauto doc      = ja.toVariantList();\r\n\tif ( doc.size() )\r\n\t{\r\n\t\tauto map = doc.first().toMap();\r\n\t\tGameState::load( map );\r\n\t}\r\n\r\n\tfor ( const auto& vMat : GameState::addedMaterials )\r\n\t{\r\n\t\tDB::addRow( \"Materials\", vMat.toMap() );\r\n\t}\r\n\r\n\tfor ( const auto& key : GameState::addedTranslations.keys() )\r\n\t{\r\n\t\tStrings::getInstance().insertString( key, GameState::addedTranslations[key].toString() );\r\n\t}\r\n\r\n\tg->nm()->deserialize( GameState::neighbors );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IO::saveWorld( QString folder )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"saveWorld\";\r\n\tQFile worldFile( folder + \"world.dat\" );\r\n\tif ( worldFile.open( QIODevice::WriteOnly ) )\r\n\t{\r\n\t\tQDataStream out( &worldFile );\r\n\t\tstd::vector<Tile>& world = g->w()->world();\r\n\r\n\t\tfor ( const auto& tile : world )\r\n\t\t{\r\n\t\t\tout << (quint64)tile.flags;\r\n\t\t\tout << (quint16)tile.wallType;\r\n\t\t\tout << (quint16)tile.wallMaterial;\r\n\t\t\tout << (quint16)tile.floorType;\r\n\t\t\tout << (quint16)tile.floorMaterial;\r\n\t\t\tout << (quint8)tile.wallRotation;\r\n\t\t\tout << (quint8)tile.floorRotation;\r\n\t\t\tout << (quint8)tile.fluidLevel;\r\n\t\t\tout << (quint8)tile.pressure;\r\n\t\t\tout << (quint8)tile.flow;\r\n\t\t\tout << (quint8)tile.vegetationLevel;\r\n\t\t\tout << (quint16)tile.embeddedMaterial;\r\n\r\n\t\t\tout << (quint32)tile.wallSpriteUID;\r\n\t\t\tout << (quint32)tile.floorSpriteUID;\r\n\t\t\tout << (quint32)tile.itemSpriteUID;\r\n#ifdef SAVEREGIONINFO\r\n\t\t\tout << (quint32)tile.region;\r\n#endif\r\n\t\t}\r\n\t}\r\n\tworldFile.close();\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadWorld( QString folder )\r\n{\r\n\tQFile worldFile( folder + \"world.dat\" );\r\n\tif ( worldFile.open( QIODevice::ReadOnly ) )\r\n\t{\r\n\t\tQDataStream in( &worldFile );\r\n\r\n\t\tloadWorld( in );\r\n\r\n\t\tworldFile.close();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid IO::loadWorld( QDataStream& in )\r\n{\r\n\tunsigned short dimX = Global::dimX;\r\n\tunsigned short dimY = Global::dimY;\r\n\tunsigned short dimZ = Global::dimZ;\r\n\r\n\tg->setWorld( dimX, dimY, dimZ );\r\n\tstd::vector<Tile>& world = g->w()->world();\r\n\tworld.clear();\r\n\tworld.reserve( dimX * dimY * dimZ );\r\n\r\n\twhile ( !in.atEnd() )\r\n\t{\r\n\t\tquint16 wallType;\r\n\t\tquint16 floorType;\r\n\t\tquint64 tileFlags;\r\n\t\tquint8 flow;\r\n\r\n\t\tTile tile;\r\n\t\tin >> tileFlags;\r\n\t\tin >> wallType;\r\n\t\tin >> tile.wallMaterial;\r\n\t\tin >> floorType;\r\n\t\tin >> tile.floorMaterial;\r\n\t\tin >> tile.wallRotation;\r\n\t\tin >> tile.floorRotation;\r\n\t\tin >> tile.fluidLevel;\r\n\t\tin >> tile.pressure;\r\n\t\tin >> flow;\r\n\t\tin >> tile.vegetationLevel;\r\n\t\tin >> tile.embeddedMaterial;\r\n\t\tin >> tile.wallSpriteUID;\r\n\t\tin >> tile.floorSpriteUID;\r\n\t\tin >> tile.itemSpriteUID;\r\n\t\ttile.flags     = (TileFlag)tileFlags;\r\n\t\ttile.wallType  = (WallType)wallType;\r\n\t\ttile.floorType = (FloorType)floorType;\r\n\t\ttile.flow      = (WaterFlow)flow;\r\n\r\n\t\tworld.push_back( tile );\r\n\t}\r\n\tworld.shrink_to_fit();\r\n}\r\n\r\nQJsonArray IO::jsonArrayWallConstructions()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayWallConstructions\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& constr : g->w()->wallConstructions() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( constr );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nQJsonArray IO::jsonArrayFloorConstructions()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayFloorConstructions\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& constr : g->w()->floorConstructions() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( constr );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadFloorConstructions( QJsonDocument& jd )\r\n{\r\n\tg->w()->loadFloorConstructions( jd.array().toVariantList() );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadWallConstructions( QJsonDocument& jd )\r\n{\r\n\tg->w()->loadWallConstructions( jd.array().toVariantList() );\r\n\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArraySprites()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArraySprites\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& sc : g->sf()->spriteCreations() )\r\n\t{\r\n\t\tQVariantMap vm;\r\n\t\tvm.insert( \"ItemSID\", sc.itemSID );\r\n\t\tvm.insert( \"MaterialSIDs\", sc.materialSIDs.join( '_' ) );\r\n\t\tvm.insert( \"Random\", Global::util->mapJoin( sc.random ) );\r\n\t\tvm.insert( \"UID\", sc.uID );\r\n\t\tif ( sc.creatureID )\r\n\t\t{\r\n\t\t\tvm.insert( \"CreatureID\", sc.creatureID );\r\n\t\t}\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( vm );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadSprites( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tQList<SpriteCreation> scl;\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tQVariantMap em = entry.toMap();\r\n\t\tSpriteCreation sc;\r\n\t\tsc.itemSID      = em.value( \"ItemSID\" ).toString();\r\n\t\tsc.materialSIDs = em.value( \"MaterialSIDs\" ).toString().split( \"_\" );\r\n\t\tsc.random       = Global::util->mapSplit( em.value( \"Random\" ).toString() );\r\n\t\tsc.uID          = em.value( \"UID\" ).toUInt();\r\n\t\tsc.creatureID   = em.value( \"CreatureID\" ).toUInt();\r\n\t\tscl.push_back( sc );\r\n\t}\r\n\tg->sf()->createSprites( scl );\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayGnomes()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayGnomes\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& gnome : g->gm()->gnomes() )\r\n\t{\r\n\t\tQVariantMap out;\r\n\t\tgnome->serialize( out );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( out );\r\n\t\tja.append( jv );\r\n\t}\r\n\tfor ( const auto& gnome : g->gm()->specialGnomes() )\r\n\t{\r\n\t\tQVariantMap out;\r\n\t\tgnome->serialize( out );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( out );\r\n\t\tja.append( jv );\r\n\t}\r\n\tfor ( const auto& automaton : g->gm()->automatons() )\r\n\t{\r\n\t\tQVariantMap out;\r\n\t\tautomaton->serialize( out );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( out );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nQJsonArray IO::jsonArrayMonsters( int startIndex, int amount )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayMonsters\";\r\n\tQJsonArray ja;\r\n\r\n\tint i         = startIndex;\r\n\tauto monsters = g->cm()->monsters();\r\n\r\n\twhile ( i < monsters.size() && amount > 0 )\r\n\t{\r\n\t\tauto monster = monsters[i];\r\n\r\n\t\tQVariantMap out;\r\n\t\tmonster->serialize( out );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( out );\r\n\t\tja.append( jv );\r\n\r\n\t\t++i;\r\n\t\t--monster;\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::saveMonsters( QString folder )\r\n{\r\n\tint i          = 1;\r\n\tint startIndex = 0;\r\n\twhile ( true )\r\n\t{\r\n\t\tauto ja = jsonArrayMonsters( startIndex, 10000 );\r\n\t\tif ( ja.size() > 0 )\r\n\t\t{\r\n\t\t\tIO::saveFile( folder + \"monsters\" + QString::number( i ) + \".json\", ja );\r\n\t\t\t++i;\r\n\t\t\tstartIndex += 10000;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadGnomes( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tqDebug() << \"load \" << ja.toVariantList().size() << \"gnomes\";\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tauto em = entry.toMap();\r\n\t\tswitch ( (CreatureType)em.value( \"Type\" ).toInt() )\r\n\t\t{\r\n\t\t\tcase CreatureType::GNOME:\r\n\t\t\t\tg->gm()->addGnome( em );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureType::GNOME_TRADER:\r\n\t\t\t\tg->gm()->addTrader( em );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureType::AUTOMATON:\r\n\t\t\t\tg->gm()->addAutomaton( em );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadMonsters( QString folder )\r\n{\r\n\tQJsonDocument jd;\r\n\tif ( QFileInfo::exists( folder + \"monsters.json\" ) )\r\n\t{\r\n\t\tloadFile( folder + \"monsters.json\", jd );\r\n\t\tQJsonArray ja = jd.array();\r\n\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t{\r\n\t\t\tg->cm()->addCreature( CreatureType::MONSTER, entry.toMap() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint i = 1;\r\n\t\twhile ( QFileInfo::exists( folder + \"monsters\" + QString::number( i ) + \".json\" ) )\r\n\t\t{\r\n\t\t\tloadFile( folder + \"monsters\" + QString::number( i ) + \".json\", jd );\r\n\t\t\tQJsonArray ja = jd.array();\r\n\t\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t\t{\r\n\t\t\t\tg->cm()->addCreature( CreatureType::MONSTER, entry.toMap() );\r\n\t\t\t}\r\n\t\t\t++i;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayPlants( int startIndex, int amount )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayAnimals\";\r\n\r\n\tQJsonArray ja;\r\n\tauto plants = g->w()->plants();\r\n\tauto keys   = plants.keys();\r\n\tint i       = startIndex;\r\n\r\n\twhile ( i < keys.size() && amount > 0 )\r\n\t{\r\n\t\tconst auto& plant = plants[keys[i]];\r\n\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( plant.serialize() );\r\n\t\tja.append( jv );\r\n\r\n\t\t++i;\r\n\t\t--amount;\r\n\t}\r\n\treturn ja;\r\n}\r\n\r\nbool IO::savePlants( QString folder )\r\n{\r\n\tQByteArray out;\r\n\r\n\tint i          = 1;\r\n\tint startIndex = 0;\r\n\twhile ( true )\r\n\t{\r\n\t\tauto ja = jsonArrayPlants( startIndex, 10000 );\r\n\t\tif ( ja.size() > 0 )\r\n\t\t{\r\n\t\t\tIO::saveFile( folder + \"plants\" + QString::number( i ) + \".json\", ja );\r\n\t\t\t++i;\r\n\t\t\tstartIndex += 10000;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadPlants( QString folder )\r\n{\r\n\tQJsonDocument jd;\r\n\tif ( QFileInfo::exists( folder + \"plants.json\" ) )\r\n\t{\r\n\t\tloadFile( folder + \"plants.json\", jd );\r\n\t\tQJsonArray ja = jd.array();\r\n\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t{\r\n\t\t\tPlant plant( entry.toMap(), g );\r\n\t\t\tg->w()->addPlant( plant );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint i = 1;\r\n\r\n\t\twhile ( QFileInfo::exists( folder + \"plants\" + QString::number( i ) + \".json\" ) )\r\n\t\t{\r\n\t\t\tloadFile( folder + \"plants\" + QString::number( i ) + \".json\", jd );\r\n\t\t\tQJsonArray ja = jd.array();\r\n\r\n\t\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t\t{\r\n\t\t\t\tPlant plant( entry.toMap(), g );\r\n\t\t\t\tg->w()->addPlant( plant );\r\n\t\t\t}\r\n\t\t\t++i;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayItems( int startIndex, int amount )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayAnimals\";\r\n\r\n\tQJsonArray ja;\r\n\tauto& items = g->inv()->allItems();\r\n\tauto keys   = items.keys();\r\n\r\n\tint i = startIndex;\r\n\r\n\twhile ( i < keys.size() && amount > 0 )\r\n\t{\r\n\t\tauto itemID   = keys[i];\r\n\t\tauto& item    = items[itemID];\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( item.serialize() );\r\n\t\tja.append( jv );\r\n\r\n\t\t++i;\r\n\t\t--amount;\r\n\t}\r\n\treturn ja;\r\n}\r\n\r\nbool IO::saveItems( QString folder )\r\n{\r\n\tg->inv()->sanityCheck();\r\n\r\n\tQByteArray out;\r\n\r\n\tauto& items = g->inv()->allItems();\r\n\r\n\tint i          = 1;\r\n\tint startIndex = 0;\r\n\twhile ( true )\r\n\t{\r\n\t\tauto ja = jsonArrayItems( startIndex, 50000 );\r\n\t\tif ( ja.size() > 0 )\r\n\t\t{\r\n\t\t\tIO::saveFile( folder + \"items\" + QString::number( i ) + \".json\", ja );\r\n\t\t\t++i;\r\n\t\t\tstartIndex += 50000;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadItems( QString folder )\r\n{\r\n\tg->inv()->loadFilter();\r\n\r\n\tQJsonDocument jd;\r\n\tif ( QFileInfo::exists( folder + \"items.json\" ) )\r\n\t{\r\n\t\tloadFile( folder + \"items.json\", jd );\r\n\t\tQJsonArray ja = jd.array();\r\n\t\tint count     = 0;\r\n\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t{\r\n\t\t\tg->inv()->createItem( entry.toMap() );\r\n\t\t\t++count;\r\n\t\t}\r\n\t\tqDebug() << \"loaded\" << count << \"items\";\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint i     = 1;\r\n\t\tint count = 0;\r\n\t\twhile ( QFileInfo::exists( folder + \"items\" + QString::number( i ) + \".json\" ) )\r\n\t\t{\r\n\t\t\tloadFile( folder + \"items\" + QString::number( i ) + \".json\", jd );\r\n\t\t\tQJsonArray ja = jd.array();\r\n\r\n\t\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->createItem( entry.toMap() );\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t\t++i;\r\n\t\t}\r\n\t\tqDebug() << \"loaded\" << count << \"items\";\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadItemHistory( QJsonDocument& jd )\r\n{\r\n\tg->inv()->itemHistory()->deserialize( jd.toVariant().toMap() );\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayJobs()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayJobs\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& job : g->jm()->allJobs() )\r\n\t{\r\n\t\tif ( !job->type().isEmpty() )\r\n\t\t{\r\n\t\t\tQJsonValue jv = QJsonValue::fromVariant( job->serialize() );\r\n\t\t\tja.append( jv );\r\n\t\t}\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nQJsonArray IO::jsonArrayJobSprites()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayJobSprites\";\r\n\tQJsonArray ja;\r\n\tauto jobSprites = g->w()->jobSprites();\r\n\r\n\tfor ( const auto& key : jobSprites.keys() )\r\n\t{\r\n\t\tauto entry = jobSprites[key];\r\n\t\tentry.insert( \"PosID\", key );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( entry );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadJobs( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->jm()->addLoadedJob( entry );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadJobSprites( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tauto em          = entry.toMap();\r\n\t\tunsigned int key = em.value( \"JobID\" ).toUInt();\r\n\t\tem.remove( \"JobID\" );\r\n\t\tg->w()->insertLoadedJobSprite( key, em );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayFarms()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayFarms\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& farm : g->fm()->allFarms() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( farm->serialize() );\r\n\t\tja.append( jv );\r\n\t}\r\n\tfor ( const auto& grove : g->fm()->allGroves() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( grove->serialize() );\r\n\t\tja.append( jv );\r\n\t}\r\n\tfor ( const auto& pasture : g->fm()->allPastures() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( pasture->serialize() );\r\n\t\tja.append( jv );\r\n\t}\r\n\tfor ( const auto& beehive : g->fm()->allBeeHives() )\r\n\t{\r\n\t\tQVariantMap vm;\r\n\t\tbeehive->serialize( vm );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( vm );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nQJsonArray IO::jsonArrayRooms()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayRooms\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& room : g->rm()->allRooms() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( room->serialize() );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nQJsonArray IO::jsonArrayDoors()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayDoors\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& door : g->rm()->allDoors() )\r\n\t{\r\n\t\tQVariantMap out;\r\n\r\n\t\tout.insert( \"Pos\", door.pos.toString() );\r\n\t\tout.insert( \"Name\", door.name );\r\n\t\tout.insert( \"ItemUID\", door.itemUID );\r\n\t\tout.insert( \"MaterialUID\", door.materialUID );\r\n\t\tout.insert( \"BlockGnomes\", door.blockGnomes );\r\n\t\tout.insert( \"BlockAnimals\", door.blockAnimals );\r\n\t\tout.insert( \"BlockMonsters\", door.blockMonsters );\r\n\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( out );\r\n\t\tja.append( jv );\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadFarms( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->fm()->load( entry.toMap() );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadRooms( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->rm()->load( entry.toMap() );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadDoors( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->rm()->loadDoor( entry.toMap() );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayStockpiles()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayStockpiles\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& stockpileID : g->spm()->allStockpilesOrdered() )\r\n\t{\r\n\t\tauto stockpile = g->spm()->getStockpile( stockpileID );\r\n\t\tif ( stockpile )\r\n\t\t{\r\n\t\t\tQJsonValue jv = QJsonValue::fromVariant( stockpile->serialize() );\r\n\t\t\tja.append( jv );\r\n\t\t}\r\n\t}\r\n\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadStockpiles( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->spm()->load( entry.toMap() );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayWorkshops()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayWorkshops\";\r\n\tQJsonArray ja;\r\n\tfor ( const auto& w : g->wsm()->workshops() )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( w->serialize() );\r\n\t\tja.append( jv );\r\n\t}\r\n\treturn ja;\r\n}\r\n\r\nbool IO::loadWorkshops( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->wsm()->addWorkshop( entry.toMap() );\r\n\t\tfor ( const auto& s : entry.toMap().value( \"Sprites\" ).toList() )\r\n\t\t{\r\n\t\t\tg->w()->addLoadedSprites( s.toMap() );\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonArray IO::jsonArrayAnimals( int startIndex, int amount )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayAnimals\";\r\n\r\n\tQJsonArray ja;\r\n\tauto animals = g->cm()->animals();\r\n\r\n\tint i = startIndex;\r\n\r\n\twhile ( i < animals.size() && amount > 0 )\r\n\t{\r\n\t\tauto a = animals[i];\r\n\t\tQVariantMap values;\r\n\t\ta->serialize( values );\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( values );\r\n\t\tja.append( jv );\r\n\r\n\t\t++i;\r\n\t\t--amount;\r\n\t}\r\n\treturn ja;\r\n}\r\n\r\nbool IO::saveAnimals( QString folder )\r\n{\r\n\tint i          = 1;\r\n\tint startIndex = 0;\r\n\twhile ( true )\r\n\t{\r\n\t\tauto ja = jsonArrayAnimals( startIndex, 10000 );\r\n\t\tif ( ja.size() > 0 )\r\n\t\t{\r\n\t\t\tIO::saveFile( folder + \"animals\" + QString::number( i ) + \".json\", ja );\r\n\t\t\t++i;\r\n\t\t\tstartIndex += 10000;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadAnimals( QString folder )\r\n{\r\n\tQJsonDocument jd;\r\n\tif ( QFileInfo::exists( folder + \"animals.json\" ) )\r\n\t{\r\n\t\tloadFile( folder + \"animals.json\", jd );\r\n\t\tQJsonArray ja = jd.array();\r\n\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t{\r\n\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, entry.toMap() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint i = 1;\r\n\t\twhile ( QFileInfo::exists( folder + \"animals\" + QString::number( i ) + \".json\" ) )\r\n\t\t{\r\n\t\t\tloadFile( folder + \"animals\" + QString::number( i ) + \".json\", jd );\r\n\t\t\tQJsonArray ja = jd.array();\r\n\t\t\tfor ( const auto& entry : ja.toVariantList() )\r\n\t\t\t{\r\n\t\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, entry.toMap() );\r\n\t\t\t}\r\n\t\t\t++i;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonDocument IO::jsonArrayItemHistory()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayItemHistory\";\r\n\tQVariantMap out;\r\n\tg->inv()->itemHistory()->serialize( out );\r\n\r\n\tQJsonDocument jd = QJsonDocument::fromVariant( out );\r\n\r\n\treturn jd;\r\n}\r\n\r\nQJsonDocument IO::jsonArrayEvents()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayEvents\";\r\n\tQVariantMap out = g->em()->serialize();\r\n\tQVariantList ol;\r\n\tol.append( out );\r\n\tQJsonDocument jd = QJsonDocument::fromVariant( ol );\r\n\r\n\treturn jd;\r\n}\r\n\r\nbool IO::loadEvents( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tfor ( const auto& entry : ja.toVariantList() )\r\n\t{\r\n\t\tg->em()->deserialize( entry.toMap() );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQJsonDocument IO::jsonArrayMechanisms()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayMechanisms\";\r\n\tQVariantList ol;\r\n\r\n\tfor ( const auto& md : g->mcm()->mechanisms() )\r\n\t{\r\n\t\tauto vmd = md.serialize();\r\n\t\tol.append( vmd );\r\n\t}\r\n\r\n\tQJsonDocument jd = QJsonDocument::fromVariant( ol );\r\n\r\n\treturn jd;\r\n}\r\n\r\nbool IO::loadMechanisms( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tg->mcm()->loadMechanisms( ja.toVariantList() );\r\n\treturn true;\r\n}\r\n\r\nQJsonDocument IO::jsonArrayPipes()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"jsonArrayPipes\";\r\n\tQVariantList ol;\r\n\r\n\tfor ( const auto& fp : g->flm()->pipes() )\r\n\t{\r\n\t\tauto vfp = fp.serialize();\r\n\t\t/*\r\n\t\tif( md.jobID )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> job = g->mcm()->getJob( md.jobID );\r\n\t\t\tif( job )\r\n\t\t\t{\r\n\t\t\t\tvmd.insert( \"Job\", job->serialize() );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tvmd.insert( \"JobID\", 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\t*/\r\n\t\tol.append( vfp );\r\n\t}\r\n\r\n\tQJsonDocument jd = QJsonDocument::fromVariant( ol );\r\n\r\n\treturn jd;\r\n}\r\n\r\nbool IO::loadPipes( QJsonDocument& jd )\r\n{\r\n\tQJsonArray ja = jd.array();\r\n\tg->flm()->loadPipes( ja.toVariantList() );\r\n\treturn true;\r\n}\r\n\r\nbool IO::saveFile( QString url, const QJsonObject& jo )\r\n{\r\n\tQJsonDocument saveDoc( jo );\r\n\treturn saveFile( url, saveDoc );\r\n}\r\n\r\nbool IO::saveFile( QString url, const QJsonArray& ja )\r\n{\r\n\tQJsonDocument saveDoc( ja );\r\n\treturn saveFile( url, saveDoc );\r\n}\r\n\r\nbool IO::saveFile( QString url, const QJsonDocument& jd )\r\n{\r\n\tQFile file( url );\r\n\r\n\tif ( !file.open( QIODevice::WriteOnly ) )\r\n\t{\r\n\t\tqWarning( \"Couldn't open save file.\" );\r\n\t\treturn false;\r\n\t}\r\n\r\n\tfile.write( jd.toJson() );\r\n\tfile.close();\r\n\treturn true;\r\n}\r\n\r\nbool IO::loadFile( QString url, QJsonDocument& ja )\r\n{\r\n\tQFile file( url );\r\n\tfile.open( QIODevice::ReadOnly | QIODevice::Text );\r\n\tQString val = file.readAll();\r\n\tfile.close();\r\n\r\n\tQJsonParseError error;\r\n\tja = QJsonDocument::fromJson( val.toUtf8(), &error );\r\n\r\n\tif ( error.error == QJsonParseError::NoError )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tqDebug() << \"json parse error in\" << url << error.offset;\r\n\r\n\treturn false;\r\n}\r\n"
  },
  {
    "path": "src/base/io.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\n\r\nclass IO : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\npublic:\r\n\tIO( Game* g, QObject* parent );\r\n\t~IO();\r\n\r\n\tstatic QString getDataFolder();\r\n\tstatic bool createFolders();\r\n\tstatic bool saveConfig();\r\n\tstatic bool loadOriginalConfig( QJsonDocument& jd );\r\n\r\n\tbool saveGameExists();\r\n\r\n\tQString save( bool autosave = false );\r\n\tbool load( QString folder );\r\n\r\n\tvoid sanitize();\r\n\r\n\tstatic bool saveCompatible( QString folder );\r\n\tstatic QString versionString( QString folder );\r\n\tstatic int versionInt( QString folder );\r\n\r\n\tstatic bool saveFile( QString url, const QJsonDocument& jd );\r\n\tstatic bool saveFile( QString url, const QJsonArray& ja );\r\n\tstatic bool saveFile( QString url, const QJsonObject& jo );\r\n\tstatic bool loadFile( QString url, QJsonDocument& ja );\r\n\r\n\tbool saveWorld( QString folder );\r\n\tbool loadWorld( QString folder );\r\n\tvoid loadWorld( QDataStream& in );\r\n\r\n\tQJsonArray jsonArraySprites();\r\n\tQJsonArray jsonArrayGame();\r\n\tQJsonArray jsonArrayConfig();\r\n\tQJsonArray jsonArrayWallConstructions();\r\n\tQJsonArray jsonArrayFloorConstructions();\r\n\tQJsonArray jsonArrayGnomes();\r\n\r\n\r\n\tQJsonArray jsonArrayMonsters( int startindex, int amount );\r\n\tQJsonArray jsonArrayAnimals( int startindex, int amount );\r\n\t\r\n\tQJsonArray jsonArrayPlants( int startindex, int amount );\r\n\tQJsonArray jsonArrayItems( int startindex, int amount );\r\n\tQJsonArray jsonArrayJobs();\r\n\tQJsonArray jsonArrayJobSprites();\r\n\tQJsonArray jsonArrayFarms();\r\n\tQJsonArray jsonArrayRooms();\r\n\tQJsonArray jsonArrayDoors();\r\n\tQJsonArray jsonArrayStockpiles();\r\n\tQJsonArray jsonArrayWorkshops();\r\n\tQJsonDocument jsonArrayItemHistory();\r\n\tQJsonDocument jsonArrayEvents();\r\n\tQJsonDocument jsonArrayMechanisms();\r\n\tQJsonDocument jsonArrayPipes();\r\n\r\n\tbool loadSprites( QJsonDocument& jd );\r\n\tbool loadGame( QJsonDocument& jd );\r\n\tbool loadConfig( QJsonDocument& jd );\r\n\tbool loadFloorConstructions( QJsonDocument& jd );\r\n\tbool loadWallConstructions( QJsonDocument& jd );\r\n\tbool loadGnomes( QJsonDocument& jd );\r\n\tbool loadMonsters( QString folder );\r\n\tbool loadPlants( QString folder );\r\n\tbool loadItems( QString folder );\r\n\tbool loadItemHistory( QJsonDocument& jd );\r\n\tbool loadJobs( QJsonDocument& jd );\r\n\tbool loadJobSprites( QJsonDocument& jd );\r\n\tbool loadFarms( QJsonDocument& jd );\r\n\tbool loadStockpiles( QJsonDocument& jd );\r\n\tbool loadAnimals( QString folder );\r\n\tbool loadWorkshops( QJsonDocument& jd );\r\n\tbool loadRooms( QJsonDocument& jd );\r\n\tbool loadDoors( QJsonDocument& jd );\r\n\tbool loadEvents( QJsonDocument& jd );\r\n\tbool loadMechanisms( QJsonDocument& jd );\r\n\tbool loadPipes( QJsonDocument& jd );\r\n\r\n\tbool saveItems( QString folder );\r\n\tbool savePlants( QString folder );\r\n\tbool saveAnimals( QString folder );\r\n\tbool saveMonsters( QString folder );\r\n\r\n\tint version = 0;\r\n\r\n\tQString getTempFolder();\r\n\r\nsignals:\r\n\tvoid signalStatus( QString text );\r\n};\r\n"
  },
  {
    "path": "src/base/lightmap.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"lightmap.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/gamestate.h\"\r\n\r\n#include <QDebug>\r\n#include <QList>\r\n#include <QPair>\r\n#include <QQueue>\r\n#include <QVector3D>\r\n\r\nLightMap::LightMap()\r\n{\r\n}\r\n\r\nLightMap::~LightMap()\r\n{\r\n}\r\n\r\nvoid LightMap::init()\r\n{\r\n\tm_lightMap.clear();\r\n\tm_lights.clear();\r\n\r\n\tm_dimX = Global::dimX;\r\n\tm_dimY = Global::dimY;\r\n\tm_dimZ = Global::dimZ;\r\n}\r\n\r\nvoid LightMap::addLight( QSet<unsigned int>& updateList, std::vector<Tile>& world, unsigned int id, Position pos, int intensity )\r\n{\r\n\tLight light;\r\n\tlight.id        = id;\r\n\tlight.pos       = pos;\r\n\tlight.intensity = intensity;\r\n\r\n\tQQueue<QPair<Position, int>> wq;\r\n\tQSet<unsigned int> visited;\r\n\twq.enqueue( QPair<Position, int>( pos, 0 ) );\r\n\tint decay = Global::cfg->get( \"lightDecay\" ).toInt();\r\n\r\n\tint range = intensity / decay;\r\n\r\n\tvisited.reserve( range * range * range );\r\n\r\n\twhile ( !wq.empty() )\r\n\t{\r\n\t\tQPair<Position, int> current = wq.dequeue();\r\n\t\tPosition curPos              = current.first;\r\n\t\tunsigned int curPosID        = curPos.toInt();\r\n\t\tif ( !visited.contains( curPosID ) )\r\n\t\t{\r\n\t\t\tvisited.insert( curPosID );\r\n\t\t\t// check line of sight to source\r\n\t\t\tQVector3D dir( curPos.x - pos.x, curPos.y - pos.y, curPos.z - pos.z );\r\n\t\t\tint curRadius = current.second;\r\n\t\t\tbool los      = true;\r\n\t\t\tfor ( int i = 1; i <= curRadius - 1; ++i )\r\n\t\t\t{\r\n\t\t\t\tQVector3D offset = dir * ( (float)i / (float)curRadius );\r\n\r\n\t\t\t\tTile& tile = getTile( world, pos.x + (int)( offset.x() ), pos.y + (int)( offset.y() ), pos.z + (int)( offset.z() ) );\r\n\t\t\t\tif ( tile.wallType & WallType::WT_VIEWBLOCKING )\r\n\t\t\t\t{\r\n\t\t\t\t\tlos = false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( los )\r\n\t\t\t{\r\n\t\t\t\tint dist         = sqrt( pos.distSquare( curPos ) );\r\n\t\t\t\tint curIntensity = 0;\r\n\t\t\t\tif ( curPos.z == pos.z )\r\n\t\t\t\t{\r\n\t\t\t\t\tcurIntensity = qMax( 0, ( intensity - decay * dist ) );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcurIntensity = qMax( 0, ( intensity - decay * curRadius ) );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( curIntensity > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_lightMap[curPosID].insert( id, curIntensity );\r\n\r\n\t\t\t\t\tTile& tile      = getTile( world, curPos );\r\n\t\t\t\t\ttile.lightLevel = calcIntensity( curPosID );\r\n\r\n\t\t\t\t\tlight.effectTiles.append( curPosID );\r\n\t\t\t\t\tupdateList.insert( curPosID );\r\n\r\n\t\t\t\t\tif ( !( tile.wallType & WallType::WT_VIEWBLOCKING ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tPosition north( curPos.x, ( curPos.y == 0 ) ? 0 : curPos.y - 1, curPos.z );\r\n\t\t\t\t\t\twq.enqueue( QPair<Position, int>( north, current.second + 1 ) );\r\n\t\t\t\t\t\tPosition south( curPos.x, ( curPos.y == m_dimY - 1 ) ? m_dimY - 1 : curPos.y + 1, curPos.z );\r\n\t\t\t\t\t\twq.enqueue( QPair<Position, int>( south, current.second + 1 ) );\r\n\t\t\t\t\t\tPosition east( ( curPos.x == m_dimX - 1 ) ? m_dimX - 1 : curPos.x + 1, curPos.y, curPos.z );\r\n\t\t\t\t\t\twq.enqueue( QPair<Position, int>( east, current.second + 1 ) );\r\n\t\t\t\t\t\tPosition west( ( curPos.x == 0 ) ? 0 : curPos.x - 1, curPos.y, curPos.z );\r\n\t\t\t\t\t\twq.enqueue( QPair<Position, int>( west, current.second + 1 ) );\r\n\t\t\t\t\t\tif ( !( tile.floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tPosition down( curPos.x, curPos.y, ( curPos.z == 0 ) ? 0 : curPos.z - 1 );\r\n\t\t\t\t\t\t\twq.enqueue( QPair<Position, int>( down, current.second + 1 ) );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( !( getTile( world, pos.aboveOf() ).floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tPosition up( curPos.x, curPos.y, ( curPos.z == m_dimZ - 1 ) ? m_dimZ - 1 : curPos.z + 1 );\r\n\t\t\t\t\t\t\twq.enqueue( QPair<Position, int>( up, current.second + 1 ) );\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\tm_lights.insert( id, light );\r\n}\r\n\r\nunsigned char LightMap::calcIntensity( unsigned int posID )\r\n{\r\n\tif ( m_lightMap.contains( posID ) )\r\n\t{\r\n\t\tconst auto& maps = m_lightMap[posID];\r\n\t\tint light = 0;\r\n\t\tfor ( const auto& value : maps )\r\n\t\t{\r\n\t\t\tlight += value;\r\n\t\t}\r\n\t\treturn qMin( 255, light );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nvoid LightMap::removeLight( QSet<unsigned int>& updateList, std::vector<Tile>& world, unsigned int id )\r\n{\r\n\tif ( m_lights.contains( id ) )\r\n\t{\r\n\t\tLight light = m_lights[id];\r\n\t\tm_lights.remove( id );\r\n\r\n\t\tfor ( auto posID : light.effectTiles )\r\n\t\t{\r\n\t\t\tm_lightMap[posID].remove( id );\r\n\r\n\t\t\tTile& tile      = world[posID];\r\n\t\t\ttile.lightLevel = calcIntensity( posID );\r\n\t\t\tupdateList.insert( posID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid LightMap::updateLight( QSet<unsigned int>& updateList, std::vector<Tile>& world, Position pos )\r\n{\r\n\tunsigned int posID = pos.toInt();\r\n\tif ( m_lightMap.contains( posID ) )\r\n\t{\r\n\t\tauto maps = m_lightMap[posID];\r\n\r\n\t\tfor ( auto key : maps.keys() )\r\n\t\t{\r\n\t\t\tLight light = m_lights[key];\r\n\r\n\t\t\tremoveLight( updateList, world, key );\r\n\t\t\taddLight( updateList, world, key, light.pos, light.intensity );\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/base/lightmap.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../base/tile.h\"\r\n\r\n#include <vector>\r\n\r\nstruct Light\r\n{\r\n\tunsigned int id;\r\n\tPosition pos;\r\n\tint intensity;\r\n\tQList<unsigned int> effectTiles;\r\n};\r\n\r\nclass LightMap\r\n{\r\npublic:\r\n\tLightMap();\r\n\t~LightMap();\r\n\r\n\tvoid init();\r\n\r\n\tvoid addLight( QSet<unsigned int>& updateList, std::vector<Tile>& world, unsigned int id, Position pos, int intensity );\r\n\tvoid removeLight( QSet<unsigned int>& updateList, std::vector<Tile>& world, unsigned int id );\r\n\tvoid updateLight( QSet<unsigned int>& updateList, std::vector<Tile>& world, Position pos );\r\n\r\nprivate:\r\n\tQMap<unsigned int, QMap<unsigned int, unsigned char>> m_lightMap;\r\n\tQMap<unsigned int, Light> m_lights;\r\n\r\n\tunsigned char calcIntensity( unsigned int posID );\r\n\r\n\tint m_dimX = 0;\r\n\tint m_dimY = 0;\r\n\tint m_dimZ = 0;\r\n\r\n\tTile& getTile( std::vector<Tile>& world, unsigned short x, unsigned short y, unsigned short z )\r\n\t{\r\n\t\treturn world[x + y * m_dimX + z * m_dimX * m_dimY];\r\n\t}\r\n\tTile& getTile( std::vector<Tile>& world, Position pos )\r\n\t{\r\n\t\treturn world[pos.x + pos.y * m_dimX + pos.z * m_dimX * m_dimY];\r\n\t}\r\n};\r\n"
  },
  {
    "path": "src/base/logger.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"logger.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n\r\nLogger::Logger()\r\n{\r\n}\r\n\r\nLogger::~Logger()\r\n{\r\n}\r\n\r\nvoid Logger::reset()\r\n{\r\n\tm_messages.clear();\r\n}\r\n\r\nvoid Logger::log( LogType lt, QString msg, unsigned int sourceEntity )\r\n{\r\n\tLogMessage lm { GameState::tick, \"\", lt, msg, sourceEntity };\r\n\tQMutexLocker lock( &m_mutex );\r\n\tm_messages.push_back( lm );\r\n}\r\n"
  },
  {
    "path": "src/base/logger.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMutex>\r\n#include <QString>\r\n\r\n#include <vector>\r\n\r\nenum class LogType\r\n{\r\n\tDEBUG,\r\n\tJOB,\r\n\tCRAFT,\r\n\tCOMBAT\r\n};\r\n\r\nstruct LogMessage\r\n{\r\n\tquint64 tick;\r\n\tQString dateTime;\r\n\tLogType type;\r\n\tQString message;\r\n\tunsigned int source;\r\n};\r\n\r\nclass Logger\r\n{\r\npublic:\r\n\tLogger();\r\n\t~Logger();\r\n\r\n\tvoid reset();\r\n\r\n\tvoid log( LogType lt, QString msg, unsigned int sourceEntity );\r\n\r\n\tstd::vector<LogMessage>& messages()\r\n\t{\r\n\t\treturn m_messages;\r\n\t}\r\n\r\nprivate:\r\n\tQMutex m_mutex;\r\n\r\n\tstd::vector<LogMessage> m_messages;\r\n};\r\n"
  },
  {
    "path": "src/base/octree.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"octree.h\"\r\n\r\nOctree::Octree( int x, int y, int z, int dx, int dy, int dz ) :\r\n\tm_x( x ),\r\n\tm_y( y ),\r\n\tm_z( z ),\r\n\tm_dx( dx ),\r\n\tm_dy( dy ),\r\n\tm_dz( dz ),\r\n\tm_isLeaf( dx <= 4 || dy <= 4 || dz <= 4 )\r\n{\r\n}\r\n\r\nOctree::~Octree()\r\n{\r\n\tfor ( auto ot : m_children )\r\n\t{\r\n\t\tdelete ot;\r\n\t}\r\n\tm_items.clear();\r\n}\r\n\r\nvoid Octree::insertItem( int x, int y, int z, unsigned int item )\r\n{\r\n\tif ( m_isLeaf )\r\n\t{\r\n\t\tm_items.insert( item );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint id = 0;\r\n\t\tif ( x >= m_x )\r\n\t\t\tid += 2;\r\n\t\tif ( y >= m_y )\r\n\t\t\tid += 1;\r\n\t\tif ( z >= m_z )\r\n\t\t\tid += 4;\r\n\t\tif ( !m_children[id] )\r\n\t\t{\r\n\t\t\tint x2         = m_dx / 2;\r\n\t\t\tint y2         = m_dy / 2;\r\n\t\t\tint z2         = m_dz / 2;\r\n\t\t\tm_children[id] = new Octree(\r\n\t\t\t\t( x >= m_x ) ? m_x + x2 : m_x - x2,\r\n\t\t\t\t( y >= m_y ) ? m_y + y2 : m_y - y2,\r\n\t\t\t\t( z >= m_z ) ? m_z + z2 : m_z - z2,\r\n\t\t\t\tx2, y2, z2 );\r\n\t\t}\r\n\t\tm_children[id]->insertItem( x, y, z, item );\r\n\t}\r\n}\r\n\r\nbool Octree::removeItem( int x, int y, int z, unsigned int item )\r\n{\r\n\tif ( m_isLeaf )\r\n\t{\r\n\t\tm_items.remove( item );\r\n\t\treturn m_items.isEmpty();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint id = 0;\r\n\t\tif ( x >= m_x )\r\n\t\t\tid += 2;\r\n\t\tif ( y >= m_y )\r\n\t\t\tid += 1;\r\n\t\tif ( z >= m_z )\r\n\t\t\tid += 4;\r\n\t\tif ( m_children[id] )\r\n\t\t{\r\n\t\t\tbool empty = m_children[id]->removeItem( x, y, z, item );\r\n\t\t\tif ( empty )\r\n\t\t\t{\r\n\t\t\t\tdelete m_children[id];\r\n\t\t\t\tm_children[id] = nullptr;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( int i = 0; i < 8; ++i )\r\n\t\t{\r\n\t\t\tif ( m_children[i] )\r\n\t\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\nQList<unsigned int> Octree::query( int x, int y, int z, int limit ) const\r\n{\r\n\tif ( m_isLeaf )\r\n\t{\r\n\t\treturn m_items.values();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint id = 0;\r\n\t\tif ( x >= m_x )\r\n\t\t\tid += 2;\r\n\t\tif ( y >= m_y )\r\n\t\t\tid += 1;\r\n\t\tif ( z >= m_z )\r\n\t\t\tid += 4;\r\n\r\n\t\tQList<unsigned int> out;\r\n\r\n\t\tfor ( int i = 0; i < 8; ++i )\r\n\t\t{\r\n\t\t\tint j = ( i + id ) % 8;\r\n\t\t\tif ( m_children[j] )\r\n\t\t\t{\r\n\t\t\t\tout.append( m_children[j]->query( x, y, z, limit ) );\r\n\t\t\t\tif ( out.size() > limit )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn out;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn out;\r\n\t}\r\n}\r\n\r\nbool Octree::visit( int x, int y, int z, const std::function<bool( unsigned int )>& visitor ) const\r\n{\r\n\tif ( m_isLeaf )\r\n\t{\r\n\t\tfor ( const auto& item : m_items )\r\n\t\t{\r\n\t\t\tif ( !visitor( item ) )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint id = 0;\r\n\t\tif ( x >= m_x )\r\n\t\t\tid += 2;\r\n\t\tif ( y >= m_y )\r\n\t\t\tid += 1;\r\n\t\tif ( z >= m_z )\r\n\t\t\tid += 4;\r\n\r\n\t\tfor ( int i = 0; i < 8; ++i )\r\n\t\t{\r\n\t\t\tint j = ( i + id ) % 8;\r\n\t\t\tif ( m_children[j] && !m_children[j]->visit( x, y, z, visitor ) )\r\n\t\t\t{\r\n\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"
  },
  {
    "path": "src/base/octree.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QList>\r\n#include <QSet>\r\n\r\n#include <functional>\r\n\r\nclass Octree\r\n{\r\npublic:\r\n\tOctree() = delete;\r\n\tOctree( int x, int y, int z, int dx, int dy, int dz );\r\n\t~Octree();\r\n\r\n\tvoid insertItem( int x, int y, int z, unsigned int item );\r\n\tbool removeItem( int x, int y, int z, unsigned int item );\r\n\r\n\tQList<unsigned int> query( int x, int y, int z, int limit = 999999999 ) const;\r\n\tbool visit( int x, int y, int z, const std::function<bool( unsigned int )>& visitor ) const;\r\n\r\nprivate:\r\n\tconst int m_x;\r\n\tconst int m_y;\r\n\tconst int m_z;\r\n\r\n\tconst int m_dx;\r\n\tconst int m_dy;\r\n\tconst int m_dz;\r\n\r\n\tconst bool m_isLeaf;\r\n\r\n\tOctree* m_children[8] = { 0 };\r\n\tQSet<unsigned int> m_items;\r\n};\r\n"
  },
  {
    "path": "src/base/pathfinder.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"pathfinder.h\"\r\n\r\n#include \"../base/PathFinderThread.h\"\r\n#include \"../base/config.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n\r\nPathFinder::PathFinder( World* world, QObject* parent) :\r\n\tm_world( world ),\r\n\tQObject(parent)\r\n{\r\n}\r\n\r\nPathFinder::~PathFinder()\r\n{\r\n\tm_jobs.clear();\r\n}\r\n\r\nvoid PathFinder::cancelRequest( unsigned int id )\r\n{\r\n\t//TODO implement\r\n}\r\n\r\nPathFinderResult PathFinder::getPath( unsigned int id, Position start, Position goal, bool ignoreNoPass, std::vector<Position>& path )\r\n{\r\n\tQMutexLocker lock( &m_mutex );\r\n\tauto it = m_jobs.find( id );\r\n\tif ( it != m_jobs.end() )\r\n\t{\r\n\t\tif ( it->state != PathFinderResult::Running && it->state != PathFinderResult::Pending )\r\n\t\t{\r\n\t\t\tpath = std::move( it->path );\r\n\t\t\tconst auto result = it->state;\r\n\t\t\tm_jobs.erase( it );\r\n\t\t\treturn result;\r\n\t\t}\r\n\t\tpath.clear();\r\n\t\treturn PathFinderResult::Running;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Fast synchronous checks\r\n\t\tif ( !m_world->isWalkableGnome( goal ) )\r\n\t\t{\r\n\t\t\treturn PathFinderResult::NoConnection;\r\n\t\t}\r\n\r\n\t\tif ( !checkConnectedRegions( start, goal ) )\r\n\t\t{\r\n\t\t\treturn PathFinderResult::NoConnection;\r\n\t\t}\r\n\t\tif ( start.distSquare( goal, 2 ) == 1 )\r\n\t\t{\r\n\t\t\tpath = { goal };\r\n\t\t\treturn PathFinderResult::FoundPath;\r\n\t\t}\r\n\t\tif ( start.z == goal.z && start.distSquare( goal ) < 10 )\r\n\t\t{\r\n\t\t\tauto naivePath = getNaivePath( start, goal );\r\n\r\n\t\t\tif ( !naivePath.empty() )\r\n\t\t\t{\r\n\t\t\t\tpath = naivePath;\r\n\t\t\t\treturn PathFinderResult::FoundPath;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// If no trivial solution exists, fork to worker\r\n\t\tauto it = m_jobs.insert(\r\n\t\t\tid,\r\n\t\t\t{\r\n\t\t\t\tstart,\r\n\t\t\t\tgoal,\r\n\t\t\t\tignoreNoPass,\r\n\t\t\t\tPathFinderResult::Pending,\r\n\t\t\t\t{}\r\n\t\t\t}\r\n\t\t);\r\n\r\n\t\treturn it->state;\r\n\t}\r\n}\r\n\r\nvoid PathFinder::findPaths()\r\n{\r\n\tusing namespace std::placeholders;\r\n\r\n\tstd::vector<std::future<void>> tasks;\r\n\tdecltype( m_jobs ) jobs;\r\n\r\n\t{\r\n\t\tQMutexLocker lock( &m_mutex );\r\n\r\n\t\t// Filter jobs which are not pending yet\r\n\t\tfor ( auto it = m_jobs.begin(); it != m_jobs.end(); ++it )\r\n\t\t{\r\n\t\t\tif ( it.value().state == PathFinderResult::Pending )\r\n\t\t\t{\r\n\t\t\t\tit.value().state = PathFinderResult::Running;\r\n\t\t\t\tjobs.insert( it.key(), it.value() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto it = jobs.begin(); it != jobs.end(); ++it)\r\n\t{\r\n\t\t// Common case is for many creatures to have the same goal, so invert path finding direction by default\r\n\t\tconst Position start = it->goal;\r\n\t\tstd::unordered_set<Position> goals = { it->start };\r\n\t\tconst bool ignoreNoPass = it->ignoreNoPass;\r\n\t\t// Fold all other requests which share either of goal or start into this one\r\n\t\tfor (auto it2 = it + 1; it2 != jobs.end();)\r\n\t\t{\r\n\t\t\tif (it2->ignoreNoPass == ignoreNoPass)\r\n\t\t\t{\r\n\t\t\t\tif (it2->goal == start)\r\n\t\t\t\t{\r\n\t\t\t\t\tgoals.emplace( it2->start );\r\n\t\t\t\t\tit2 = jobs.erase( it2 );\r\n\t\t\t\t}\r\n\t\t\t\telse if (it2->start == start)\r\n\t\t\t\t{\r\n\t\t\t\t\tgoals.emplace( it2->goal );\r\n\t\t\t\t\tit2 = jobs.erase( it2 );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t++it2;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++it2;\r\n\t\t\t}\r\n\t\t}\r\n\t\ttasks.emplace_back(std::async(\r\n\t\t\tstd::launch::async,\r\n\t\t\tPathFinderThread( m_world, start, std::move( goals ), ignoreNoPass, std::bind( &PathFinder::onResult, this, _1, _2, _3, _4 ) )\r\n\t\t));\r\n\t}\r\n\tfor ( auto& task : tasks )\r\n\t{\r\n\t\ttask.get();\r\n\t}\r\n}\r\n\r\n\r\nvoid PathFinder::onResult( Position start, Position goal, bool ignoreNoPass, std::vector<Position> path )\r\n{\r\n\tQMutexLocker lock( &m_mutex );\r\n\tfor ( auto& job : m_jobs )\r\n\t{\r\n\t\tconst bool forwardPath = ( job.goal == goal && job.start == start );\r\n\t\tconst bool reversePath = ( job.goal == start && job.start == goal );\r\n\t\tif ( ( forwardPath || reversePath ) && job.ignoreNoPass == ignoreNoPass )\r\n\t\t{\r\n\t\t\tif ( path.empty() )\r\n\t\t\t{\r\n\t\t\t\tjob.state = PathFinderResult::NoConnection;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tjob.state = PathFinderResult::FoundPath;\r\n\t\t\t\tif ( forwardPath )\r\n\t\t\t\t{\r\n\t\t\t\t\tjob.path = std::move( path );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// Copy in reverse order, minus element [0] (our current position), and prepend our real goal instead\r\n\t\t\t\t\tjob.path.reserve( path.size() );\r\n\t\t\t\t\tjob.path.emplace_back( start );\r\n\t\t\t\t\tfor ( auto it = path.crbegin(); it != path.crend() - 1; ++it )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob.path.emplace_back( *it );\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\n\r\nstd::vector<Position> PathFinder::getNaivePath( Position& start, Position& goal )\r\n{\r\n\tstd::vector<Position> out;\r\n\r\n\tPosition current = goal;\r\n\tout.push_back( goal );\r\n\twhile ( current != start )\r\n\t{\r\n\t\tbool changed = false;\r\n\t\tfor ( auto neigh : m_world->connectedNeighbors( current ) )\r\n\t\t{\r\n\t\t\tif ( ( neigh.z == current.z ) && ( neigh.distSquare( start ) < current.distSquare( start ) ) )\r\n\t\t\t{\r\n\t\t\t\tcurrent = neigh;\r\n\t\t\t\tout.push_back( current );\r\n\t\t\t\tchanged = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( !changed )\r\n\t\t{\r\n\t\t\tout.clear();\r\n\t\t\treturn out;\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nbool PathFinder::checkConnectedRegions( const Position start, const Position goal )\r\n{\r\n\treturn m_world->regionMap().checkConnectedRegions( start, goal );\r\n}\r\n"
  },
  {
    "path": "src/base/pathfinder.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QMutex>\r\n#include <QQueue>\r\n#include <QSet>\r\n#include <QThreadPool>\r\n#include <QVector>\r\n#include <optional>\r\n\r\nclass PathFinderThread;\r\nclass World;\r\n\r\nstruct PathFindingRequest\r\n{\r\n\tunsigned int ID;\r\n\tPosition start;\r\n\tPosition goal;\r\n\tbool ignoreNoPass;\r\n};\r\n\r\nenum class PathFinderResult\r\n{\r\n\tNoConnection,\r\n\tFoundPath,\r\n\tRunning,\r\n\tPending\r\n};\r\n\r\nclass PathFinder : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( PathFinder )\r\npublic:\r\n\tPathFinder( World* world, QObject* parent );\r\n\t~PathFinder();\r\n\r\nprivate:\r\n\tstruct PathFinderJob\r\n\t{\r\n\t\tPosition start;\r\n\t\tPosition goal;\r\n\t\tbool ignoreNoPass      = false;\r\n\t\tPathFinderResult state = PathFinderResult::Pending;\r\n\t\tstd::vector<Position> path;\r\n\t};\r\n\r\n\tQMap<unsigned int, PathFinderJob> m_jobs;\r\n\r\n\tQMutex m_mutex;\r\n\r\n\tstd::vector<Position> getNaivePath( Position& start, Position& goal );\r\n\r\n\tWorld* m_world = nullptr;\r\n\r\npublic:\r\n\tPathFinderResult getPath( unsigned int id, Position start, Position goal, bool ignoreNoPass, std::vector<Position>& path );\r\n\r\n\tvoid cancelRequest( unsigned int id );\r\n\r\n\tbool checkConnectedRegions( const Position start, const Position goal );\r\n\r\n\tvoid onResult( Position start, Position goal, bool ignoreNoPass, std::vector<Position> path );\r\n\t// Dispatch workers for all outstanding pathfinding requests\r\n\tvoid findPaths();\r\n};\r\n"
  },
  {
    "path": "src/base/position.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/global.h\"\r\n\r\n#include <QString>\r\n#include <QStringList>\r\n#include <QVariant>\r\n\r\n#include <tuple>\r\n\r\nclass Sprite;\r\n\r\nstruct Position\r\n{\r\n\tconstexpr Position() = default;\r\n\tPosition& operator=( const Position& other ) = default;\r\n\r\n\tconstexpr Position( int _x, int _y, int _z ) :\r\n\t\tx( _x ), y( _y ), z( _z )\r\n\t{\r\n\t}\r\n\r\n\tPosition( QString text ) :\r\n\t\tx( 0 ), y( 0 ), z( 0 )\r\n\t{\r\n\t\tQStringList sl = text.split( \" \" );\r\n\t\tassert( sl.size() == 3 );\r\n\t\tif ( sl.size() == 3 )\r\n\t\t{\r\n\t\t\tx = sl[0].toInt();\r\n\t\t\ty = sl[1].toInt();\r\n\t\t\tz = sl[2].toInt();\r\n\r\n\t\t\tassert( x < Global::dimX );\r\n\t\t\tassert( y < Global::dimY );\r\n\t\t\tassert( z <= Global::dimZ );\r\n\t\t}\r\n\t}\r\n\r\n\tPosition( QVariant val ) :\r\n\t\tx( 0 ), y( 0 ), z( 0 )\r\n\t{\r\n\t\tQStringList sl = val.toString().split( \" \" );\r\n\t\tassert( sl.size() == 3 );\r\n\t\tif ( sl.size() == 3 )\r\n\t\t{\r\n\t\t\tx = sl[0].toInt();\r\n\t\t\ty = sl[1].toInt();\r\n\t\t\tz = sl[2].toInt();\r\n\r\n\t\t\tassert( x < Global::dimX );\r\n\t\t\tassert( y < Global::dimY );\r\n\t\t\tassert( z <= Global::dimZ );\r\n\t\t}\r\n\t}\r\n\r\n\tPosition( unsigned int tileID ) :\r\n\t\tx( 0 ), y( 0 ), z( 0 )\r\n\t{\r\n\t\tz = tileID / ( Global::dimX * Global::dimY );\r\n\t\ty = ( tileID / Global::dimX ) % Global::dimY;\r\n\t\tx = tileID % Global::dimX;\r\n\r\n\t\tassert( x < Global::dimX );\r\n\t\tassert( y < Global::dimY );\r\n\t\tassert( z <= Global::dimZ );\r\n\t}\r\n\r\n\tconstexpr bool operator==( const Position& other ) const\r\n\t{\r\n\t\treturn std::tie( x, y, z ) == std::tie( other.x, other.y, other.z );\r\n\t}\r\n\tconstexpr bool operator!=( const Position& other ) const\r\n\t{\r\n\t\treturn std::tie( x, y, z ) != std::tie( other.x, other.y, other.z );\r\n\t}\r\n\tconstexpr bool operator<( const Position& other ) const\r\n\t{\r\n\t\treturn std::tie( x, y, z ) < std::tie( other.x, other.y, other.z );\r\n\t}\r\n\tconstexpr Position operator-( const Position& other ) const\r\n\t{\r\n\t\treturn Position( x - other.x, y - other.y, z - other.z );\r\n\t}\r\n\tconstexpr Position operator+( const Position& other ) const\r\n\t{\r\n\t\treturn Position( x + other.x, y + other.y, z + other.z );\r\n\t}\r\n\tconstexpr Position operator/( const int& other ) const\r\n\t{\r\n\t\treturn Position( x / other, y / other, z / other );\r\n\t}\r\n\r\n\tQString toString() const\r\n\t{\r\n\t\treturn QString::number( x ) + \" \" + QString::number( y ) + \" \" + QString::number( z );\r\n\t}\r\n\r\n\tconstexpr int distSquare( const Position& other, int zWeight = 1 ) const\r\n\t{\r\n\t\treturn ( ( x - other.x ) * ( x - other.x ) ) + ( ( y - other.y ) * ( y - other.y ) ) + ( ( z - other.z ) * ( z - other.z ) * zWeight );\r\n\t}\r\n\tconstexpr int distSquare( int otherX, int otherY, int otherZ, int zWeight = 1 ) const\r\n\t{\r\n\t\treturn ( ( x - otherX ) * ( x - otherX ) ) + ( ( y - otherY ) * ( y - otherY ) ) + ( ( z - otherZ ) * ( z - otherZ ) * zWeight );\r\n\t}\r\n\r\n\tunsigned int toInt() const\r\n\t{\r\n\t\tassert( x < Global::dimX );\r\n\t\tassert( y < Global::dimY );\r\n\t\tassert( z <= Global::dimZ );\r\n\t\treturn x + Global::dimX * y + Global::dimX * Global::dimX * z;\r\n\t\t//return x + 4096 * y + 16777216 * z;\r\n\t}\r\n\r\n\tconstexpr unsigned int toHashBase() const\r\n\t{\r\n\t\treturn ( z << 20 ) + ( y << 10 ) + x;\r\n\t}\r\n\r\n\tbool valid() const\r\n\t{\r\n\t\t// Usuable volume excludes 1 row/col in each X and Y, so neighbours are addressable for read-only\r\n\t\treturn x >= 1 && x <= Global::dimX - 2 && y >= 1 && y <= Global::dimY - 2 && z >= 0 && z <= Global::dimZ - 1;\r\n\t}\r\n\r\n\tconstexpr Position northOf() const\r\n\t{\r\n\t\treturn Position( x, y - 1, z );\r\n\t}\r\n\tconstexpr Position eastOf() const\r\n\t{\r\n\t\treturn Position( x + 1, y, z );\r\n\t}\r\n\tconstexpr Position southOf() const\r\n\t{\r\n\t\treturn Position( x, y + 1, z );\r\n\t}\r\n\tconstexpr Position westOf() const\r\n\t{\r\n\t\treturn Position( x - 1, y, z );\r\n\t}\r\n\tconstexpr Position aboveOf() const\r\n\t{\r\n\t\treturn Position( x, y, z + 1 );\r\n\t}\r\n\tconstexpr Position belowOf() const\r\n\t{\r\n\t\treturn Position( x, y, z - 1 );\r\n\t}\r\n\r\n\tconstexpr Position neOf() const\r\n\t{\r\n\t\treturn Position( x + 1, y - 1, z );\r\n\t}\r\n\tconstexpr Position seOf() const\r\n\t{\r\n\t\treturn Position( x + 1, y + 1, z );\r\n\t}\r\n\tconstexpr Position nwOf() const\r\n\t{\r\n\t\treturn Position( x - 1, y - 1, z );\r\n\t}\r\n\tconstexpr Position swOf() const\r\n\t{\r\n\t\treturn Position( x - 1, y + 1, z );\r\n\t}\r\n\r\n\tvoid setToBounds()\r\n\t{\r\n\t\tx = qMax( 0, qMin( Global::dimX - 1, (int)x ) );\r\n\t\ty = qMax( 0, qMin( Global::dimX - 1, (int)y ) );\r\n\t\tz = qMax( 0, qMin( Global::dimZ - 1, (int)z ) );\r\n\t}\r\n\r\n\tconstexpr bool isZero() const\r\n\t{\r\n\t\treturn x == 0 && y == 0 && z == 0;\r\n\t}\r\n\r\n\tconstexpr bool is( short xx, short yy, short zz ) const\r\n\t{\r\n\t\treturn x == xx && y == yy && z == zz;\r\n\t}\r\n\r\n\tshort x = 0;\r\n\tshort y = 0;\r\n\tshort z = 0;\r\n};\r\nQ_DECLARE_TYPEINFO( Position, Q_PRIMITIVE_TYPE );\r\nQ_DECLARE_METATYPE( Position );\r\n\r\nconstexpr uint qHash( const Position& key, uint seed )\r\n{\r\n\treturn qHash( key.toHashBase(), seed );\r\n}\r\nnamespace std\r\n{\r\ntemplate <>\r\nstruct hash<Position>\r\n{\r\n\tinline std::size_t operator()( const Position& k ) const\r\n\t{\r\n\t\treturn std::hash<unsigned int>()( k.toHashBase() );\r\n\t}\r\n};\r\n\r\n} // namespace std\r\n\r\ninline bool testLine( const Position& a, const Position& b, const std::function<bool( const Position& current, const Position& previous )>& callback )\r\n{\r\n\t// Bresenham's Algorithm\r\n\tconst auto distX = std::abs( a.x - b.x );\r\n\tconst auto distY = std::abs( a.y - b.y );\r\n\tconst auto distZ = std::abs( a.z - b.z );\r\n\r\n\tconst auto dirX = a.x < b.x ? 1 : ( a.x > b.x ? -1 : 0 );\r\n\tconst auto dirY = a.y < b.y ? 1 : ( a.y > b.y ? -1 : 0 );\r\n\tconst auto dirZ = a.z < b.z ? 1 : ( a.z > b.z ? -1 : 0 );\r\n\r\n\tconst bool xIsMax = distX >= distY && distX >= distZ;\r\n\tconst bool yIsMax = distY >= distX && distY >= distZ;\r\n\tconst bool zIsMax = distZ >= distX && distZ >= distY;\r\n\r\n\tauto current  = a;\r\n\tauto previous = a;\r\n\r\n\tif ( !callback( current, previous ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tif ( xIsMax )\r\n\t{\r\n\t\tauto p1 = 2 * distY - distX;\r\n\t\tauto p2 = 2 * distZ - distX;\r\n\t\twhile ( current.x != b.x )\r\n\t\t{\r\n\t\t\tprevious = current;\r\n\t\t\tcurrent.x += dirX;\r\n\t\t\tif ( p1 > 0 )\r\n\t\t\t{\r\n\t\t\t\tcurrent.y += dirY;\r\n\t\t\t\tp1 -= 2 * dirX;\r\n\t\t\t}\r\n\t\t\tif ( p2 > 0 )\r\n\t\t\t{\r\n\t\t\t\tcurrent.z += dirZ;\r\n\t\t\t\tp2 -= 2 * dirX;\r\n\t\t\t}\r\n\t\t\tp1 += 2 * dirY;\r\n\t\t\tp2 += 2 * dirZ;\r\n\t\t\tif ( !callback( current, previous ) )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( yIsMax )\r\n\t{\r\n\t\tauto p1 = 2 * distX - distY;\r\n\t\tauto p2 = 2 * distZ - distY;\r\n\t\twhile ( current.y != b.y )\r\n\t\t{\r\n\t\t\tprevious = current;\r\n\t\t\tcurrent.y += dirY;\r\n\t\t\tif ( p1 > 0 )\r\n\t\t\t{\r\n\t\t\t\tcurrent.x += dirX;\r\n\t\t\t\tp1 -= 2 * dirY;\r\n\t\t\t}\r\n\t\t\tif ( p2 > 0 )\r\n\t\t\t{\r\n\t\t\t\tcurrent.z += dirZ;\r\n\t\t\t\tp2 -= 2 * dirY;\r\n\t\t\t}\r\n\t\t\tp1 += 2 * dirX;\r\n\t\t\tp2 += 2 * dirZ;\r\n\t\t\tif ( !callback( current, previous ) )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( zIsMax )\r\n\t{\r\n\t\tauto p1 = 2 * distX - distZ;\r\n\t\tauto p2 = 2 * distY - distZ;\r\n\t\twhile ( current.z != b.z )\r\n\t\t{\r\n\t\t\tprevious = current;\r\n\t\t\tcurrent.z += dirZ;\r\n\t\t\tif ( p1 > 0 )\r\n\t\t\t{\r\n\t\t\t\tcurrent.x += dirX;\r\n\t\t\t\tp1 -= 2 * dirZ;\r\n\t\t\t}\r\n\t\t\tif ( p2 > 0 )\r\n\t\t\t{\r\n\t\t\t\tcurrent.y += dirY;\r\n\t\t\t\tp2 -= 2 * dirZ;\r\n\t\t\t}\r\n\t\t\tp1 += 2 * dirX;\r\n\t\t\tp2 += 2 * dirY;\r\n\t\t\tif ( !callback( current, previous ) )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}"
  },
  {
    "path": "src/base/priorityqueue.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <queue>\r\n\r\n#include <functional>\r\n#include <utility>\r\n\r\ntemplate <typename T, typename priority_t, typename value_t = std::pair<priority_t, T>>\r\nclass PriorityQueue : public std::priority_queue<value_t, std::vector<value_t>, std::greater<value_t>>\r\n{\r\npublic:\r\n\tusing base_type = std::priority_queue<value_t, std::vector<value_t>, std::greater<value_t>>;\r\n\tinline void put( const T &item, const priority_t &priority )\r\n\t{\r\n\t\tbase_type::emplace( priority, item );\r\n\t}\r\n\r\n\tinline T get()\r\n\t{\r\n\t\tT best_item = base_type::top().second;\r\n\t\tbase_type::pop();\r\n\t\treturn best_item;\r\n\t}\r\n\r\n\tinline const std::vector<value_t>& raw() const\r\n\t{\r\n\t\treturn base_type::c;\r\n\t}\r\n};\r\n"
  },
  {
    "path": "src/base/region.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"region.h\"\r\n\r\n#include \"../base/global.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nRegion::Region( unsigned int id ) :\r\n\tm_id( id )\r\n{\r\n}\r\n\r\nRegion::~Region()\r\n{\r\n}\r\n\r\nvoid Region::addConnectionFrom( unsigned int toRegion, const Position& pos )\r\n{\r\n\tm_connectionsFrom[toRegion].insert( pos.toString() );\r\n}\r\nvoid Region::addConnectionTo( unsigned int toRegion, const Position& pos )\r\n{\r\n\tm_connectionsTo[toRegion].insert( pos.toString() );\r\n}\r\nvoid Region::removeConnectionFrom( unsigned int toRegion, const Position& pos )\r\n{\r\n\tm_connectionsFrom[toRegion].remove( pos.toString() );\r\n\tif ( m_connectionsFrom[toRegion].empty() )\r\n\t{\r\n\t\tm_connectionsFrom.remove( toRegion );\r\n\t}\r\n}\r\nvoid Region::removeConnectionTo( unsigned int toRegion, const Position& pos )\r\n{\r\n\tm_connectionsTo[toRegion].remove( pos.toString() );\r\n\tif ( m_connectionsTo[toRegion].empty() )\r\n\t{\r\n\t\tm_connectionsTo.remove( toRegion );\r\n\t}\r\n}\r\n\r\nvoid Region::addConnectionFrom( unsigned int toRegion, QString pos )\r\n{\r\n\tm_connectionsFrom[toRegion].insert( pos );\r\n}\r\nvoid Region::addConnectionTo( unsigned int toRegion, QString pos )\r\n{\r\n\tm_connectionsTo[toRegion].insert( pos );\r\n}\r\nvoid Region::removeConnectionFrom( unsigned int toRegion, QString pos )\r\n{\r\n\tm_connectionsFrom[toRegion].remove( pos );\r\n\tif ( m_connectionsFrom[toRegion].empty() )\r\n\t{\r\n\t\tm_connectionsFrom.remove( toRegion );\r\n\t}\r\n}\r\nvoid Region::removeConnectionTo( unsigned int toRegion, QString pos )\r\n{\r\n\tm_connectionsTo[toRegion].remove( pos );\r\n\tif ( m_connectionsTo[toRegion].empty() )\r\n\t{\r\n\t\tm_connectionsTo.remove( toRegion );\r\n\t}\r\n}\r\n\r\nvoid Region::removeAllConnectionsFrom( unsigned int id )\r\n{\r\n\tm_connectionsFrom.remove( id );\r\n}\r\n\r\nvoid Region::removeAllConnectionsTo( unsigned int id )\r\n{\r\n\tm_connectionsTo.remove( id );\r\n}\r\n"
  },
  {
    "path": "src/base/region.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QMap>\r\n#include <QSet>\r\n\r\nclass Region\r\n{\r\npublic:\r\n\tRegion( unsigned int id = 0 );\r\n\t~Region();\r\n\r\n\tvoid addConnectionFrom( unsigned int toRegion, const Position& pos );\r\n\tvoid addConnectionTo( unsigned int toRegion, const Position& pos );\r\n\tvoid addConnectionFrom( unsigned int toRegion, QString pos );\r\n\tvoid addConnectionTo( unsigned int toRegion, QString pos );\r\n\r\n\tvoid removeConnectionFrom( unsigned int toRegion, const Position& pos );\r\n\tvoid removeConnectionTo( unsigned int toRegion, const Position& pos );\r\n\tvoid removeConnectionFrom( unsigned int toRegion, QString pos );\r\n\tvoid removeConnectionTo( unsigned int toRegion, QString pos );\r\n\r\n\tvoid clearConnectionsFrom()\r\n\t{\r\n\t\tm_connectionsFrom.clear();\r\n\t}\r\n\tvoid clearConnectionsTo()\r\n\t{\r\n\t\tm_connectionsTo.clear();\r\n\t}\r\n\r\n\tvoid removeAllConnectionsFrom( unsigned int id );\r\n\tvoid removeAllConnectionsTo( unsigned int id );\r\n\r\n\tQMap<unsigned int, QSet<QString>> connectionSetFrom()\r\n\t{\r\n\t\treturn m_connectionsFrom;\r\n\t};\r\n\tQMap<unsigned int, QSet<QString>> connectionSetTo()\r\n\t{\r\n\t\treturn m_connectionsTo;\r\n\t}\r\n\r\n\tQSet<QString> connectionsToRegion( unsigned int region )\r\n\t{\r\n\t\treturn m_connectionsTo.value( region );\r\n\t}\r\n\r\n\tunsigned id()\r\n\t{\r\n\t\treturn m_id;\r\n\t}\r\n\tQList<unsigned int> connectionsFrom()\r\n\t{\r\n\t\treturn m_connectionsFrom.keys();\r\n\t}\r\n\tQList<unsigned int> connectionsTo()\r\n\t{\r\n\t\treturn m_connectionsTo.keys();\r\n\t}\r\n\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tQMap<unsigned int, QSet<QString>> m_connectionsFrom;\r\n\tQMap<unsigned int, QSet<QString>> m_connectionsTo;\r\n};\r\n"
  },
  {
    "path": "src/base/regionmap.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"regionmap.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/region.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QQueue>\r\nRegionMap::RegionMap( World* parent ) :\r\n\tm_world( parent )\r\n{\r\n}\r\n\r\nRegionMap::~RegionMap()\r\n{\r\n}\r\n\r\nvoid RegionMap::clear()\r\n{\r\n\tm_regionMap.clear();\r\n\tm_regions.clear();\r\n\r\n\tm_dimX = 0;\r\n\tm_dimY = 0;\r\n\tm_dimZ = 0;\r\n\r\n\tm_initialized = false;\r\n}\r\n\r\nunsigned int RegionMap::regionID( unsigned int tileID )\r\n{\r\n\treturn m_regions[m_regionMap[tileID]].id();\r\n}\r\n\r\nunsigned int RegionMap::regionID( const Position& pos )\r\n{\r\n\treturn m_regions[m_regionMap[index( pos )]].id();\r\n}\r\n\r\nRegion& RegionMap::region( const Position& pos )\r\n{\r\n\treturn m_regions[m_regionMap[index( pos )]];\r\n}\r\n\r\nRegion& RegionMap::region( unsigned int id )\r\n{\r\n\treturn m_regions[id];\r\n}\r\n\r\nvoid RegionMap::initRegions()\r\n{\r\n\tm_dimX = Global::dimX;\r\n\tm_dimY = Global::dimY;\r\n\tm_dimZ = Global::dimZ;\r\n\r\n\tm_regions.clear();\r\n\tm_regions.emplace_back( 0 );\r\n\tm_regionMap.clear();\r\n\tm_regionMap.resize( m_world->world().size() );\r\n\tfor ( auto i = 0; i < m_regionMap.size(); ++i )\r\n\t\tm_regionMap[i] = 0;\r\n\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\tfor ( int z = 1; z < m_dimZ - 1; ++z )\r\n\t{\r\n\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tTile& tile = m_world->getTile( x, y, z );\r\n\t\t\t\tif ( ( tile.flags & TileFlag::TF_WALKABLE && !( tile.flags & TileFlag::TF_NOPASS ) ) && ( m_regionMap[index( x, y, z )] == 0 ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t////qDebug() << \"found new tile without region\";\r\n\t\t\t\t\t// assign new region numer\r\n\t\t\t\t\tunsigned int id               = static_cast<unsigned int>( m_regions.size() );\r\n\t\t\t\t\tm_regionMap[index( x, y, z )] = id;\r\n\t\t\t\t\tm_regions.emplace_back( id );\r\n\r\n\t\t\t\t\tfloodFill( 0, id, x, y, z );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tunsigned int currentIndex = 0;\r\n\tfor ( int z = 1; z < m_dimZ - 1; ++z )\r\n\t{\r\n\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tTile& tile = m_world->getTile( x, y, z );\r\n\r\n\t\t\t\tif ( tile.wallType & WallType::WT_STAIR || tile.wallType & WallType::WT_SCAFFOLD || tile.wallType & WallType::WT_RAMP )\r\n\t\t\t\t{\r\n\t\t\t\t\tcurrentIndex = index( x, y, z );\r\n\r\n\t\t\t\t\tstd::vector<Position> cons = connectedNeighborsUp( Position( x, y, z ) );\r\n\t\t\t\t\tPosition curPos( x, y, z );\r\n\t\t\t\t\tfor ( auto con : cons )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// insert into this region the region above\r\n\t\t\t\t\t\tm_regions[m_regionMap[currentIndex]].addConnectionTo( regionID( con ), curPos );\r\n\t\t\t\t\t\t// insert into the region above this region\r\n\t\t\t\t\t\tm_regions[m_regionMap[index( con )]].addConnectionFrom( m_regions[m_regionMap[currentIndex]].id(), curPos );\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\tqDebug() << \"initialized \" << m_regions.size() << \" regions in \" + QString::number( timer.elapsed() ) + \" ms\";\r\n\tm_initialized = true;\r\n}\r\n\r\nvoid RegionMap::mergeRegions( const Position& pos, unsigned int oldRegionID, unsigned int newRegionID )\r\n{\r\n\tfloodFill( oldRegionID, newRegionID, pos.x, pos.y, pos.z );\r\n\r\n\tRegion& oldRegion = m_regions[oldRegionID];\r\n\tRegion& newRegion = m_regions[newRegionID];\r\n\r\n\tfor ( auto con : oldRegion.connectionSetTo().keys() )\r\n\t{\r\n\t\tfor ( auto conPos : oldRegion.connectionSetTo().value( con ) )\r\n\t\t{\r\n\t\t\tnewRegion.addConnectionTo( con, conPos );\r\n\t\t\tm_regions[con].addConnectionFrom( newRegionID, conPos );\r\n\t\t}\r\n\t\tm_regions[con].removeAllConnectionsFrom( oldRegionID );\r\n\t}\r\n\r\n\tfor ( auto con : oldRegion.connectionSetFrom().keys() )\r\n\t{\r\n\t\tfor ( auto conPos : oldRegion.connectionSetFrom().value( con ) )\r\n\t\t{\r\n\t\t\tnewRegion.addConnectionFrom( con, conPos );\r\n\t\t\tm_regions[con].addConnectionTo( newRegionID, Position( conPos ) );\r\n\t\t}\r\n\t\tm_regions[con].removeAllConnectionsTo( oldRegionID );\r\n\t}\r\n}\r\n\r\nvoid RegionMap::splitRegions( unsigned int fromRegionID, unsigned int intoRegionID )\r\n{\r\n\t// Purge cache in case of split\r\n\tm_cachedConnections.clear();\r\n\r\n\tRegion& fromRegion = m_regions[fromRegionID];\r\n\tRegion& intoRegion = m_regions[intoRegionID];\r\n\r\n\tauto oldConSetTo = fromRegion.connectionSetTo();\r\n\r\n\tfromRegion.clearConnectionsTo();\r\n\tfor ( auto con : oldConSetTo.keys() )\r\n\t{\r\n\t\tfor ( auto conPosString : oldConSetTo.value( con ) )\r\n\t\t{\r\n\t\t\t//check if location is in new region or still in old region\r\n\t\t\tPosition conPos( conPosString );\r\n\t\t\tif ( m_regionMap[index( conPos )] == fromRegionID )\r\n\t\t\t{\r\n\t\t\t\tfromRegion.addConnectionTo( con, conPos );\r\n\t\t\t\t//m_regions[con].addConnectionFrom( fromRegionID, conPos );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tintoRegion.addConnectionTo( con, conPos );\r\n\t\t\t\tm_regions[con].removeConnectionFrom( fromRegionID, conPos );\r\n\t\t\t\tm_regions[con].addConnectionFrom( intoRegionID, conPos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tauto oldConSet = fromRegion.connectionSetFrom();\r\n\tfromRegion.clearConnectionsFrom();\r\n\tfor ( auto downRegionID : oldConSet.keys() )\r\n\t{\r\n\t\tRegion& downRegion = m_regions[downRegionID];\r\n\t\t// get list of position to the old region that is split\r\n\t\tauto connectionsTo = downRegion.connectionsToRegion( fromRegionID );\r\n\t\t// delete the connection set down there\r\n\t\tdownRegion.removeAllConnectionsTo( fromRegionID );\r\n\t\t// iterate over the connections and set them again\r\n\r\n\t\tfor ( auto connectionPos : connectionsTo )\r\n\t\t{\r\n\t\t\tPosition curPos( connectionPos );\r\n\t\t\tTile& tile = m_world->getTile( curPos );\r\n\r\n\t\t\tif ( tile.wallType & WallType::WT_STAIR || tile.wallType & WallType::WT_SCAFFOLD || tile.wallType & WallType::WT_RAMP )\r\n\t\t\t{\r\n\t\t\t\tstd::vector<Position> cons = connectedNeighborsUp( curPos );\r\n\r\n\t\t\t\tfor ( auto con : cons )\r\n\t\t\t\t{\r\n\t\t\t\t\t// insert into this region the region above\r\n\t\t\t\t\tdownRegion.addConnectionTo( regionID( con ), curPos );\r\n\t\t\t\t\t// insert into the region above this region\r\n\t\t\t\t\tm_regions[m_regionMap[index( con )]].addConnectionFrom( downRegionID, curPos );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int RegionMap::index( int x, int y, int z )\r\n{\r\n\treturn x + y * m_dimX + z * m_dimX * m_dimY;\r\n}\r\n\r\nunsigned int RegionMap::index( const Position& pos )\r\n{\r\n\treturn pos.x + pos.y * m_dimX + pos.z * m_dimX * m_dimY;\r\n}\r\n\r\nvoid RegionMap::floodFill( unsigned int oldID, unsigned int newID, int x_, int y_, int z_ )\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tQQueue<Position> floodQueue;\r\n\tPosition startPos( x_, y_, z_ );\r\n\tfloodQueue.enqueue( startPos );\r\n\t//qDebug() << \"start flood fill:\" << id << startPos.toString();\r\n\twhile ( !floodQueue.isEmpty() )\r\n\t{\r\n\t\tPosition p0 = floodQueue.dequeue();\r\n\t\tm_world->addToUpdateList( p0 );\r\n\t\t//qDebug() << \"continue with \" << p0.toString();\r\n\t\tunsigned int currentIndex = index( p0.x, p0.y, p0.z );\r\n\r\n\t\tbool prevLineAdded = false;\r\n\t\tbool nextLineAdded = false;\r\n\t\tfor ( int x = p0.x; x < m_dimX - 1; ++x )\r\n\t\t{\r\n\t\t\tif ( m_world->getTile( currentIndex ).flags & TileFlag::TF_WALKABLE && !( m_world->getTile( currentIndex ).flags & TileFlag::TF_NOPASS ) )\r\n\t\t\t{\r\n\t\t\t\tm_regionMap[currentIndex] = newID;\r\n\t\t\t\tm_world->addToUpdateList( Position( x, p0.y, p0.z ) );\r\n\r\n\t\t\t\tif ( ( m_world->getTile( currentIndex - m_dimX ).flags & TileFlag::TF_WALKABLE && !( m_world->getTile( currentIndex - m_dimX ).flags & TileFlag::TF_NOPASS ) ) && ( m_regionMap[currentIndex - m_dimX] == oldID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !prevLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_regionMap[currentIndex - m_dimX] = newID;\r\n\t\t\t\t\t\tPosition pos( x, p0.y - 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tprevLineAdded = true;\r\n\t\t\t\t\t\t//qDebug() << \"add to queue: \" << pos.toString();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprevLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( m_world->getTile( currentIndex + m_dimX ).flags & TileFlag::TF_WALKABLE && !( m_world->getTile( currentIndex + m_dimX ).flags & TileFlag::TF_NOPASS ) ) && ( m_regionMap[currentIndex + m_dimX] == oldID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !nextLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_regionMap[currentIndex + m_dimX] = newID;\r\n\t\t\t\t\t\tPosition pos( x, p0.y + 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tnextLineAdded = true;\r\n\t\t\t\t\t\t//qDebug() << \"add to queue: \" << pos.toString();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tnextLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t++currentIndex;\r\n\t\t}\r\n\r\n\t\tcurrentIndex  = index( p0.x, p0.y, p0.z );\r\n\t\tprevLineAdded = false;\r\n\t\tnextLineAdded = false;\r\n\t\tfor ( int x = p0.x; x > 0; --x )\r\n\t\t{\r\n\t\t\tif ( m_world->getTile( currentIndex ).flags & TileFlag::TF_WALKABLE && !( m_world->getTile( currentIndex ).flags & TileFlag::TF_NOPASS ) )\r\n\t\t\t{\r\n\t\t\t\tm_regionMap[currentIndex] = newID;\r\n\t\t\t\tm_world->addToUpdateList( Position( x, p0.y, p0.z ) );\r\n\r\n\t\t\t\tif ( ( m_world->getTile( currentIndex - m_dimX ).flags & TileFlag::TF_WALKABLE && !( m_world->getTile( currentIndex - m_dimX ).flags & TileFlag::TF_NOPASS ) ) && ( m_regionMap[currentIndex - m_dimX] == oldID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !prevLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_regionMap[currentIndex - m_dimX] = newID;\r\n\t\t\t\t\t\tPosition pos( x, p0.y - 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tprevLineAdded = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprevLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t\tif ( ( m_world->getTile( currentIndex + m_dimX ).flags & TileFlag::TF_WALKABLE && !( m_world->getTile( currentIndex + m_dimX ).flags & TileFlag::TF_NOPASS ) ) && ( m_regionMap[currentIndex + m_dimX] == oldID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !nextLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_regionMap[currentIndex + m_dimX] = newID;\r\n\t\t\t\t\t\tPosition pos( x, p0.y + 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tnextLineAdded = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tnextLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t--currentIndex;\r\n\t\t}\r\n\t}\r\n\t//if( z_ == 100 ) qDebug() << \"initialized region 100 in \" +  QString::number( timer.elapsed() ) + \" ms\";\r\n}\r\n\r\nvoid RegionMap::updatePosition( const Position& pos )\r\n{\r\n\tif ( m_initialized )\r\n\t{\r\n\t\t//qDebug() << \"update position \" << pos.toString();\r\n\t\tif ( m_world->isWalkableGnome( pos ) )\r\n\t\t{\r\n\t\t\tupdatePositionSetWalkable( pos );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tupdatePositionClearWalkable( pos );\r\n\t\t}\r\n\t\tupdateConnectedRegions( pos );\r\n\t}\r\n}\r\n\r\nvoid RegionMap::updatePositionClearWalkable( const Position& pos )\r\n{\r\n\tif ( m_initialized )\r\n\t{\r\n\t\t// remove tile from region\r\n\t\tif ( m_regionMap[index( pos )] != 0 )\r\n\t\t{\r\n\t\t\t// check for possible split of regions\r\n\t\t\tm_regionMap[index( pos )] = 0;\r\n\r\n\t\t\tbool isSplit = checkSplit( pos );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RegionMap::updatePositionSetWalkable( const Position& pos )\r\n{\r\n\tif ( m_initialized )\r\n\t{\r\n\t\tif ( m_regionMap[index( pos )] == 0 )\r\n\t\t{\r\n\t\t\t// check if neighboring tiles are walkable, take their region\r\n\t\t\tunsigned int region1 = m_regionMap[index( pos.x - 1, pos.y, pos.z )];\r\n\t\t\tunsigned int region2 = m_regionMap[index( pos.x + 1, pos.y, pos.z )];\r\n\t\t\tunsigned int region3 = m_regionMap[index( pos.x, pos.y - 1, pos.z )];\r\n\t\t\tunsigned int region4 = m_regionMap[index( pos.x, pos.y + 1, pos.z )];\r\n\r\n\t\t\tunsigned int region = region1;\r\n\t\t\tif ( ( region == 0 ) || ( ( region2 != 0 ) && ( region2 < region ) ) )\r\n\t\t\t\tregion = region2;\r\n\t\t\tif ( ( region == 0 ) || ( ( region3 != 0 ) && ( region3 < region ) ) )\r\n\t\t\t\tregion = region3;\r\n\t\t\tif ( ( region == 0 ) || ( ( region4 != 0 ) && ( region4 < region ) ) )\r\n\t\t\t\tregion = region4;\r\n\r\n\t\t\tif ( region == 0 )\r\n\t\t\t{\r\n\t\t\t\t// if no neighbor with region, start new region\r\n\t\t\t\tunsigned int id           = static_cast<unsigned int>( m_regions.size() );\r\n\t\t\t\tm_regionMap[index( pos )] = id;\r\n\t\t\t\tm_regions.emplace_back( id );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_regionMap[index( pos )] = region;\r\n\r\n\t\t\t\t// if neighbors have different regions -> merge\r\n\r\n\t\t\t\tif ( region1 && ( region1 != region ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmergeRegions( pos, region1, region );\r\n\t\t\t\t}\r\n\t\t\t\tif ( region2 && ( region2 != region ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmergeRegions( pos, region2, region );\r\n\t\t\t\t}\r\n\t\t\t\tif ( region3 && ( region3 != region ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmergeRegions( pos, region3, region );\r\n\t\t\t\t}\r\n\t\t\t\tif ( region4 && ( region4 != region ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmergeRegions( pos, region4, region );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RegionMap::updateConnectedRegions( const Position& pos )\r\n{\r\n\tif ( m_initialized )\r\n\t{\r\n\t\t//qDebug() << \"update connected regions \" << pos.toString();\r\n\r\n\t\tunsigned int currentIndex = index( pos );\r\n\r\n\t\tTile& tile = m_world->getTile( pos );\r\n\r\n\t\tif ( (bool)( tile.wallType & ( WallType::WT_STAIR | WallType::WT_SCAFFOLD | WallType::WT_RAMP ) ) )\r\n\t\t{\r\n\t\t\tstd::vector<Position> cons = connectedNeighborsUp( pos );\r\n\t\t\tfor ( auto con : cons )\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"set connection at pos \" << con.toString() << \" regions \" << m_regionMap[ currentIndex] << \" to \" << m_regionMap[ index(con) ];\r\n\t\t\t\t// insert into this region the region above\r\n\t\t\t\tm_regions[m_regionMap[currentIndex]].addConnectionTo( m_regions[m_regionMap[index( con )]].id(), pos );\r\n\t\t\t\t// insert into the region above this region\r\n\t\t\t\tm_regions[m_regionMap[index( con )]].addConnectionFrom( m_regions[m_regionMap[currentIndex]].id(), pos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool RegionMap::checkSplit( const Position& pos )\r\n{\r\n\tunsigned int region1 = m_regionMap[index( pos.x - 1, pos.y, pos.z )];\r\n\tunsigned int region2 = m_regionMap[index( pos.x + 1, pos.y, pos.z )];\r\n\tunsigned int region3 = m_regionMap[index( pos.x, pos.y - 1, pos.z )];\r\n\tunsigned int region4 = m_regionMap[index( pos.x, pos.y + 1, pos.z )];\r\n\r\n\tunsigned int between13 = m_regionMap[index( pos.x - 1, pos.y - 1, pos.z )];\r\n\tunsigned int between14 = m_regionMap[index( pos.x - 1, pos.y + 1, pos.z )];\r\n\r\n\tunsigned int between23 = m_regionMap[index( pos.x + 1, pos.y - 1, pos.z )];\r\n\tunsigned int between24 = m_regionMap[index( pos.x + 1, pos.y + 1, pos.z )];\r\n\r\n\tif ( region1 )\r\n\t{\r\n\t\tbool split = false;\r\n\t\tif ( region1 == region2 )\r\n\t\t{\r\n\t\t\t//oposite\r\n\t\t\tif ( ( region1 == between13 ) && ( region1 == region3 ) && ( region1 == between23 ) ||\r\n\t\t\t\t ( region1 == between14 ) && ( region1 == region4 ) && ( region1 == between24 ) )\r\n\t\t\t{\r\n\t\t\t\t//still connected\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"check split flood\";\r\n\t\t\t\tsplit = checkSplitFlood( Position( pos.x - 1, pos.y, pos.z ), Position( pos.x + 1, pos.y, pos.z ), region1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( region1 == region3 )\r\n\t\t{\r\n\t\t\t//quick check is the corner tile between them still connected?\r\n\t\t\tif ( between13 == region1 )\r\n\t\t\t{\r\n\t\t\t\t//still connected\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"check split flood\";\r\n\t\t\t\tsplit = checkSplitFlood( Position( pos.x - 1, pos.y, pos.z ), Position( pos.x, pos.y - 1, pos.z ), region1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( region1 == region4 )\r\n\t\t{\r\n\t\t\t//quick check is the corner tile between them still connected?\r\n\t\t\tif ( between23 == region1 )\r\n\t\t\t{\r\n\t\t\t\t//still connected\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"check split flood\";\r\n\t\t\t\tsplit = checkSplitFlood( Position( pos.x - 1, pos.y, pos.z ), Position( pos.x, pos.y + 1, pos.z ), region1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( split )\r\n\t\t{\r\n\t\t\tunsigned int id                                           = static_cast<unsigned int>( m_regions.size() );\r\n\t\t\tm_regionMap[index( Position( pos.x - 1, pos.y, pos.z ) )] = id;\r\n\t\t\tm_regions.emplace_back( id );\r\n\t\t\t//qDebug() << \"flood fill 2 : \" << Position( pos.x-1, pos.y, pos.z ).toString();\r\n\t\t\tfloodFill( region1, id, pos.x - 1, pos.y, pos.z );\r\n\t\t\tsplitRegions( region1, id );\r\n\t\t}\r\n\t}\r\n\tregion2 = m_regionMap[index( pos.x + 1, pos.y, pos.z )];\r\n\tregion3 = m_regionMap[index( pos.x, pos.y - 1, pos.z )];\r\n\tregion4 = m_regionMap[index( pos.x, pos.y + 1, pos.z )];\r\n\tif ( region2 )\r\n\t{\r\n\t\tbool split = false;\r\n\t\tif ( region2 == region3 )\r\n\t\t{\r\n\t\t\t//quick check is the corner tile between them still connected?\r\n\t\t\tif ( between23 == region2 )\r\n\t\t\t{\r\n\t\t\t\t//still connected\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"check split flood\";\r\n\t\t\t\tsplit = checkSplitFlood( Position( pos.x + 1, pos.y, pos.z ), Position( pos.x, pos.y - 1, pos.z ), region2 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( region2 == region4 )\r\n\t\t{\r\n\t\t\t//quick check is the corner tile between them still connected?\r\n\t\t\tif ( between24 == region2 )\r\n\t\t\t{\r\n\t\t\t\t//still connected\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"check split flood\";\r\n\t\t\t\tsplit = checkSplitFlood( Position( pos.x + 1, pos.y, pos.z ), Position( pos.x, pos.y + 1, pos.z ), region2 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( split )\r\n\t\t{\r\n\t\t\tunsigned int id                                           = static_cast<unsigned int>( m_regions.size() );\r\n\t\t\tm_regionMap[index( Position( pos.x + 1, pos.y, pos.z ) )] = id;\r\n\t\t\tRegion r( id );\r\n\t\t\tm_regions.emplace_back( id );\r\n\t\t\t//qDebug() << \"flood fill 2 : \" << Position( pos.x+1, pos.y, pos.z ).toString();\r\n\t\t\tfloodFill( region2, id, pos.x + 1, pos.y, pos.z );\r\n\t\t\tsplitRegions( region2, id );\r\n\t\t}\r\n\t}\r\n\tregion1 = m_regionMap[index( pos.x - 1, pos.y, pos.z )];\r\n\tregion2 = m_regionMap[index( pos.x + 1, pos.y, pos.z )];\r\n\tregion3 = m_regionMap[index( pos.x, pos.y - 1, pos.z )];\r\n\tregion4 = m_regionMap[index( pos.x, pos.y + 1, pos.z )];\r\n\r\n\tbetween13 = m_regionMap[index( pos.x - 1, pos.y - 1, pos.z )];\r\n\tbetween14 = m_regionMap[index( pos.x - 1, pos.y + 1, pos.z )];\r\n\r\n\tbetween23 = m_regionMap[index( pos.x + 1, pos.y - 1, pos.z )];\r\n\tbetween24 = m_regionMap[index( pos.x + 1, pos.y + 1, pos.z )];\r\n\tif ( region3 )\r\n\t{\r\n\t\tif ( region3 == region4 )\r\n\t\t{\r\n\t\t\t//oposite\r\n\t\t\tif ( ( region3 == between13 ) && ( region3 == region1 ) && ( region3 == between14 ) ||\r\n\t\t\t\t ( region3 == between23 ) && ( region3 == region2 ) && ( region3 == between24 ) )\r\n\t\t\t{\r\n\t\t\t\t//still connected\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"check split flood\";\r\n\t\t\t\tif ( checkSplitFlood( Position( pos.x, pos.y - 1, pos.z ), Position( pos.x, pos.y + 1, pos.z ), region3 ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int id                                           = static_cast<unsigned int>( m_regions.size() );\r\n\t\t\t\t\tm_regionMap[index( Position( pos.x, pos.y - 1, pos.z ) )] = id;\r\n\t\t\t\t\tm_regions.emplace_back( id );\r\n\t\t\t\t\t//qDebug() << \"flood fill 2 : \" << Position( pos.x, pos.y-1, pos.z ).toString();\r\n\t\t\t\t\tfloodFill( region3, id, pos.x, pos.y - 1, pos.z );\r\n\t\t\t\t\tsplitRegions( region3, id );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RegionMap::checkSplitFlood( const Position& pos, const Position& pos2, unsigned int regionID )\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tQQueue<Position> floodQueue;\r\n\r\n\tQVector<bool> visited( m_dimX * m_dimX, false );\r\n\r\n\tfloodQueue.enqueue( pos );\r\n\t//qDebug() << \"start flood fill:\" << id << startPos.toString();\r\n\twhile ( !floodQueue.isEmpty() )\r\n\t{\r\n\t\tPosition p0 = floodQueue.dequeue();\r\n\t\tif ( p0 == pos2 )\r\n\t\t{\r\n\t\t\t//found target pos, no split happened;\r\n\t\t\t//qDebug() << \"found target in \" +  QString::number( timer.elapsed() ) + \" ms, no split\";\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t//qDebug() << \"continue with \" << p0.toString();\r\n\t\tunsigned int currentIndex     = index( p0.x, p0.y, p0.z );\r\n\t\tvisited[p0.x + p0.y * m_dimX] = true;\r\n\r\n\t\tbool prevLineAdded = false;\r\n\t\tbool nextLineAdded = false;\r\n\t\tfor ( int x = p0.x; x < m_dimX - 1; ++x )\r\n\t\t{\r\n\t\t\tif ( m_regionMap[currentIndex] == regionID )\r\n\t\t\t{\r\n\t\t\t\tif ( m_regionMap[currentIndex - m_dimX] == regionID && !visited[x + ( p0.y - 1 ) * m_dimX] )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !prevLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvisited[x + ( p0.y - 1 ) * m_dimX] = true;\r\n\t\t\t\t\t\tPosition pos( x, p0.y - 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tprevLineAdded = true;\r\n\t\t\t\t\t\t//qDebug() << \"add to queue: \" << pos.toString();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprevLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t\tif ( m_regionMap[currentIndex + m_dimX] == regionID && !visited[x + ( p0.y + 1 ) * m_dimX] )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !nextLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvisited[x + ( p0.y + 1 ) * m_dimX] = true;\r\n\t\t\t\t\t\tPosition pos( x, p0.y + 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tnextLineAdded = true;\r\n\t\t\t\t\t\t//qDebug() << \"add to queue: \" << pos.toString();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tnextLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t++currentIndex;\r\n\t\t}\r\n\r\n\t\tcurrentIndex  = index( p0.x, p0.y, p0.z );\r\n\t\tprevLineAdded = false;\r\n\t\tnextLineAdded = false;\r\n\t\tfor ( int x = p0.x; x > 0; --x )\r\n\t\t{\r\n\t\t\tif ( m_regionMap[currentIndex] == regionID )\r\n\t\t\t{\r\n\t\t\t\tif ( m_regionMap[currentIndex - m_dimX] == regionID && !visited[x + ( p0.y - 1 ) * m_dimX] )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !prevLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvisited[x + ( p0.y - 1 ) * m_dimX] = true;\r\n\t\t\t\t\t\tPosition pos( x, p0.y - 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tprevLineAdded = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tprevLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t\tif ( m_regionMap[currentIndex + m_dimX] == regionID && !visited[x + ( p0.y + 1 ) * m_dimX] )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !nextLineAdded )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tvisited[x + ( p0.y + 1 ) * m_dimX] = true;\r\n\t\t\t\t\t\tPosition pos( x, p0.y + 1, p0.z );\r\n\t\t\t\t\t\tfloodQueue.enqueue( pos );\r\n\t\t\t\t\t\tnextLineAdded = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tnextLineAdded = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t--currentIndex;\r\n\t\t}\r\n\t}\r\n\t//qDebug() << \"check took \" +  QString::number( timer.elapsed() ) + \" ms, split happened\";\r\n\treturn true;\r\n}\r\n\r\nbool RegionMap::checkConnectedRegions( unsigned int start, unsigned int goal )\r\n{\r\n\tif ( start == goal )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif ( start > goal )\r\n\t{\r\n\t\tstd::swap( start, goal );\r\n\t}\r\n\tconst auto it = m_cachedConnections.find( std::make_pair( start, goal ) );\r\n\tif ( it != m_cachedConnections.end() )\r\n\t{\r\n\t\treturn it->second;\r\n\t}\r\n\t//qDebug() << \"check connection between \" << start << goal;\r\n\tQQueue<unsigned int> floodQueue;\r\n\tQSet<unsigned int> visited;\r\n\tfor ( auto con : region( start ).connectionsTo() )\r\n\t{\r\n\t\tfloodQueue.enqueue( con );\r\n\t\tvisited.insert( con );\r\n\t}\r\n\tfor ( auto con : region( start ).connectionsFrom() )\r\n\t{\r\n\t\tfloodQueue.enqueue( con );\r\n\t\tvisited.insert( con );\r\n\t}\r\n\tvisited.insert( start );\r\n\r\n\tbool found = false;\r\n\twhile ( !floodQueue.isEmpty() && !found )\r\n\t{\r\n\t\tunsigned int currentRegionID = floodQueue.dequeue();\r\n\t\tif ( currentRegionID == goal )\r\n\t\t{\r\n\t\t\tm_cachedConnections.insert( { std::make_pair( start, goal ), true } );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tfor ( auto con : region( currentRegionID ).connectionsTo() )\r\n\t\t{\r\n\t\t\tif ( con == goal )\r\n\t\t\t{\r\n\t\t\t\tm_cachedConnections.insert( { std::make_pair( start, goal ), true } );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif ( !visited.contains( con ) )\r\n\t\t\t{\r\n\t\t\t\tfloodQueue.enqueue( con );\r\n\t\t\t\tvisited.insert( con );\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( auto con : region( currentRegionID ).connectionsFrom() )\r\n\t\t{\r\n\t\t\tif ( con == goal )\r\n\t\t\t{\r\n\t\t\t\tm_cachedConnections.insert( { std::make_pair( start, goal ), true } );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tif ( !visited.contains( con ) )\r\n\t\t\t{\r\n\t\t\t\tfloodQueue.enqueue( con );\r\n\t\t\t\tvisited.insert( con );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_cachedConnections.insert( { std::make_pair( start, goal ), false } );\r\n\t//qDebug() << \"no connection\";\r\n\treturn false;\r\n}\r\n\r\nbool RegionMap::checkConnectedRegions( const Position& start, const Position& goal )\r\n{\r\n\t/*\r\n\tQElapsedTimer et;\r\n\tet.start();\r\n\tbool connected = checkConnectedRegions( regionID( start), regionID( goal ) );\r\n\tqDebug() << \"check connected regions took \" << et.elapsed() << \" ms\";\r\n\treturn connected;\r\n\t*/\r\n\treturn checkConnectedRegions( regionID( start ), regionID( goal ) );\r\n}\r\n\r\n\r\nstd::vector<Position> RegionMap::connectedNeighborsUp( const Position& pos )\r\n{\r\n\tstd::vector<Position> out;\r\n\r\n\tTile& tile = m_world->getTile( pos );\r\n\r\n\tif ( (bool)( tile.wallType & ( WT_STAIR | WT_SCAFFOLD ) ) )\r\n\t{\r\n\t\tout.push_back( pos.aboveOf() );\r\n\t}\r\n\tif ( (bool)( tile.wallType & ( WT_RAMP ) ) )\r\n\t{\r\n\t\tauto above = pos.aboveOf();\r\n\r\n\t\tTile& nt = m_world->getTile( above.northOf() );\r\n\t\tif ( nt.flags & TileFlag::TF_WALKABLE )\r\n\t\t{\r\n\t\t\tout.push_back( above.northOf() );\r\n\t\t}\r\n\t\tTile& et = m_world->getTile( above.eastOf() );\r\n\t\tif ( et.flags & TileFlag::TF_WALKABLE )\r\n\t\t{\r\n\t\t\tout.push_back( above.eastOf() );\r\n\t\t}\r\n\t\tTile& st = m_world->getTile( above.southOf() );\r\n\t\tif ( st.flags & TileFlag::TF_WALKABLE )\r\n\t\t{\r\n\t\t\tout.push_back( above.southOf() );\r\n\t\t}\r\n\t\tTile& wt = m_world->getTile( above.westOf() );\r\n\t\tif ( wt.flags & TileFlag::TF_WALKABLE )\r\n\t\t{\r\n\t\t\tout.push_back( above.westOf() );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}"
  },
  {
    "path": "src/base/regionmap.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QSet>\r\n\r\n#include <vector>\r\n\r\nstruct Tile;\r\nclass Region;\r\nclass World;\r\n\r\nclass RegionMap\r\n{\r\npublic:\r\n\tRegionMap( World* parent );\r\n\t~RegionMap();\r\n\r\n\tvoid clear();\r\n\r\n\tunsigned int regionID( const Position& pos );\r\n\tRegion& region( const Position& pos );\r\n\tRegion& region( unsigned int id );\r\n\r\n\tvoid initRegions();\r\n\tvoid mergeRegions( const Position& pos, unsigned int region, unsigned int intoRegion );\r\n\tvoid splitRegions( unsigned int region, unsigned int intoRegion );\r\n\r\n\tunsigned int regionID( unsigned int tileID );\r\n\r\n\tvoid updatePosition( const Position& pos );\r\n\tvoid updateConnectedRegions( const Position& pos );\r\n\r\n\tbool checkConnectedRegions( unsigned int start, unsigned int goal );\r\n\tbool checkConnectedRegions( const Position& start, const Position& goal );\r\n\r\nprivate:\r\n\tWorld* m_world = nullptr;\r\n\r\n\tstd::vector<unsigned int> m_regionMap;\r\n\tstd::vector<Region> m_regions;\r\n\r\n\tstruct mHash\r\n\t{\r\n\t\tinline std::size_t operator()( const std::pair<unsigned int, unsigned int>& s ) const noexcept\r\n\t\t{\r\n\t\t\treturn std::hash<std::size_t> {}( static_cast<std::size_t>( s.first ) ^ ( static_cast<std::size_t>( s.second ) << 32 ) );\r\n\t\t}\r\n\t};\r\n\tstd::unordered_map<std::pair<unsigned int, unsigned int>, bool, mHash> m_cachedConnections;\r\n\r\n\tint m_dimX = 0;\r\n\tint m_dimY = 0;\r\n\tint m_dimZ = 0;\r\n\r\n\tbool m_initialized = false;\r\n\r\n\tunsigned int index( int x, int y, int z );\r\n\tunsigned int index( const Position& pos );\r\n\r\n\tvoid floodFill( unsigned int oldID, unsigned int newID, int x, int y, int z );\r\n\r\n\tbool checkSplit( const Position& pos );\r\n\tbool checkSplitFlood( const Position& pos, const Position& pos2, unsigned int regionID );\r\n\r\n\tvoid updatePositionClearWalkable( const Position& pos );\r\n\tvoid updatePositionSetWalkable( const Position& pos );\r\n\r\n\tstd::vector<Position> connectedNeighborsUp( const Position& pos );\r\n};\r\n"
  },
  {
    "path": "src/base/selection.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"selection.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n#include <QJsonValue>\r\n\r\nSelection::Selection( Game* game ) :\r\n\tg( game ),\r\n\tm_rotation( 0 ),\r\n\tm_firstClicked( false ),\r\n\tm_action( \"\" ),\r\n\tm_debug( false ),\r\n\tQObject( game )\r\n{\r\n\tm_selectionSize.first  = 0;\r\n\tm_selectionSize.second = 0;\r\n\r\n\tm_reqMap.insert( \"none\", SEL_NONE );\r\n\tm_reqMap.insert( \"Floor\", SEL_FLOOR );\r\n\tm_reqMap.insert( \"FloorOrScaffold\", SEL_FLOOR_OR_SCAFFOLD );\r\n\tm_reqMap.insert( \"Wall\", SEL_WALL );\r\n\tm_reqMap.insert( \"MineableWall\", SEL_MINEABLE_WALL );\r\n\tm_reqMap.insert( \"Construction\", SEL_CONSTRUCTION );\r\n\tm_reqMap.insert( \"Job\", SEL_JOB );\r\n\tm_reqMap.insert( \"Designation\", SEL_DESIGNATION );\r\n\tm_reqMap.insert( \"Stockpile\", SEL_STOCKPILE );\r\n\tm_reqMap.insert( \"Room\", SEL_ROOM );\r\n\tm_reqMap.insert( \"AllowBell\", SEL_ALLOW_BELL );\r\n\tm_reqMap.insert( \"AllowFurniture\", SEL_ALLOW_FURNITURE );\r\n\tm_reqMap.insert( \"Pasture\", SEL_PASTURE );\r\n\tm_reqMap.insert( \"Walkable\", SEL_WALKABLE );\r\n\tm_reqMap.insert( \"Mechanism\", SEL_MECHANISM );\r\n\tm_reqMap.insert( \"GearBox\", SEL_GEARBOX );\r\n\r\n\tm_reqMap.insert( \"Stairs\", SEL_STAIRS );\r\n\tm_reqMap.insert( \"StairsTop\", SEL_STAIRSTOP );\r\n\tm_reqMap.insert( \"Ramp\", SEL_RAMP );\r\n\tm_reqMap.insert( \"RampTop\", SEL_RAMPTOP );\r\n\r\n\tm_reqMap.insert( \"Soil\", SEL_SOIL );\r\n\tm_reqMap.insert( \"Tree\", SEL_TREE );\r\n\tm_reqMap.insert( \"Plant\", SEL_PLANT );\r\n\tm_reqMap.insert( \"TreeCLip\", SEL_TREECLIP );\r\n\tm_reqMap.insert( \"PlantWithFruit\", SEL_PLANT_WITH_FRUIT );\r\n\tm_reqMap.insert( \"TreeInRange\", SEL_TREE_IN_RANGE );\r\n\r\n\tm_reqMap.insert( \"AnyWall\", SEL_ANYWALL );\r\n}\r\n\r\nSelection::~Selection()\r\n{\r\n}\r\n\r\nQVariantMap Selection::serialize()\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"Rot\", m_rotation );\r\n\tout.insert( \"Pos\", m_firstClick.toString() );\r\n\tout.insert( \"Action\", m_action );\r\n\tout.insert( \"Item\", m_item );\r\n\tout.insert( \"Mats\", m_materials.join( '_' ) );\r\n\r\n\tQVariantList spl; // selection position list\r\n\tfor ( auto s : m_selection )\r\n\t{\r\n\t\tspl.push_back( s.first.toString() );\r\n\t}\r\n\tout.insert( \"Selection\", spl );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Selection::clear()\r\n{\r\n\tm_action = \"\";\r\n\tm_selection.clear();\r\n\tm_firstClicked         = false;\r\n\tm_selectionSize.first  = 0;\r\n\tm_selectionSize.second = 0;\r\n\tm_changed              = true;\r\n\tm_isFloor              = false;\r\n\tm_isMulti              = false;\r\n\tm_tileCheckList.clear();\r\n\tm_item = \"\";\r\n\tm_materials.clear();\r\n\tm_canRotate = false;\r\n\r\n\temit signalActionChanged( \"\" );\r\n}\r\n\r\nvoid Selection::rotate()\r\n{\r\n\t++m_rotation;\r\n\tif ( m_rotation > 3 )\r\n\t\tm_rotation = 0;\r\n\tm_changed = true;\r\n}\r\n\r\nbool Selection::leftClick( Position& pos, bool shift, bool ctrl )\r\n{\r\n\tif ( !m_firstClicked )\r\n\t{\r\n\t\t// first click\r\n\t\tm_firstClick          = pos;\r\n\t\tm_firstClicked        = true;\r\n\t\tQVariantMap actionMap = DB::selectRow( \"Actions\", m_action );\r\n\t\tm_isFloor             = actionMap.value( \"IsFloor\" ).toBool();\r\n\t\tm_isMulti             = actionMap.value( \"Multi\" ).toBool();\r\n\t\tif ( m_action == \"BuildItem\" && DB::select( \"IsContainer\", \"Items\", m_item ).toBool() )\r\n\t\t{\r\n\t\t\tm_isMulti = true;\r\n\t\t}\r\n\r\n\t\tm_isMultiZ  = actionMap.value( \"MultiZ\" ).toBool();\r\n\t\tm_canRotate = actionMap.value( \"Rotate\" ).toBool();\r\n\t\tm_selection.push_back( QPair<Position, bool>( pos, testTileForJobSelection( pos ) ) );\r\n\t\t\r\n\t\temit signalFirstClick( m_firstClick.toString() );\r\n\r\n\t\tif ( !m_isMulti && !shift )\r\n\t\t{\r\n\t\t\tonSecondClick( shift, ctrl );\r\n\t\t\tm_firstClicked = false;\r\n\t\t\tm_changed      = true;\r\n\t\t\tupdateSelection( pos, shift, ctrl );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// second click creates whatever we want to create\r\n\t\tpos.z = m_firstClick.z;\r\n\t\tonSecondClick( shift, ctrl );\r\n\t\tm_firstClicked = false;\r\n\t\tm_changed      = true;\r\n\t\temit signalFirstClick( \"\" );\r\n\t\temit signalSize( \"\" );\r\n\t\tupdateSelection( pos, shift, ctrl );\r\n\t\treturn true;\r\n\t}\r\n}\r\n\r\nvoid Selection::setAction( QString action )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"Selection set action: \" << action;\r\n\r\n\tclear();\r\n\r\n\tm_action              = action;\r\n\tQVariantMap actionMap = DB::selectRow( \"Actions\", m_action );\r\n\r\n\tm_isFloor   = actionMap.value( \"IsFloor\" ).toBool();\r\n\tm_isMulti   = actionMap.value( \"Multi\" ).toBool();\r\n\tm_isMultiZ  = actionMap.value( \"MultiZ\" ).toBool();\r\n\tm_canRotate = actionMap.value( \"Rotate\" ).toBool();\r\n\r\n\temit signalActionChanged( m_action );\r\n}\r\n\r\nvoid Selection::updateSelection( Position& pos, bool shift, bool ctrl )\r\n{\r\n\tif ( m_action.isEmpty() )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t// a job is selected but we haven't clicked into the world yet\r\n\tif ( m_firstClicked == false )\r\n\t{\r\n\t\tm_selection.clear();\r\n\t\tm_selectionSize.first  = 0;\r\n\t\tm_selectionSize.second = 0;\r\n\t\tm_selection.push_back( QPair<Position, bool>( pos, testTileForJobSelection( pos ) ) );\r\n\t\tm_changed = true;\r\n\t}\r\n\t// for single tile job we just return here\r\n\tif ( !m_isMulti && !shift )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\t// clicked one, we span the selection between the clicked tile and the cursor position\r\n\tif ( m_firstClicked )\r\n\t{\r\n\t\tint beginX = ( m_firstClick.x < pos.x ) ? m_firstClick.x : pos.x;\r\n\t\tint endX   = ( m_firstClick.x > pos.x ) ? m_firstClick.x : pos.x;\r\n\t\tint beginY = ( m_firstClick.y < pos.y ) ? m_firstClick.y : pos.y;\r\n\t\tint endY   = ( m_firstClick.y > pos.y ) ? m_firstClick.y : pos.y;\r\n\r\n\t\tm_selectionSize.first  = qMax( 1, endX - beginX + 1 );\r\n\t\tm_selectionSize.second = qMax( 1, endY - beginY + 1 );\r\n\r\n\t\tm_selection.clear();\r\n\r\n\t\tif ( m_isMultiZ )\r\n\t\t{\r\n\t\t\tint z0 = qMin( m_firstClick.z, pos.z );\r\n\t\t\tint zn = qMax( m_firstClick.z, pos.z );\r\n\t\t\tfor ( int z = z0; z <= zn; ++z )\r\n\t\t\t{\r\n\t\t\t\tfor ( int y = beginY; y <= endY; ++y )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int x = beginX; x <= endX; ++x )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( m_ctrlActive )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( x > beginX && x < endX && y > beginY && y < endY )\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tpos = Position( x, y, z );\r\n\t\t\t\t\t\tm_selection.push_back( QPair<Position, bool>( pos, testTileForJobSelection( pos ) ) );\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\telse\r\n\t\t{\r\n\t\t\tfor ( int y = beginY; y <= endY; ++y )\r\n\t\t\t{\r\n\t\t\t\tfor ( int x = beginX; x <= endX; ++x )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_ctrlActive )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( x > beginX && x < endX && y > beginY && y < endY )\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpos = Position( x, y, m_firstClick.z );\r\n\t\t\t\t\tm_selection.push_back( QPair<Position, bool>( pos, testTileForJobSelection( pos ) ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( m_firstClicked )\r\n\t{\r\n\t\temit signalSize( QString::number( m_selectionSize.first ) + \" x \" + QString::number( m_selectionSize.second ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\temit signalSize( \"\" );\r\n\t}\r\n\r\n\tm_changed = true;\r\n}\r\n\r\nvoid Selection::rightClick( Position& pos )\r\n{\r\n\tif ( m_firstClicked )\r\n\t{\r\n\t\tm_selection.clear();\r\n\t\tQVariantMap actionMap = DB::selectRow( \"Actions\", m_action );\r\n\t\tm_selection.push_back( QPair<Position, bool>( pos, testTileForJobSelection( pos ) ) );\r\n\t\tm_firstClicked         = false;\r\n\t\tm_selectionSize.first  = 0;\r\n\t\tm_selectionSize.second = 0;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tclear();\r\n\t}\r\n\r\n\temit signalFirstClick( \"\" );\r\n\temit signalSize( \"\" );\r\n\t\t\r\n\tm_changed = true;\r\n}\r\n\r\nbool Selection::testTileForJobSelection( const Position& pos )\r\n{\r\n\t// TODO cache plants and posID and make it faster :)\r\n\tTile* tile;\r\n\tint dim = Global::dimX;\r\n\r\n\tif ( m_tileCheckList.empty() )\r\n\t{\r\n\t\tif ( m_action == \"BuildWorkshop\" )\r\n\t\t{\r\n\t\t\t// Workshops_Components\r\n\t\t\tm_tileCheckList = DB::selectRows( \"Workshops_Components\", \"ID\", m_item );\r\n\t\t}\r\n\t\telse if ( m_action == \"BuildItem\" )\r\n\t\t{\r\n\t\t\t// Item_Tiles\r\n\t\t\tm_tileCheckList = DB::selectRows( \"Items_Tiles\", \"ID\", m_item );\r\n\t\t}\r\n\t\telse if ( m_action == \"BuildWall\" && m_item == \"Palisade\" )\r\n\t\t{\r\n\t\t\t// Actions_Tiles\r\n\t\t\tif ( Global::debugMode )\r\n\t\t\t\tqDebug() << \"test tiles: \"\r\n\t\t\t\t\t\t << \"Actions_Tiles BuildWallPalisade\";\r\n\t\t\tm_tileCheckList = DB::selectRows( \"Actions_Tiles\", \"ID\", \"BuildWallPalisade\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Actions_Tiles\r\n\t\t\tm_tileCheckList = DB::selectRows( \"Actions_Tiles\", \"ID\", m_action );\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto tm : m_tileCheckList )\r\n\t{\r\n\t\tPosition testPos;\r\n\t\tPosition offset;\r\n\t\tif ( tm.contains( \"Offset\" ) )\r\n\t\t{\r\n\t\t\toffset   = Position( tm.value( \"Offset\" ).toString() );\r\n\t\t\tint rotX = offset.x;\r\n\t\t\tint rotY = offset.y;\r\n\t\t\tswitch ( m_rotation )\r\n\t\t\t{\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\toffset.x = -1 * rotY;\r\n\t\t\t\t\toffset.y = rotX;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\toffset.x = -1 * rotX;\r\n\t\t\t\t\toffset.y = -1 * rotY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\toffset.x = rotY;\r\n\t\t\t\t\toffset.y = -1 * rotX;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\ttestPos = Position( pos.x + offset.x, pos.y + offset.y, pos.z + offset.z );\r\n\t\t\tif ( !testPos.valid() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\ttile = &g->w()->getTile( testPos );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttestPos = pos;\r\n\t\t\tif ( !testPos.valid() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t\ttile    = &g->w()->getTile( pos );\r\n\t\t}\r\n\r\n\t\tQStringList required = tm.value( \"Required\" ).toString().split( \"|\" );\r\n\t\tif ( m_action == \"BuildWorkshop\" )\r\n\t\t{\r\n\t\t\tif ( required.size() == 1 && required[0].isEmpty() && offset.z == 0 )\r\n\t\t\t{\r\n\t\t\t\trequired.clear();\r\n\t\t\t\trequired.append( \"Floor\" );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif( Global::debugMode)\r\n\t\t{\r\n\t\t\tqDebug() << testPos.toString() << QString::number( (quint64)tile->flags, 16 ) << tile->wallType << tile->floorType;\r\n\t\t}\r\n\r\n\t\tfor ( auto req : required )\r\n\t\t{\r\n\t\t\t//if ( Global::debugMode )\r\n\t\t\t//\tqDebug() << \"test requirement: \" << req << \"...\";\r\n\t\t\tswitch ( m_reqMap.value( req ) )\r\n\t\t\t{\r\n\t\t\t\tcase SEL_NONE:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_FLOOR:\r\n\t\t\t\t\tif ( !(bool)( tile->floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_FLOOR_OR_SCAFFOLD:\r\n\t\t\t\t\tif ( !( (bool)( tile->floorType & FloorType::FT_SOLIDFLOOR ) || (bool)( tile->floorType & FloorType::FT_SCAFFOLD ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_WALL:\r\n\t\t\t\t\tif ( !( (bool)( tile->wallType & WallType::WT_ROUGH || (bool)( tile->wallType & WallType::WT_SOLIDWALL ) ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_MINEABLE_WALL:\r\n\t\t\t\t\tif ( !( (bool)( tile->wallType & WallType::WT_ROUGH || (bool)( tile->wallType & WallType::WT_SOLIDWALL ) || (bool)( tile->wallType & WallType::WT_RAMP ) || (bool)( tile->wallType & WallType::WT_RAMPCORNER ) ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_CONSTRUCTION:\r\n\t\t\t\t\tif ( !( (bool)( tile->wallType & WallType::WT_CONSTRUCTED ) || (bool)( tile->floorType & FloorType::FT_CONSTRUCTION ) ) && !g->mcm()->hasMechanism( pos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_MECHANISM:\r\n\t\t\t\t\tif ( !g->mcm()->hasMechanism( pos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_GEARBOX:\r\n\t\t\t\t\tif ( !g->mcm()->hasGearBox( pos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_JOB:\r\n\t\t\t\t\tif ( !g->w()->hasJob( testPos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_DESIGNATION:\r\n\t\t\t\t\tif ( !( tile->flags & ( TileFlag::TF_STOCKPILE + TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE + TileFlag::TF_ROOM + TileFlag::TF_NOPASS ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_STOCKPILE:\r\n\t\t\t\t\tif ( !( tile->flags & TileFlag::TF_STOCKPILE ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_ROOM:\r\n\t\t\t\t\tif ( !( tile->flags & TileFlag::TF_ROOM ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_ALLOW_BELL:\r\n\t\t\t\t\tif ( !( tile->flags & TileFlag::TF_ROOM ) || !g->rm()->allowBell( testPos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_ALLOW_FURNITURE:\r\n\t\t\t\t\tif ( ( tile->flags & ( TileFlag::TF_STOCKPILE + TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE + TileFlag::TF_NOPASS ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_PASTURE:\r\n\t\t\t\t\tif ( !( tile->flags & TileFlag::TF_PASTURE ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_WALKABLE:\r\n\t\t\t\t\tif ( !( tile->flags & TileFlag::TF_WALKABLE ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_STAIRS:\r\n\t\t\t\t\tif ( !( tile->wallType & WallType::WT_STAIR ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_STAIRSTOP:\r\n\t\t\t\t\tif ( !( tile->floorType & FloorType::FT_STAIRTOP ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_RAMP:\r\n\t\t\t\t\tif ( !( tile->wallType & WallType::WT_RAMP ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_RAMPTOP:\r\n\t\t\t\t\tif ( !( tile->floorType & FloorType::FT_RAMPTOP ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_SOIL:\r\n\t\t\t\t{\r\n\t\t\t\t\tQString matSID = DBH::materialSID( tile->floorMaterial );\r\n\r\n\t\t\t\t\tif ( DB::select( \"Type\", \"Materials\", matSID ).toString() != \"Soil\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_TREE:\r\n\t\t\t\t{\r\n\t\t\t\t\tbool isTree = false;\r\n\t\t\t\t\tif ( g->w()->plants().contains( testPos.toInt() ) )\r\n\t\t\t\t\t{ // need to guard [] access otherwise it constructs a default object for that location and furth checks fails\r\n\t\t\t\t\t\tisTree = g->w()->plants()[testPos.toInt()].isTree();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( !isTree )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_PLANT:\r\n\t\t\t\t{\r\n\t\t\t\t\tbool isPlant = false;\r\n\t\t\t\t\tif ( g->w()->plants().contains( testPos.toInt() ) )\r\n\t\t\t\t\t{ // need to guard [] access otherwise it constructs a default object for that location and further checks fail\r\n\t\t\t\t\t\tisPlant = g->w()->plants()[testPos.toInt()].isPlant();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( !isPlant )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_TREECLIP:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_PLANT_WITH_FRUIT:\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !( g->w()->plants().contains( testPos.toInt() ) && g->w()->plants()[testPos.toInt()].harvestable() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t//if ( Global::debugMode )\r\n\t\t\t//\tqDebug() << \"passed.\";\r\n\t\t}\r\n\r\n\t\tQStringList forbidden = tm.value( \"Forbidden\" ).toString().split( \"|\" );\r\n\t\tif ( m_action == \"BuildWorkshop\" && forbidden.size() == 1 && forbidden[0].isEmpty() )\r\n\t\t{\r\n\t\t\tforbidden.append( \"AnyWall\" );\r\n\t\t}\r\n\t\tfor ( auto forb : forbidden )\r\n\t\t{\r\n\t\t\t//if ( Global::debugMode )\r\n\t\t\t//\tqDebug() << \"test forbidden: \" << forb << \"...\";\r\n\t\t\tif ( m_action.startsWith( \"Build\" ) && tile->flags & TileFlag::TF_OCCUPIED )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tswitch ( m_reqMap.value( forb ) )\r\n\t\t\t{\r\n\t\t\t\tcase SEL_NONE:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_FLOOR:\r\n\t\t\t\t\tif ( (bool)( tile->floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_FLOOR_OR_SCAFFOLD:\r\n\t\t\t\t\tif ( ( (bool)( tile->floorType & FloorType::FT_SOLIDFLOOR ) || (bool)( tile->floorType & FloorType::FT_SCAFFOLD ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_WALL:\r\n\t\t\t\t\tif ( ( (bool)( tile->wallType & WallType::WT_ROUGH || (bool)( tile->wallType & WallType::WT_SOLIDWALL ) ) ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t//if( (bool)tile->wallType ) return false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_CONSTRUCTION:\r\n\t\t\t\t\tif ( (bool)( tile->wallType & WallType::WT_CONSTRUCTED ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_MECHANISM:\r\n\t\t\t\t\tif ( g->mcm()->hasMechanism( pos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_JOB:\r\n\t\t\t\t\tif ( g->w()->hasJob( testPos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_DESIGNATION:\r\n\t\t\t\t\tif ( tile->flags & ( TileFlag::TF_STOCKPILE + TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_ROOM + TileFlag::TF_PASTURE + TileFlag::TF_NOPASS ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_STOCKPILE:\r\n\t\t\t\t\tif ( tile->flags & TileFlag::TF_STOCKPILE )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_ROOM:\r\n\t\t\t\t\tif ( tile->flags & TileFlag::TF_ROOM )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_PASTURE:\r\n\t\t\t\t\tif ( tile->flags & TileFlag::TF_PASTURE )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\tcase SEL_STAIRS:\r\n\t\t\t\t\tif ( (bool)( tile->wallType & WallType::WT_STAIR ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_STAIRSTOP:\r\n\t\t\t\t\tif ( (bool)( tile->floorType & FloorType::FT_STAIRTOP ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_RAMP:\r\n\t\t\t\t\tif ( (bool)( tile->wallType & WallType::WT_RAMP ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_RAMPTOP:\r\n\t\t\t\t\tif ( (bool)( tile->floorType & FloorType::FT_RAMPTOP ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_SOIL:\r\n\t\t\t\t{\r\n\t\t\t\t\tQString matSID = DBH::materialSID( tile->floorMaterial );\r\n\t\t\t\t\tif ( DB::select( \"Type\", \"Materials\", matSID ).toString() == \"Soil\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_TREE:\r\n\t\t\t\t{\r\n\t\t\t\t\tbool isTree = false;\r\n\t\t\t\t\tif ( g->w()->plants().contains( testPos.toInt() ) )\r\n\t\t\t\t\t{ // need to guard [] access otherwise it constructs a default object for that location and furth checks fails\r\n\t\t\t\t\t\tisTree = g->w()->plants()[testPos.toInt()].isTree();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( isTree )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_PLANT:\r\n\t\t\t\t{\r\n\t\t\t\t\tbool isPlant = false;\r\n\t\t\t\t\tif ( g->w()->plants().contains( testPos.toInt() ) )\r\n\t\t\t\t\t{ // need to guard [] access otherwise it constructs a default object for that location and further checks fail\r\n\t\t\t\t\t\tisPlant = g->w()->plants()[testPos.toInt()].isPlant();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( isPlant )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_TREECLIP:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_TREE_IN_RANGE:\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( testPos.x < 3 || testPos.x > Global::dimX - 4 || testPos.y < 3 || testPos.y > Global::dimY - 4 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( !g->w()->noTree( testPos, 2, 2 ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_PLANT_WITH_FRUIT:\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( g->w()->plants().contains( testPos.toInt() ) && g->w()->plants()[testPos.toInt()].harvestable() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase SEL_ANYWALL:\r\n\t\t\t\t\tif ( tile->wallType )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tif ( g->w()->plants().contains( testPos.toInt() ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tif ( tile->flags & ( TileFlag::TF_STOCKPILE + TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_ROOM + TileFlag::TF_NOPASS ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tif ( g->w()->hasJob( testPos ) )\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\t//if ( Global::debugMode )\r\n\t\t\t//\tqDebug() << \"passed.\";\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid Selection::onSecondClick( bool shift, bool ctrl )\r\n{\r\n\tm_changed = true;\r\n\tif ( m_action == \"RemoveDesignation\" )\r\n\t{\r\n\t\tfor ( auto p : m_selection )\r\n\t\t{\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tg->w()->removeDesignation( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_action == \"CancelJob\" )\r\n\t{\r\n\t\tfor ( auto p : m_selection )\r\n\t\t{\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tg->jm()->cancelJob( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_action == \"RaisePrio\" )\r\n\t{\r\n\t\tfor ( auto p : m_selection )\r\n\t\t{\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tg->jm()->raisePrio( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"LowerPrio\" )\r\n\t{\r\n\t\tfor ( auto p : m_selection )\r\n\t\t{\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tg->jm()->lowerPrio( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_action == \"CreateStockpile\" )\r\n\t{\r\n\t\tg->spm()->addStockpile( m_firstClick, m_selection );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateGrove\" )\r\n\t{\r\n\t\tg->fm()->addGrove( m_firstClick, m_selection );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateFarm\" )\r\n\t{\r\n\t\tg->fm()->addFarm( m_firstClick, m_selection );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreatePasture\" )\r\n\t{\r\n\t\tg->fm()->addPasture( m_firstClick, m_selection );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateRoom\" )\r\n\t{\r\n\t\tg->rm()->addRoom( m_firstClick, m_selection, RoomType::PersonalRoom );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateDorm\" )\r\n\t{\r\n\t\tg->rm()->addRoom( m_firstClick, m_selection, RoomType::Dorm );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateDining\" )\r\n\t{\r\n\t\tg->rm()->addRoom( m_firstClick, m_selection, RoomType::Dining );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateHospital\" )\r\n\t{\r\n\t\tg->rm()->addRoom( m_firstClick, m_selection, RoomType::Hospital );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_action == \"CreateNoPass\" )\r\n\t{\r\n\t\tg->rm()->addNoPass( m_firstClick, m_selection );\r\n\t\treturn;\r\n\t}\r\n\tQString jobId = DB::select( \"Job\", \"Actions\", m_action ).toString();\r\n\r\n\tQVariantList vmats;\r\n\tfor ( auto m : m_materials )\r\n\t{\r\n\t\tvmats.push_back( m );\r\n\t}\r\n\tQVariantList vUMats;\r\n\tif ( m_debug )\r\n\t{\r\n\t\tfor ( auto m : m_materials )\r\n\t\t{\r\n\t\t\tvUMats.push_back( DBH::materialUID( m ) );\r\n\t\t}\r\n\t\tif ( m_isMulti )\r\n\t\t{\r\n\t\t\tfor ( auto p : m_selection )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->w()->construct( m_item, p.first, 0, Global::util->variantList2UInt( vUMats ), p.first );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_debug = false;\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_isMulti || shift )\r\n\t{\r\n\t\tif ( m_action == \"Deconstruct\" )\r\n\t\t{\r\n\t\t\tQSet<unsigned int> workshops;\r\n\r\n\t\t\tQList<QPair<Position, bool>> newSelection;\r\n\r\n\t\t\tfor ( auto p : m_selection )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second )\r\n\t\t\t\t{\r\n\t\t\t\t\t//if tile belongs to workshop, put in workshop set, else add position to newList\r\n\t\t\t\t\tauto ws = g->wsm()->workshopAt( p.first );\r\n\t\t\t\t\tif ( ws )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( !workshops.contains( ws->id() ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tworkshops.insert( ws->id() );\r\n\t\t\t\t\t\t\tnewSelection.append( QPair<Position, bool>( ws->pos(), true ) );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnewSelection.append( p );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfor ( auto p : newSelection )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->jm()->addJob( jobId, p.first, m_rotation );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto p : m_selection )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_materials.empty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tqDebug() << \"Selection::onSecondclick1\" << jobId << p.first.toString() << m_item << m_materials << m_rotation;\r\n\t\t\t\t\t\tg->jm()->addJob( jobId, p.first, m_rotation );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tqDebug() << \"Selection::onSecondclick2\" << jobId << p.first.toString() << m_item << m_materials << m_rotation;\r\n\t\t\t\t\t\tg->jm()->addJob( jobId, p.first, m_item, m_materials, m_rotation );\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\telse\r\n\t{\r\n\t\tif ( !m_selection.empty() )\r\n\t\t{\r\n\t\t\tauto& p = m_selection.first();\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tif ( m_materials.empty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\tqDebug() << jobId << p.first.toString() << m_item << m_materials << m_rotation;\r\n\t\t\t\t\tg->jm()->addJob( jobId, p.first, m_rotation );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\tqDebug() << jobId << p.first.toString() << m_item << m_materials << m_rotation;\r\n\t\t\t\t\tg->jm()->addJob( jobId, p.first, m_item, m_materials, m_rotation );\r\n\t\t\t\t}\r\n\t\t\t\tp.second = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint Selection::rotation()\r\n{\r\n\tif ( m_canRotate )\r\n\t{\r\n\t\treturn m_rotation;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n}\r\n\r\nbool Selection::changed()\r\n{\r\n\tbool out  = m_changed;\r\n\tm_changed = false;\r\n\treturn out;\r\n}\r\n\r\nvoid Selection::updateGui()\r\n{\r\n\temit signalActionChanged( \"\" );\r\n\temit signalSize( \"\" );\r\n}"
  },
  {
    "path": "src/base/selection.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QColor>\r\n#include <QList>\r\n#include <QPair>\r\n#include <QString>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\n\r\nenum enumReqs\r\n{\r\n\tSEL_NONE,\r\n\tSEL_FLOOR,\r\n\tSEL_FLOOR_OR_SCAFFOLD,\r\n\tSEL_WALL,\r\n\tSEL_MINEABLE_WALL,\r\n\tSEL_CONSTRUCTION,\r\n\tSEL_JOB,\r\n\tSEL_DESIGNATION,\r\n\tSEL_STOCKPILE,\r\n\tSEL_ROOM,\r\n\tSEL_ALLOW_BELL,\r\n\tSEL_ALLOW_FURNITURE,\r\n\tSEL_PASTURE,\r\n\tSEL_WALKABLE,\r\n\tSEL_MECHANISM,\r\n\tSEL_GEARBOX,\r\n\r\n\tSEL_STAIRS,\r\n\tSEL_STAIRSTOP,\r\n\tSEL_RAMP,\r\n\tSEL_RAMPTOP,\r\n\r\n\tSEL_SOIL,\r\n\tSEL_TREE,\r\n\tSEL_PLANT,\r\n\tSEL_TREECLIP,\r\n\tSEL_PLANT_WITH_FRUIT,\r\n\tSEL_TREE_IN_RANGE,\r\n\r\n\tSEL_ANYWALL\r\n};\r\n\r\nclass Selection : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tint m_rotation;\r\n\tPosition m_firstClick;\r\n\tbool m_firstClicked;\r\n\tQString m_action;\r\n\tQString m_item;\r\n\tQStringList m_materials;\r\n\tQList<QPair<Position, bool>> m_selection;\r\n\tQPair<int, int> m_selectionSize;\r\n\tbool m_debug;\r\n\tbool m_isFloor    = false;\r\n\tbool m_isMulti    = false;\r\n\tbool m_isMultiZ   = false;\r\n\tbool m_ctrlActive = false;\r\n\tQList<QVariantMap> m_tileCheckList;\r\n\tbool m_canRotate = false;\r\n\r\n\tQMap<QString, int> m_reqMap;\r\n\r\n\tbool testTileForJobSelection( const Position& pos );\r\n\tvoid onSecondClick( bool shift, bool ctrl );\r\n\r\n\tbool m_changed = false;\r\n\r\npublic:\r\n\tSelection( Game* game );\r\n\t~Selection();\r\n\r\n\tQVariantMap serialize();\r\n\r\n\tvoid clear();\r\n\tvoid rotate();\r\n\tbool leftClick( Position& pos, bool shift, bool ctrl );\r\n\tvoid updateSelection( Position& pos, bool shift, bool ctrl );\r\n\tvoid rightClick( Position& pos );\r\n\tvoid setAction( QString action );\r\n\tvoid setItemID( QString item )\r\n\t{\r\n\t\tm_item = item;\r\n\t}\r\n\tvoid setMaterials( QList<QString> materials )\r\n\t{\r\n\t\tm_materials = materials;\r\n\t}\r\n\tvoid setMaterial( QString material )\r\n\t{\r\n\t\tm_materials.clear();\r\n\t\tm_materials.append( material );\r\n\t}\r\n\tvoid setDebug( bool d )\r\n\t{\r\n\t\tm_debug = d;\r\n\t}\r\n\r\n\tbool hasAction()\r\n\t{\r\n\t\treturn !m_action.isEmpty();\r\n\t}\r\n\tQList<QPair<Position, bool>>& getSelection()\r\n\t{\r\n\t\treturn m_selection;\r\n\t}\r\n\tQString& action()\r\n\t{\r\n\t\treturn m_action;\r\n\t}\r\n\tQString& itemID()\r\n\t{\r\n\t\treturn m_item;\r\n\t}\r\n\tQStringList& material()\r\n\t{\r\n\t\treturn m_materials;\r\n\t}\r\n\tQPair<int, int>& size()\r\n\t{\r\n\t\treturn m_selectionSize;\r\n\t}\r\n\tint rotation();\r\n\tbool isFloor()\r\n\t{\r\n\t\treturn m_isFloor;\r\n\t}\r\n\tvoid setControlActive( bool active )\r\n\t{\r\n\t\tm_ctrlActive = active;\r\n\t}\r\n\r\n\tbool changed();\r\n\tvoid updateGui();\r\n\r\nsignals:\r\n\tvoid signalActionChanged( const QString action );\r\n\tvoid signalFirstClick( const QString firstClick );\r\n\tvoid signalSize( const QString size );\r\n};\r\n"
  },
  {
    "path": "src/base/tile.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\nstruct TerrainMaterial\r\n{\r\n\tQString key;\r\n\tint rowid;\r\n\tQString type;\r\n\tQString wall;\r\n\tQString shortwall;\r\n\tQString floor;\r\n\tint lowest;\r\n\tint highest;\r\n\tunsigned int wallSprite      = 0;\r\n\tunsigned int shortWallSprite = 0;\r\n\tunsigned int floorSprite     = 0;\r\n};\r\n\r\nstruct EmbeddedMaterial\r\n{\r\n\tQString key;\r\n\tint rowid;\r\n\tQString type;\r\n\tQString wall;\r\n\tint lowest;\r\n\tint highest;\r\n};\r\n\r\nenum WallType : unsigned short\r\n{\r\n\tWT_NOWALL       = 0,\r\n\tWT_SOLIDWALL    = 0x01,\r\n\tWT_ROUGH        = 0x02,\r\n\tWT_CONSTRUCTED  = 0x04,\r\n\tWT_VIEWBLOCKING = 0x08,\r\n\tWT_MOVEBLOCKING = 0x10,\r\n\tWT_STAIR        = 0x20,\r\n\tWT_RAMP         = 0x40,\r\n\tWT_RAMPCORNER   = 0x80,\r\n\tWT_SCAFFOLD     = 0x100\r\n};\r\nQ_DECLARE_TYPEINFO( WallType, Q_PRIMITIVE_TYPE );\r\n\r\nenum FloorType : unsigned char\r\n{\r\n\tFT_NOFLOOR      = 0,\r\n\tFT_SOLIDFLOOR   = 0x01,\r\n\tFT_STAIRTOP     = 0x02,\r\n\tFT_CONSTRUCTION = 0x04,\r\n\tFT_RAMPTOP      = 0x08,\r\n\tFT_SCAFFOLD     = 0x10\r\n};\r\nQ_DECLARE_TYPEINFO( FloorType, Q_PRIMITIVE_TYPE );\r\n\r\nenum class TileFlag : quint64\r\n{\r\n\tTF_NONE              = 0,\r\n\tTF_WALKABLE          = 0x01,\r\n\tTF_UNDISCOVERED      = 0x02,\r\n\tTF_SUNLIGHT          = 0x04,\r\n\tTF_WET               = 0x08,\r\n\tTF_GRASS             = 0x10,\r\n\tTF_NOPASS            = 0x20, // no pass designation, gnomes are not allowed to walk here\r\n\tTF_BLOCKED           = 0x40, // workshop output tile full\r\n\tTF_DOOR              = 0x80,\r\n\tTF_STOCKPILE         = 0x0100,\r\n\tTF_GROVE             = 0x0200,\r\n\tTF_FARM              = 0x0400,\r\n\tTF_TILLED            = 0x0800,\r\n\tTF_WORKSHOP          = 0x1000,\r\n\tTF_ROOM              = 0x2000,\r\n\tTF_LAVA              = 0x4000,\r\n\tTF_WATER             = 0x8000,\r\n\tTF_JOB_FLOOR         = 0x10000,\r\n\tTF_JOB_WALL          = 0x20000,\r\n\tTF_JOB_BUSY_FLOOR    = 0x40000,\r\n\tTF_JOB_BUSY_WALL     = 0x80000,\r\n\tTF_MOUSEOVER         = 0x100000,\r\n\tTF_WALKABLEANIMALS   = 0x200000,\r\n\tTF_WALKABLEMONSTERS  = 0x400000,\r\n\tTF_PASTURE           = 0x800000,\r\n\tTF_INDIRECT_SUNLIGHT = 0x01000000,\r\n\tTF_BIOME_MUSHROOM    = 0x02000000,\r\n\tTF_OCCUPIED          = 0x04000000,\r\n\tTF_PIPE              = 0x08000000,\r\n\tTF_AQUIFIER          = 0x10000000,\r\n\tTF_DEAQUIFIER        = 0x20000000,\r\n\tTF_TRANSPARENT       = 0x40000000,\r\n\tTF_OVERSIZE          = 0x80000000,\r\n};\r\n\r\nbool operator|( const TileFlag& a, const TileFlag& b ) = delete;\r\nconstexpr inline bool operator&( const TileFlag& a, const TileFlag& b )\r\n{\r\n\treturn static_cast<quint64>( a ) & static_cast<quint64>( b );\r\n}\r\n\r\nconstexpr inline TileFlag operator+( const TileFlag& a, const TileFlag& b )\r\n{\r\n\treturn static_cast<TileFlag>( static_cast<quint64>( a ) | static_cast<quint64>( b ) );\r\n}\r\n\r\nconstexpr inline TileFlag operator-( const TileFlag& a, const TileFlag& b )\r\n{\r\n\treturn static_cast<TileFlag>( static_cast<quint64>( a ) & ~static_cast<quint64>( b ) );\r\n}\r\n\r\nconstexpr inline TileFlag operator~( const TileFlag& a )\r\n{\r\n\treturn static_cast<TileFlag>( ~static_cast<quint64>( a ) );\r\n}\r\n\r\nconstexpr inline void operator+=( TileFlag& a, const TileFlag& b )\r\n{\r\n\ta = a + b;\r\n}\r\nconstexpr inline void operator-=( TileFlag& a, const TileFlag& b )\r\n{\r\n\ta = a - b;\r\n}\r\n\r\nenum WaterFlow : unsigned char\r\n{\r\n\tWF_NOFLOW = 0x00,\r\n\tWF_NORTH  = 0x01,\r\n\tWF_EAST   = 0x02,\r\n\tWF_SOUTH  = 0x04,\r\n\tWF_WEST   = 0x08,\r\n\tWF_UP     = 0x10,\r\n\tWF_DOWN   = 0x20,\r\n\tWF_EVAP   = 0x40\r\n};\r\nconstexpr inline WaterFlow operator+( const WaterFlow& a, const WaterFlow& b )\r\n{\r\n\treturn static_cast<WaterFlow>( static_cast<unsigned char>( a ) | static_cast<unsigned char>( b ) );\r\n}\r\nconstexpr inline void operator+=( WaterFlow& a, const WaterFlow& b )\r\n{\r\n\ta = a + b;\r\n}\r\n\r\nQ_DECLARE_TYPEINFO( WaterFlow, Q_PRIMITIVE_TYPE );\r\n\r\nstruct Tile\r\n{\r\n\tTileFlag flags = TileFlag::TF_NONE;\r\n\r\n\tFloorType floorType          = FT_NOFLOOR;\r\n\tunsigned short floorMaterial = 0;\r\n\r\n\tWallType wallType               = WT_NOWALL;\r\n\tunsigned short wallMaterial     = 0;\r\n\tunsigned short embeddedMaterial = 0;\r\n\r\n\tunsigned char floorRotation = 0;\r\n\tunsigned char wallRotation  = 0;\r\n\r\n\tunsigned char fluidLevel = 0;\r\n\tunsigned char pressure   = 0;\r\n\tWaterFlow flow           = WF_NOFLOW;\r\n\r\n\tunsigned char lightLevel      = 0;\r\n\tunsigned char vegetationLevel = 0;\r\n\r\n\tunsigned int floorSpriteUID = 0;\r\n\tunsigned int wallSpriteUID  = 0;\r\n\tunsigned int itemSpriteUID  = 0;\r\n};\r\nQ_DECLARE_TYPEINFO( Tile, Q_PRIMITIVE_TYPE );\r\n\r\nstruct AxleData\r\n{\r\n\tunsigned int itemID = 0;\r\n\tPosition pos;\r\n\tunsigned short spriteID = 0;\r\n\tquint8 localRot         = 0;\r\n\tbool anim               = false;\r\n\tbool isVertical         = false;\r\n};\r\nQ_DECLARE_TYPEINFO( AxleData, Q_PRIMITIVE_TYPE );\r\n"
  },
  {
    "path": "src/base/util.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"util.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/pathfinder.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/object.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QComboBox>\r\n#include <QDebug>\r\n#include <QIcon>\r\n#include <QJsonDocument>\r\n#include <QPainter>\r\n\r\nUtil::Util( Game* game ) :\r\n\tg( game )\r\n{\r\n}\r\n\r\nUtil::~Util()\r\n{\r\n}\r\n\r\nQStringList Util::seedItems( QString plantType, QString material )\r\n{\r\n\tQStringList out;\r\n\r\n\tQList<QString> ids = DB::ids( \"Plants\", \"Type\", plantType );\r\n\tfor ( const auto& id : ids )\r\n\t{\r\n\t\tQString mat = DB::select( \"Material\", \"Plants\", id ).toString();\r\n\t\tif ( mat == material || material == \"any\" )\r\n\t\t{\r\n\t\t\tout.push_back( DB::select( \"SeedItemID\", \"Plants\", id ).toString() );\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQString Util::itemName( QString itemID )\r\n{\r\n\treturn S::s( \"$ItemName_\" + itemID );\r\n}\r\n\r\nQString Util::materialName( QString materialID )\r\n{\r\n\treturn S::s( \"$MaterialName_\" + materialID );\r\n}\r\n\r\nQString Util::materialType( QString materialID )\r\n{\r\n\treturn DB::select( \"Type\", \"Materials\", materialID ).toString();\r\n}\r\n\r\nQString Util::requiredSkill( QString jobID )\r\n{\r\n\tauto dbjb = DB::job( jobID );\r\n\tif( dbjb )\r\n\t{\r\n\t\treturn dbjb->SkillID;\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nQString Util::requiredMagicSkill( QString spellID )\r\n{\r\n\treturn DB::select( \"SkillID\", \"Spells\", spellID ).toString();\r\n}\r\n\r\nQString Util::requiredTool( QString jobID )\r\n{\r\n\tauto dbjb = DB::job( jobID );\r\n\tif( dbjb )\r\n\t{\r\n\t\treturn dbjb->RequiredToolItemID;\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nint Util::requiredToolLevel( QString jobID, Position pos )\r\n{\r\n\tauto dbjb = DB::job( jobID );\r\n\tif( !dbjb )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\tQString method = dbjb->RequiredToolLevel;\r\n\tint level      = 0;\r\n\r\n\tif ( method == \"ByWallMaterial\" )\r\n\t{\r\n\t\tlevel = requiredToolLevelByWallMaterial( pos );\r\n\r\n\t\tif ( jobID == \"DigHole\" || jobID == \"DigStairsDown\" )\r\n\t\t{\r\n\t\t\tpos.z = qMax( 0, pos.z - 1 );\r\n\t\t}\r\n\t\tlevel = qMax( level, requiredToolLevelByWallMaterial( pos ) );\r\n\t}\r\n\tif ( method == \"ByFloorMaterial\" )\r\n\t{\r\n\t\tlevel = requiredToolLevelByFloorMaterial( pos );\r\n\t}\r\n\tif ( method == \"ByPlantMaterial\" )\r\n\t{\r\n\t\tlevel = 1;\r\n\t}\r\n\treturn level;\r\n}\r\n\r\nint Util::requiredToolLevelByWallMaterial( Position pos )\r\n{\r\n\tint level                   = 0;\r\n\tunsigned short wallMaterial = g->w()->getTile( pos ).wallMaterial;\r\n\tQString wallMatSID          = DBH::materialSID( wallMaterial );\r\n\r\n\tQString wallMatType = Util::materialType( wallMatSID );\r\n\r\n\tif ( DBH::rowID( \"MaterialToToolLevel\", wallMatSID ) )\r\n\t{\r\n\t\tlevel = DB::select( \"RequiredToolLevel\", \"MaterialToToolLevel\", wallMatSID ).toInt();\r\n\t}\r\n\telse if ( DBH::rowID( \"MaterialToToolLevel\", wallMatType ) )\r\n\t{\r\n\t\tlevel = DB::select( \"RequiredToolLevel\", \"MaterialToToolLevel\", wallMatType ).toInt();\r\n\t}\r\n\treturn level;\r\n}\r\nint Util::requiredToolLevelByFloorMaterial( Position pos )\r\n{\r\n\tint level                    = 0;\r\n\tunsigned short floorMaterial = g->w()->getTile( pos ).floorMaterial;\r\n\r\n\tQString floorMatSID = DBH::materialSID( floorMaterial );\r\n\r\n\tQString floorMatType = Util::materialType( floorMatSID );\r\n\r\n\tif ( DBH::rowID( \"MaterialToToolLevel\", floorMatSID ) )\r\n\t{\r\n\t\tlevel = DB::select( \"RequiredToolLevel\", \"MaterialToToolLevel\", floorMatSID ).toInt();\r\n\t}\r\n\telse if ( DBH::rowID( \"MaterialToToolLevel\", floorMatType ) )\r\n\t{\r\n\t\tlevel = DB::select( \"RequiredToolLevel\", \"MaterialToToolLevel\", floorMatType ).toInt();\r\n\t}\r\n\treturn level;\r\n}\r\n\r\nint Util::toolLevel( unsigned int itemUID )\r\n{\r\n\tint level        = 0;\r\n\tQString material = g->inv()->materialSID( itemUID );\r\n\r\n\tQString materialType = Util::materialType( material );\r\n\r\n\tif ( DBH::rowID( \"MaterialToToolLevel\", material ) )\r\n\t{\r\n\t\tlevel = DB::select( \"ToolLevel\", \"MaterialToToolLevel\", material ).toInt();\r\n\t}\r\n\telse if ( DBH::rowID( \"MaterialToToolLevel\", materialType ) )\r\n\t{\r\n\t\tlevel = DB::select( \"ToolLevel\", \"MaterialToToolLevel\", materialType ).toInt();\r\n\t}\r\n\treturn level;\r\n}\r\n\r\nint Util::toolLevel( QString materialSID )\r\n{\r\n\tif ( DBH::rowID( \"MaterialToToolLevel\", materialSID ) )\r\n\t{\r\n\t\treturn DB::select( \"ToolLevel\", \"MaterialToToolLevel\", materialSID ).toInt();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tQString materialType = Util::materialType( materialSID );\r\n\t\tif ( DBH::rowID( \"MaterialToToolLevel\", materialType ) )\r\n\t\t{\r\n\t\t\treturn DB::select( \"ToolLevel\", \"MaterialToToolLevel\", materialType ).toInt();\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQSet<QString> Util::itemsAllowedInContainer( unsigned int containerID )\r\n{\r\n\treturn Global::allowedInContainer.value( g->inv()->itemSID( containerID ) );\r\n}\r\n\r\nbool Util::itemAllowedInContainer( unsigned int itemID, unsigned int containerID )\r\n{\r\n\treturn Global::allowedInContainer.value( g->inv()->itemSID( containerID ) ).contains( g->inv()->itemSID( itemID ) );\r\n}\r\n\r\nvoid Util::initAllowedInContainer()\r\n{\r\n\tGlobal::allowedInContainer.clear();\r\n\r\n\tfor ( const auto& itemSID : DB::ids( \"Items\" ) )\r\n\t{\r\n\t\tauto containerSID = DB::select( \"AllowedContainers\", \"Items\", itemSID ).toString();\r\n\r\n\t\tif ( !containerSID.isEmpty() )\r\n\t\t{\r\n\t\t\tGlobal::allowedInContainer[containerSID].insert( itemSID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQString Util::carryContainerForItem( QString itemSID )\r\n{\r\n\treturn DB::select( \"CarryContainer\", \"Items\", itemSID ).toString();\r\n}\r\n\r\nint Util::capacity( QString containerSID )\r\n{\r\n\treturn DB::select( \"Capacity\", \"Containers\", containerSID ).toInt();\r\n}\r\n\r\nvoid Util::addFloatToVariant( QVariantMap& vm, QString key, float addValue )\r\n{\r\n\tfloat value = vm.value( key ).toFloat();\r\n\tvalue += addValue;\r\n\tvm.insert( key, value );\r\n}\r\n\r\nQString Util::tile2String( Tile& tile, QString seperator )\r\n{\r\n\tQString out = QString::number( static_cast<quint64>( tile.flags ) );\r\n\tout += seperator;\r\n\tout += QString::number( tile.floorType );\r\n\tout += seperator;\r\n\tout += QString::number( tile.floorMaterial );\r\n\tout += seperator;\r\n\tout += QString::number( tile.wallType );\r\n\tout += seperator;\r\n\tout += QString::number( tile.wallMaterial );\r\n\tout += seperator;\r\n\tout += QString::number( tile.floorRotation );\r\n\tout += seperator;\r\n\tout += QString::number( tile.wallRotation );\r\n\tout += seperator;\r\n\tout += QString::number( tile.fluidLevel );\r\n\tout += seperator;\r\n\tif ( tile.wallSpriteUID )\r\n\t{\r\n\t\tout += QString::number( tile.wallSpriteUID );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tout += QString::number( 0 );\r\n\t}\r\n\tout += seperator;\r\n\tif ( tile.floorSpriteUID )\r\n\t{\r\n\t\tout += QString::number( tile.floorSpriteUID );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tout += QString::number( 0 );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nvoid Util::string2Tile( Tile& tile, QString data, QString seperator )\r\n{\r\n\tQStringList dl = data.split( seperator );\r\n\tint i          = 0;\r\n\tif ( dl.size() == 10 )\r\n\t{\r\n\t\ttile.flags         = (TileFlag)dl[0].toUInt();\r\n\t\ttile.floorType     = (FloorType)dl[1].toUInt();\r\n\t\ttile.floorMaterial = dl[2].toUInt();\r\n\t\ttile.wallType      = (WallType)dl[3].toUInt();\r\n\t\ttile.wallMaterial  = dl[4].toUInt();\r\n\t\ttile.floorRotation = dl[5].toUInt();\r\n\t\ttile.wallRotation  = dl[6].toUInt();\r\n\t\t//tile.fluidLevel = dl[7].toUInt();\r\n\t\ttile.wallSpriteUID  = dl[8].toUInt();\r\n\t\ttile.floorSpriteUID = dl[9].toUInt();\r\n\t}\r\n}\r\n\r\nQString Util::mapJoin( QMap<int, int> data, QString seperator )\r\n{\r\n\tQString out;\r\n\tif ( !data.isEmpty() )\r\n\t{\r\n\t\tfor ( const auto& rp : data.toStdMap() )\r\n\t\t{\r\n\t\t\tout += QString::number( rp.first );\r\n\t\t\tout += seperator;\r\n\t\t\tout += QString::number( rp.second );\r\n\t\t\tout += seperator;\r\n\t\t}\r\n\t\tout.chop( 1 );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQMap<int, int> Util::mapSplit( QString data, QString seperator )\r\n{\r\n\tQMap<int, int> m;\r\n\tif ( !data.isEmpty() )\r\n\t{\r\n\t\tQStringList dl = data.split( seperator );\r\n\t\tfor ( int i = 0; i < dl.size(); i += 2 )\r\n\t\t{\r\n\t\t\tm.insert( dl[i].toInt(), dl[i + 1].toInt() );\r\n\t\t}\r\n\t}\r\n\treturn m;\r\n}\r\n\r\nQPair<int, int> Util::pixelOffset( const int x, const int y, const int z )\r\n{\r\n\tint dimX = Global::dimX;\r\n\tint dimY = Global::dimY;\r\n\tint dimZ = Global::dimZ;\r\n\t/*\r\n\tint xOff = x * 32 - 16 * x + 16 * y;\r\n\tint yOff = -( y * 32 - ( 8 * y + 8 * x ) );\r\n\t*/\r\n\tint xOff = -16 * x + 16 * y;\r\n\tint yOff = -8 * x + -8 * y;\r\n\r\n\treturn QPair<int, int>( xOff, yOff );\r\n}\r\n\r\nQPair<int, int> Util::pixelOffset( const Position& pos )\r\n{\r\n\treturn Util::pixelOffset( pos.x, pos.y, pos.z );\r\n}\r\n\r\nunsigned char Util::rotString2Char( QString rot )\r\n{\r\n\tif ( rot == \"FL\" )\r\n\t\treturn 1;\r\n\telse if ( rot == \"BL\" )\r\n\t\treturn 2;\r\n\telse if ( rot == \"BR\" )\r\n\t\treturn 3;\r\n\treturn 0;\r\n}\r\n\r\nQPixmap Util::smallPixmap( Sprite* sprite, QString season, int rotation )\r\n{\r\n\tif ( !sprite )\r\n\t{\r\n\t\treturn QPixmap();\r\n\t}\r\n\tQPixmap pm = sprite->pixmap( season, 0, 0 );\r\n\r\n\tQImage img = pm.toImage();\r\n\tQImage newImg( 32, 32, QImage::Format::Format_RGBA8888 );\r\n\r\n\tint firstLine = 0;\r\n\tint lastLine  = 63;\r\n\r\n\tfor ( int y = 0; y < 64; ++y )\r\n\t{\r\n\t\tbool found = false;\r\n\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t{\r\n\t\t\tif ( img.height() <= y )\r\n\t\t\t\tqDebug() << \"Util::smallPixmap 1\" << sprite->sID;\r\n\t\t\tQColor col = img.pixelColor( x, y );\r\n\t\t\tif ( col.red() + col.green() + col.blue() > 0 )\r\n\t\t\t{\r\n\t\t\t\tfirstLine = 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\tif ( found )\r\n\t\t\tbreak;\r\n\t}\r\n\tfor ( int y = 63; y >= firstLine; --y )\r\n\t{\r\n\t\tbool found = false;\r\n\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t{\r\n\t\t\tif ( img.height() <= y )\r\n\t\t\t\tqDebug() << \"Util::smallPixmap 2\" << sprite->sID;\r\n\t\t\tQColor col = img.pixelColor( x, y );\r\n\t\t\tif ( col.red() + col.green() + col.blue() > 0 )\r\n\t\t\t{\r\n\t\t\t\tlastLine = 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\tif ( found )\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tint numLines = lastLine - firstLine + 1;\r\n\tint yOff     = qMax( 0, ( 32 - numLines ) ) / 2;\r\n\tQColor col1( 0, 0, 0, 0 );\r\n\tfor ( int y = 0; y < 32; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t{\r\n\t\t\tnewImg.setPixelColor( x, y, col1 );\r\n\t\t}\r\n\t}\r\n\tfor ( int y = 0; y < 32 - yOff; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t{\r\n\t\t\tif ( img.height() <= y )\r\n\t\t\t\tqDebug() << \"Util::smallPixmap 3\" << sprite->sID;\r\n\t\t\tQColor col = img.pixelColor( x, y + firstLine );\r\n\t\t\tnewImg.setPixelColor( x, y + yOff, col );\r\n\t\t}\r\n\t}\r\n\r\n\tQPixmap newPM = QPixmap::fromImage( newImg );\r\n\treturn newPM;\r\n}\r\n\r\nQColor Util::colorInt2Color( unsigned int color )\r\n{\r\n\tint a = color & 0xff;\r\n\tint b = ( color >> 8 ) & 0xff;\r\n\tint gg = ( color >> 16 ) & 0xff;\r\n\tint r = ( color >> 24 ) & 0xff;\r\n\treturn QColor( r, gg, b, a );\r\n}\r\n\r\nunsigned int Util::string2Color( QString color )\r\n{\r\n\tQStringList clist = color.split( \" \" );\r\n\tunsigned char r, gg, b;\r\n\tr = gg = b       = 0;\r\n\tunsigned char a = 255;\r\n\tif ( clist.size() > 2 )\r\n\t{\r\n\t\tr = clist[0].toInt();\r\n\t\tgg = clist[1].toInt();\r\n\t\tb = clist[2].toInt();\r\n\t}\r\n\tif ( clist.size() > 3 )\r\n\t{\r\n\t\ta = clist[3].toInt();\r\n\t}\r\n\r\n\treturn r * 16777216 + gg * 65536 + b * 256 + a;\r\n}\r\n\r\nQColor Util::string2QColor( QString color )\r\n{\r\n\tQList<QString> csl = color.split( ' ' );\r\n\tif ( csl.size() == 4 )\r\n\t{\r\n\t\treturn QColor( csl[0].toInt(), csl[1].toInt(), csl[2].toInt(), csl[3].toInt() );\r\n\t}\r\n\treturn QColor();\r\n}\r\n\r\nQColor Util::variant2QColor( QVariant color )\r\n{\r\n\tQList<QString> csl = color.toString().split( ' ' );\r\n\tif ( csl.size() == 4 )\r\n\t{\r\n\t\treturn QColor( csl[0].toInt(), csl[1].toInt(), csl[2].toInt(), csl[3].toInt() );\r\n\t}\r\n\treturn QColor();\r\n}\r\n\r\nunsigned int Util::createRawMaterialItem( Position pos, unsigned int materialID )\r\n{\r\n\t//create items from the wall material\r\n\tQString materialSID = \"None\";\r\n\tQString type        = \"None\";\r\n\tmaterialSID         = DBH::materialSID( materialID );\r\n\ttype                = Util::materialType( materialSID );\r\n\r\n\tif ( type == \"Soil\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawSoil\", materialSID );\r\n\t}\r\n\telse if ( type == \"Sand\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawSoil\", materialSID );\r\n\t}\r\n\telse if ( type == \"Clay\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawSoil\", materialSID );\r\n\t}\r\n\telse if ( type == \"Stone\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawStone\", materialSID );\r\n\t}\r\n\telse if ( type == \"Coal\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawCoal\", materialSID );\r\n\t}\r\n\telse if ( type == \"Metal\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawOre\", materialSID );\r\n\t}\r\n\telse if ( type == \"Gem\" )\r\n\t{\r\n\t\treturn g->inv()->createItem( pos, \"RawGem\", materialSID );\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint Util::ticksPerDayRandomized( int percentage )\r\n{\r\n\tint maxOffset = qMax( 1, (int)( (float)Util::ticksPerDay / 100. ) * percentage );\r\n\treturn Util::ticksPerDay + ( ( rand() % ( maxOffset * 2 ) ) - maxOffset );\r\n}\r\n\r\nunsigned int Util::reverseFib( unsigned int number )\r\n{\r\n\tif ( number < Global::xpMod )\r\n\t\treturn 1;\r\n\r\n\tdouble num = (double)number / Global::xpMod;\r\n\r\n\t//n(F) = Floor[ Log(F Sqrt(5) + 1/2)/Log(Phi)]\r\n\treturn floor( log( num * 2.2360679775 + 0.5 ) / log( 1.6180339887 ) );\r\n}\r\n\r\nPosition Util::reachableBorderPos( Position fromPos, bool& found )\r\n{\r\n\tint randPos = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\r\n\tPosition pos( randPos, randPos, Global::dimZ - 1 );\r\n\tint border = rand() % 4;\r\n\tswitch ( border )\r\n\t{\r\n\t\tcase 0: //north\r\n\t\t\tpos.y = 1;\r\n\t\t\tbreak;\r\n\t\tcase 1: //east\r\n\t\t\tpos.x = Global::dimX - 2;\r\n\t\t\tbreak;\r\n\t\tcase 2: //south\r\n\t\t\tpos.y = Global::dimX - 2;\r\n\t\t\tbreak;\r\n\t\tcase 3: // west\r\n\t\t\tpos.x = 1;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tg->w()->getFloorLevelBelow( pos, false );\r\n\r\n\tif ( g->w()->fluidLevel( pos ) == 0 )\r\n\t{\r\n\t\tif ( g->pf()->checkConnectedRegions( pos, fromPos ) )\r\n\t\t{\r\n\t\t\tfound = true;\r\n\t\t\treturn pos;\r\n\t\t}\r\n\t}\r\n\treturn pos;\r\n}\r\n\r\nPosition Util::borderPos( bool& found )\r\n{\r\n\tPosition pos;\r\n\tint border = rand() % 4;\r\n\tswitch ( border )\r\n\t{\r\n\t\tcase 0: //north\r\n\t\t\tpos.x = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\t\t\tpos.y = 1;\r\n\t\t\tbreak;\r\n\t\tcase 1: //east\r\n\t\t\tpos.x = Global::dimX - 2;\r\n\t\t\tpos.y = qMax( 2, rand() % ( Global::dimY - 2 ) );\r\n\t\t\tbreak;\r\n\t\tcase 2: //south\r\n\t\t\tpos.x = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\t\t\tpos.y = Global::dimY - 2;\r\n\t\t\tbreak;\r\n\t\tcase 3: // west\r\n\t\t\tpos.x = 1;\r\n\t\t\tpos.y = qMax( 2, rand() % ( Global::dimY - 2 ) );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tconst size_t maxTries = ( Global::dimX - 4 ) * ( Global::dimY - 4 );\r\n\tsize_t nTries         = 0;\r\n\t// walk the edge till a legal position is found\r\n\twhile ( ++nTries < maxTries )\r\n\t{\r\n\t\tpos.z = Global::dimZ - 1;\r\n\t\t// project position onto ground\r\n\t\tg->w()->getFloorLevelBelow( pos, false );\r\n\t\tif ( g->w()->isWalkableGnome(pos) )\r\n\t\t{\r\n\t\t\tfound = true;\r\n\t\t\treturn pos;\r\n\t\t}\r\n\t\tswitch (border)\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tif ( pos.x >= Global::dimX - 2 )\r\n\t\t\t\t{\r\n\t\t\t\t\tborder = 1;\r\n\t\t\t\t\t++pos.y;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t++pos.x;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tif ( pos.y >= Global::dimY - 2 )\r\n\t\t\t\t{\r\n\t\t\t\t\tborder = 2;\r\n\t\t\t\t\t--pos.x;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t++pos.y;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tif ( pos.x <= 2 )\r\n\t\t\t\t{\r\n\t\t\t\t\tborder = 3;\r\n\t\t\t\t\t--pos.y;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t--pos.x;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tif ( pos.y <= 2 )\r\n\t\t\t\t{\r\n\t\t\t\t\tborder = 0;\r\n\t\t\t\t\t++pos.x;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t--pos.y;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQList<Position> Util::neighbors8( Position pos )\r\n{\r\n\tQList<Position> out;\r\n\tint x = pos.x;\r\n\tint y = pos.y;\r\n\tint z = pos.z;\r\n\r\n\tout.push_back( Position( x - 1, y - 1, z ) );\r\n\tout.push_back( Position( x - 1, y, z ) );\r\n\tout.push_back( Position( x - 1, y + 1, z ) );\r\n\tout.push_back( Position( x, y - 1, z ) );\r\n\tout.push_back( Position( x, y + 1, z ) );\r\n\tout.push_back( Position( x + 1, y - 1, z ) );\r\n\tout.push_back( Position( x + 1, y, z ) );\r\n\tout.push_back( Position( x + 1, y + 1, z ) );\r\n\r\n\treturn out;\r\n}\r\n\r\nquint64 Util::nextSeasonChangeTick()\r\n{\r\n\t// TODO make this mod safe\r\n\tint minute            = ( GameState::minute == 60 ) ? 0 : GameState::minute;\r\n\tint hour              = ( GameState::hour == 24 ) ? 0 : GameState::hour;\r\n\tint ticksToNextHour   = ( Util::minutesPerHour - minute ) * Util::ticksPerMinute;\r\n\tint ticksToNextDay    = ( Util::hoursPerDay - ( hour + 1 ) ) * Util::ticksPerMinute * Util::minutesPerHour;\r\n\tint ticksToNextSeason = ( Util::daysPerSeason - ( GameState::day ) ) * Util::ticksPerMinute * Util::minutesPerHour * Util::hoursPerDay;\r\n\r\n\t//qDebug() << \"#\" << Util::minutesPerHour << minute << \" - \" << Util::hoursPerDay << hour << \" - \" <<  Util::daysPerSeason << Global::day;\r\n\t//qDebug() << \"##\" << ticksToNextHour << ticksToNextDay << ticksToNextSeason;\r\n\r\n\treturn GameState::tick + ticksToNextHour + ticksToNextDay + ticksToNextSeason;\r\n}\r\n\r\nQString Util::randomMetal()\r\n{\r\n\tQStringList metals = { \"Copper\", \"Tin\", \"Malachite\", \"Iron\", \"Lead\", \"Silver\", \"Gold\", \"Platinum\" };\r\n\tif ( metals.size() > 0 )\r\n\t{\r\n\t\treturn metals.at( rand() % metals.size() );\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nQString Util::randomMetalSliver( QString sourceMaterial )\r\n{\r\n\tauto row = DB::selectRow( \"RandomMetals\", sourceMaterial );\r\n\r\n\tauto ra = rand() % 100;\r\n\r\n\tQStringList metals = { \"Copper\", \"Tin\", \"Malachite\", \"Iron\", \"Lead\", \"Silver\", \"Gold\", \"Platinum\" };\r\n\tint sum            = 0;\r\n\tfor ( const auto& metal : metals )\r\n\t{\r\n\t\tsum += row.value( metal ).toInt();\r\n\t\tif ( ra < sum )\r\n\t\t{\r\n\t\t\treturn metal;\r\n\t\t}\r\n\t}\r\n\r\n\treturn \"Copper\";\r\n}\r\n\r\nQToolButton* Util::createToolButton( QIcon icon, QString text, QString toolTip )\r\n{\r\n\tQToolButton* button = new QToolButton;\r\n\tbutton->setIcon( icon );\r\n\r\n\tif ( text.isEmpty() )\r\n\t{\r\n\t\tbutton->setIconSize( QSize( 50, 50 ) );\r\n\t\tbutton->setMinimumSize( 56, 56 );\r\n\t\tbutton->setMaximumSize( 56, 56 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tbutton->setIconSize( QSize( 32, 32 ) );\r\n\t\tbutton->setText( text );\r\n\t\tbutton->setToolButtonStyle( Qt::ToolButtonTextUnderIcon );\r\n\t\tbutton->setFixedHeight( 56 );\r\n\t\t//button->setMinimumWidth( 56 );\r\n\t\tbutton->setMaximumWidth( 120 );\r\n\t}\r\n\tif ( !toolTip.isEmpty() )\r\n\t{\r\n\t\tbutton->setToolTip( toolTip );\r\n\t}\r\n\r\n\treturn button;\r\n}\r\n\r\nQString Util::getRandomString( int length )\r\n{\r\n\tconst QString possibleCharacters( \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" );\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\tQString randomString;\r\n\tfor ( int i = 0; i < length; ++i )\r\n\t{\r\n\t\tint index      = qrand() % possibleCharacters.length();\r\n\t\tQChar nextChar = possibleCharacters.at( index );\r\n\t\trandomString.append( nextChar );\r\n\t}\r\n\treturn randomString;\r\n}\r\n\r\nQVariantList Util::uintList2Variant( const QList<unsigned int>& list )\r\n{\r\n\tQVariantList out;\r\n\tfor ( auto ui : list )\r\n\t{\r\n\t\tout.append( ui );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<unsigned int> Util::variantList2UInt( const QVariantList& vlist )\r\n{\r\n\tQList<unsigned int> out;\r\n\tfor ( const auto& vui : vlist )\r\n\t{\r\n\t\tout.append( vui.toUInt() );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQVariantList Util::positionList2Variant( const QList<Position>& list )\r\n{\r\n\tQVariantList out;\r\n\tfor ( const auto& pos : list )\r\n\t{\r\n\t\tout.append( pos.toString() );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<Position> Util::variantList2Position( const QVariantList& vlist )\r\n{\r\n\tQList<Position> out;\r\n\tfor ( const auto& vpos : vlist )\r\n\t{\r\n\t\tout.append( Position( vpos ) );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQVariantList Util::pairList2Variant( const QList<QPair<QString, QString>>& plist )\r\n{\r\n\tQVariantList out;\r\n\tfor ( const auto& pair : plist )\r\n\t{\r\n\t\tout.append( pair.first );\r\n\t\tout.append( pair.second );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<QPair<QString, QString>> Util::variantList2Pair( const QVariantList& plist )\r\n{\r\n\tQList<QPair<QString, QString>> out;\r\n\r\n\tif ( plist.size() > 1 )\r\n\t{\r\n\t\tfor ( int i = 0; i < plist.size(); i += 2 )\r\n\t\t{\r\n\t\t\tQPair<QString, QString> entry( plist[i].toString(), plist[i + 1].toString() );\r\n\t\t\tout.append( entry );\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Util::setIndexFromText( QComboBox* cb, QString text )\r\n{\r\n\tfor ( int i = 0; i < cb->count(); ++i )\r\n\t{\r\n\t\tif ( cb->itemText( i ) == text )\r\n\t\t{\r\n\t\t\tcb->blockSignals( true );\r\n\t\t\tcb->setCurrentIndex( i );\r\n\t\t\tcb->blockSignals( false );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQString Util::addDyeMaterial( QString sourceMaterial, QString dyeMaterial )\r\n{\r\n\tQString targetMaterial = sourceMaterial + dyeMaterial;\r\n\tif ( !DB::select( \"rowid\", \"Materials\", targetMaterial ).toInt() )\r\n\t{\r\n\t\tauto sourceRow = DB::selectRow( \"Materials\", sourceMaterial );\r\n\t\tauto dyeRow    = DB::selectRow( \"Materials\", dyeMaterial );\r\n\t\tsourceRow.insert( \"Color\", dyeRow.value( \"Color\" ) );\r\n\t\tsourceRow.insert( \"ID\", targetMaterial );\r\n\r\n\t\tDB::addRow( \"Materials\", sourceRow );\r\n\t\t//DB::addTranslation( \"$MaterialName_\" + targetMaterial, S::s( \"$MaterialName_\" + sourceMaterial ) + \" \" + S::s( \"$MaterialName_\" + dyeMaterial ) );\r\n\t\t//strings are cached on game start, so no insert in DB but strings map\r\n\t\tStrings::getInstance().insertString( \"$MaterialName_\" + targetMaterial, S::s( \"$MaterialName_\" + dyeMaterial ) + \" \" + S::s( \"$MaterialName_\" + sourceMaterial ) );\r\n\r\n\t\tGameState::addedMaterials.append( sourceRow );\r\n\t\t\r\n\t\tGameState::addedTranslations.insert( \"$MaterialName_\" + targetMaterial, S::s( \"$MaterialName_\" + dyeMaterial ) + \" \" + S::s( \"$MaterialName_\" + sourceMaterial ) );\r\n\t}\r\n\treturn targetMaterial;\r\n}\r\n\r\nvoid Util::debugVM( QVariantMap vm, QString name )\r\n{\r\n\tqDebug() << name;\r\n\tfor ( const auto& key : vm.keys() )\r\n\t{\r\n\t\tqDebug() << key << \":\" << vm.value( key ).toString();\r\n\t}\r\n}\r\n\r\nQPixmap Util::createWorkshopImage( const QString& workshopID, const QStringList& mats )\r\n{\r\n\tauto dbws = DB::workshop( workshopID );\r\n\r\n\tif( !dbws )\r\n\t{\r\n\t\tQPixmap pm( 100, 100 );\r\n\t\tpm.fill( QColor( 0, 0, 0, 0 ) );\r\n\t\treturn pm;\r\n\t}\r\n\r\n\tif ( !dbws->Icon.isEmpty() )\r\n\t{\r\n\t\tconst auto path = Global::cfg->get( \"dataPath\" ).toString() + \"/xaml/buttons/\" + dbws->Icon;\r\n\t\tQPixmap pm( path );\r\n\t\tassert( pm.width() > 0 );\r\n\t\treturn pm;\r\n\t}\r\n\tQString season = GameState::seasonString;\r\n\r\n\tauto coms = DB::selectRows( \"Workshops_Components\", workshopID );\r\n\r\n\tQPixmap pm( 100, 100 );\r\n\tpm.fill( QColor( 0, 0, 0, 0 ) );\r\n\r\n\tQPainter painter( &pm );\r\n\tint x0 = 34;\r\n\tint y0 = 0;\r\n\r\n\tfor ( int y = 0; y < 3; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < 3; ++x )\r\n\t\t{\r\n\t\t\tconst int px      = x0 + 16 * x - 16 * y;\r\n\t\t\tconst int py      = y0 + 8 * y + 8 * x;\r\n\t\t\tunsigned char rot = 0;\r\n\t\t\tSprite* sprite    = getSprite( x - 1, y - 1, coms, rot, mats );\r\n\t\t\tif ( sprite )\r\n\t\t\t{\r\n\t\t\t\t//painter.drawPixmap( px + sprite->xOffset, py + sprite->yOffset, sprite->pixmap( season, rot ) );\r\n\t\t\t\tpainter.drawPixmap( px, py, sprite->pixmap( season, rot, 0 ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pm;\r\n}\r\n\r\nQPixmap Util::createItemImage( const QString& itemID, const QStringList& mats )\r\n{\r\n\tauto vsprite = DB::select( \"SpriteID\", \"Items\", itemID );\r\n\tQVariantMap component;\r\n\tcomponent.insert( \"SpriteID\", vsprite );\r\n\tcomponent.insert( \"Offset\", \"0 0 0\" );\r\n\r\n\tQList<QVariantMap> comps;\r\n\tcomps.append( component );\r\n\r\n\tQString season = GameState::seasonString;\r\n\r\n\tQPixmap pm( 100, 100 );\r\n\tpm.fill( QColor( 0, 0, 0, 0 ) );\r\n\r\n\tQPainter painter( &pm );\r\n\tint x0 = 34;\r\n\tint y0 = 0;\r\n\r\n\tfor ( int y = 0; y < 3; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < 3; ++x )\r\n\t\t{\r\n\t\t\tconst int px      = x0 + 16 * x - 16 * y;\r\n\t\t\tconst int py      = y0 + 8 * y + 8 * x;\r\n\t\t\tunsigned char rot = 0;\r\n\t\t\tSprite* sprite    = getSprite( x - 1, y - 1, comps, rot, mats );\r\n\t\t\tif ( sprite )\r\n\t\t\t{\r\n\t\t\t\t//painter.drawPixmap( px + sprite->xOffset, py + sprite->yOffset, sprite->pixmap( season, rot ) );\r\n\t\t\t\tpainter.drawPixmap( px, py, sprite->pixmap( season, rot, 0 ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pm;\r\n}\r\n\r\nQPixmap Util::createItemImage2( const QString& itemID, const QStringList& mats )\r\n{\r\n\tauto spriteID = DB::select( \"SpriteID\", \"Items\", itemID ).toString();\r\n\t\r\n\tQString season = GameState::seasonString;\r\n\r\n\tQPixmap pm( 32, 32 );\r\n\tpm.fill( QColor( 0, 0, 0, 0 ) );\r\n\r\n\tQPainter painter( &pm );\r\n\tint x0 = 0;\r\n\tint y0 = 0;\r\n\r\n\tSprite* sprite = g->sf()->createSprite( spriteID, mats ) ;\r\n\tif ( sprite )\r\n\t{\r\n\t\t//painter.drawPixmap( px + sprite->xOffset, py + sprite->yOffset, sprite->pixmap( season, rot ) );\r\n\t\tpainter.drawPixmap( 0, -16, sprite->pixmap( season, 0, 0 ) );\r\n\t}\r\n\treturn pm;\r\n}\r\n\r\nQPixmap Util::createConstructionImage( const QString& constructionID, const QStringList& mats )\r\n{\r\n\tauto sprites = DB::selectRows( \"Constructions_Sprites\", constructionID );\r\n\r\n\tQString season = GameState::seasonString;\r\n\r\n\tQPixmap pm( 100, 100 );\r\n\tpm.fill( QColor( 0, 0, 0, 0 ) );\r\n\r\n\tQPainter painter( &pm );\r\n\tint x0 = 34;\r\n\tint y0 = 0;\r\n\r\n\tfor ( int y = 0; y < 3; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < 3; ++x )\r\n\t\t{\r\n\t\t\tconst int px      = x0 + 16 * x - 16 * y;\r\n\t\t\tconst int py      = y0 + 8 * y + 8 * x;\r\n\t\t\tunsigned char rot = 0;\r\n\t\t\tSprite* sprite    = getSprite( x - 1, y - 1, sprites, rot, mats );\r\n\t\t\tif ( sprite )\r\n\t\t\t{\r\n\t\t\t\t//painter.drawPixmap( px + sprite->xOffset, py + sprite->yOffset, sprite->pixmap( season, rot ) );\r\n\t\t\t\tpainter.drawPixmap( px, py, sprite->pixmap( season, rot, 0 ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn pm;\r\n}\r\n\r\nSprite* Util::getSprite( int x, int y, const QList<QVariantMap>& comps, unsigned char& rot, const QStringList& mats )\r\n{\r\n\tQStringList materialIDs;\r\n\tint mid = 0;\r\n\tfor ( const auto& cm : comps )\r\n\t{\r\n\t\tPosition pos( cm.value( \"Offset\" ).toString() );\r\n\t\tif ( pos.x == x && pos.y == y )\r\n\t\t{\r\n\t\t\tif ( !cm.value( \"MaterialItem\" ).toString().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& mat : cm.value( \"MaterialItem\" ).toString().split( \"|\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmaterialIDs.push_back( mats[mat.toInt()] );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmaterialIDs.push_back( mats[mid] );\r\n\t\t\t}\r\n\t\t\tif ( !cm.value( \"WallRotation\" ).toString().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tQString wallRot = cm.value( \"WallRotation\" ).toString();\r\n\t\t\t\tif ( wallRot == \"FR\" )\r\n\t\t\t\t\trot = 0;\r\n\t\t\t\telse if ( wallRot == \"FL\" )\r\n\t\t\t\t\trot = 1;\r\n\t\t\t\telse if ( wallRot == \"BL\" )\r\n\t\t\t\t\trot = 2;\r\n\t\t\t\telse if ( wallRot == \"BR\" )\r\n\t\t\t\t\trot = 3;\r\n\t\t\t}\r\n\r\n\t\t\tif ( !cm.value( \"SpriteID\" ).toString().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\treturn g->sf()->createSprite( cm.value( \"SpriteID\" ).toString(), materialIDs );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\treturn nullptr;\r\n\t\t\t}\r\n\t\t}\r\n\t\t++mid;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQStringList Util::possibleMaterialsForItem( QString itemSID )\r\n{\r\n\tQVariantMap row = DB::selectRow( \"Items\", itemSID );\r\n\treturn possibleMaterials( row.value( \"AllowedMaterials\" ).toString(), row.value( \"AllowedMaterialTypes\" ).toString() );\r\n}\r\n\r\nQStringList Util::possibleMaterials( QString allowedMaterials, QString allowedMaterialTypes )\r\n{\r\n\tQStringList out;\r\n\r\n\tif ( !allowedMaterials.isEmpty() )\r\n\t{\r\n\t\tfor ( const auto& mat : allowedMaterials.split( \"|\" ) )\r\n\t\t{\r\n\t\t\tout.append( mat );\r\n\t\t}\r\n\t}\r\n\tif ( !allowedMaterialTypes.isEmpty() )\r\n\t{\r\n\t\tfor ( const auto& type : allowedMaterialTypes.split( \"|\" ) )\r\n\t\t{\r\n\t\t\tfor ( const auto& mat : DB::ids( \"Materials\", \"Type\", type ) )\r\n\t\t\t{\r\n\t\t\t\tout.append( mat );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nvoid Util::createBufferForNoesisImage( const QPixmap& pm, std::vector<unsigned char>& buffer )\r\n{\r\n\tint w = pm.width();\r\n\tint h = pm.height();\r\n\r\n\tbuffer.resize( w * h * 4, 0 );\r\n\tQImage img = pm.toImage();\r\n\r\n\tfor ( int x = 0; x < w; ++x )\r\n\t{\r\n\t\tfor ( int y = 0; y < h; ++y )\r\n\t\t{\r\n\t\t\tauto color                    = img.pixelColor( x, y );\r\n\t\t\tbuffer[( x + y * w ) * 4]     = color.red();\r\n\t\t\tbuffer[( x + y * w ) * 4 + 1] = color.green();\r\n\t\t\tbuffer[( x + y * w ) * 4 + 2] = color.blue();\r\n\t\t\tbuffer[( x + y * w ) * 4 + 3] = 255;\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/base/util.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QGridLayout>\r\n#include <QLayoutItem>\r\n#include <QPixmap>\r\n#include <QString>\r\n#include <QStringList>\r\n#include <QToolButton>\r\n#include <QVariant>\r\n#include <QtGlobal>\r\n\r\nclass QComboBox;\r\n\r\nclass Game;\r\nclass ObjectItem;\r\nstruct Tile;\r\n\r\nclass Util\r\n{\r\npublic:\r\n\tUtil( Game* game );\r\n\t~Util();\r\n\r\n\tQStringList seedItems( QString plantType, QString material = \"any\" );\r\n\r\n\tQString itemName( QString itemID );\r\n\tQString materialName( QString materialID );\r\n\r\n\tQString materialType( QString materialID );\r\n\r\n\tQString requiredSkill( QString jobID );\r\n\tQString requiredMagicSkill( QString spellID );\r\n\tQString requiredTool( QString jobID );\r\n\tint requiredToolLevel( QString jobID, Position pos );\r\n\tint requiredToolLevelByWallMaterial( Position pos );\r\n\tint requiredToolLevelByFloorMaterial( Position pos );\r\n\tint toolLevel( unsigned int itemUID );\r\n\tint toolLevel( QString materialSID );\r\n\r\n\tQSet<QString> itemsAllowedInContainer( unsigned int container );\r\n\tbool itemAllowedInContainer( unsigned int item, unsigned int container );\r\n\tvoid initAllowedInContainer();\r\n\tQString carryContainerForItem( QString itemSID );\r\n\tint capacity( QString containerSID );\r\n\r\n\tvoid addFloatToVariant( QVariantMap& vm, QString key, float addValue );\r\n\r\n\tQString tile2String( Tile& tile, QString seperator = \"_\" );\r\n\tvoid string2Tile( Tile& tile, QString data, QString seperator = \"_\" );\r\n\tQString mapJoin( QMap<int, int>, QString seperator = \"_\" );\r\n\tQMap<int, int> mapSplit( QString data, QString seperator = \"_\" );\r\n\r\n\tQPair<int, int> pixelOffset( const int x, const int y, const int z );\r\n\tQPair<int, int> pixelOffset( const Position& pos );\r\n\r\n\tunsigned char rotString2Char( QString rot );\r\n\r\n\tQColor colorInt2Color( unsigned int color );\r\n\tunsigned int string2Color( QString color );\r\n\tQColor string2QColor( QString color );\r\n\tQColor variant2QColor( QVariant color );\r\n\r\n\tQString randomMetal();\r\n\tQString randomMetalSliver( QString sourceMaterial );\r\n\r\n\tint ticksPerMinute = 10;\r\n\tint minutesPerHour = 60;\r\n\tint hoursPerDay = 24;\r\n\tint ticksPerDay = 14400;\r\n\tint daysPerSeason = 12;\r\n\r\n\tint ticksPerDayRandomized( int percentage );\r\n\r\n\tquint64 nextSeasonChangeTick();\r\n\r\n\tunsigned int createRawMaterialItem( Position pos, unsigned int materialID );\r\n\r\n\tunsigned int reverseFib( unsigned int number );\r\n\r\n\tPosition reachableBorderPos( Position pos, bool& found );\r\n\tPosition borderPos( bool& found );\r\n\r\n\tQList<Position> neighbors8( Position pos );\r\n\r\n\tQToolButton* createToolButton( QIcon icon, QString text, QString toolTip );\r\n\r\n\tQString getRandomString( int length );\r\n\r\n\tstatic QVariantList uintList2Variant( const QList<unsigned int>& list );\r\n\tQList<unsigned int> variantList2UInt( const QVariantList& vlist );\r\n\r\n\tQVariantList positionList2Variant( const QList<Position>& list );\r\n\tQList<Position> variantList2Position( const QVariantList& vlist );\r\n\r\n\tQVariantList pairList2Variant( const QList<QPair<QString, QString>>& plist );\r\n\tQList<QPair<QString, QString>> variantList2Pair( const QVariantList& plist );\r\n\r\n\tvoid setIndexFromText( QComboBox* cb, QString text );\r\n\r\n\tQString addDyeMaterial( QString sourceMaterial, QString dyeMaterial );\r\n\r\n\tvoid debugVM( QVariantMap vm, QString name );\r\n\r\n\tQPixmap smallPixmap( Sprite* sprite, QString season, int rotation );\r\n\tQPixmap createWorkshopImage( const QString& workshopID, const QStringList& m_mats );\r\n\tQPixmap createItemImage( const QString& constructionID, const QStringList& mats );\r\n\tQPixmap createItemImage2( const QString& constructionID, const QStringList& mats );\r\n\tQPixmap createConstructionImage( const QString& constructionID, const QStringList& mats );\r\n\tSprite* getSprite( int x, int y, const QList<QVariantMap>& comps, unsigned char& rot, const QStringList& mats );\r\n\r\n\tvoid createBufferForNoesisImage( const QPixmap& pm, std::vector<unsigned char>& buffer );\r\n\r\n\tQStringList possibleMaterialsForItem( QString itemSID );\r\n\tQStringList possibleMaterials( QString allowedMaterials, QString allowedMaterialTypes );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n};\r\n"
  },
  {
    "path": "src/base/vptr.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QVariant>\r\n\r\ntemplate <class T>\r\nclass VPtr\r\n{\r\npublic:\r\n\tstatic T* asPtr( QVariant v )\r\n\t{\r\n\t\treturn (T*)v.value<void*>();\r\n\t}\r\n\r\n\tstatic QVariant asQVariant( T* ptr )\r\n\t{\r\n\t\treturn qVariantFromValue( (void*)ptr );\r\n\t}\r\n};\r\n"
  },
  {
    "path": "src/game/anatomy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"anatomy.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/creature.h\"\r\n\r\n#include <QDebug>\r\n\r\nAnatomy::Anatomy()\r\n{\r\n}\r\n\r\nAnatomy::~Anatomy()\r\n{\r\n}\r\n\r\nvoid Anatomy::init( QString type, bool isAquatic )\r\n{\r\n\tm_type = type;\r\n\tm_isAquatic = isAquatic || ( type == \"Fish\" );\r\n\r\n\tauto def = DB::selectRow( \"Anatomy\", type );\r\n\r\n\tQString root = def.value( \"Root\" ).toString();\r\n\r\n\tif ( root.isEmpty() )\r\n\t{\r\n\t\ttype = \"Dummy\";\r\n\t\tdef  = DB::selectRow( \"Anatomy\", type );\r\n\t\troot = def.value( \"Root\" ).toString();\r\n\t}\r\n\r\n\tauto rows = DB::selectRows( \"Anatomy_Parts\", type );\r\n\r\n\tfor ( auto row : rows )\r\n\t{\r\n\t\tAnatomyPart ap;\r\n\t\tap.id     = Global::creaturePartLookUp.value( row.value( \"ID2\" ).toString() );\r\n\t\tap.parent = Global::creaturePartLookUp.value( row.value( \"Parent\" ).toString() );\r\n\r\n\t\tQString sh = row.value( \"Height\" ).toString();\r\n\t\tif ( sh == \"High\" )\r\n\t\t\tap.height = AH_HIGH;\r\n\t\telse if ( sh == \"Middle\" )\r\n\t\t\tap.height = AH_MIDDLE;\r\n\t\telse\r\n\t\t\tap.height = AH_LOW;\r\n\r\n\t\tQString ss = row.value( \"Side\" ).toString();\r\n\t\tif ( ss == \"Left\" )\r\n\t\t\tap.side = AS_LEFT;\r\n\t\telse if ( ss == \"Right\" )\r\n\t\t\tap.side = AS_RIGHT;\r\n\t\telse\r\n\t\t\tap.side = AS_CENTER;\r\n\r\n\t\tap.isInside = row.value( \"IsInside\" ).toBool();\r\n\t\tap.isVital  = row.value( \"IsVital\" ).toBool();\r\n\t\tap.hp       = row.value( \"HP\" ).toInt();\r\n\t\tap.maxHP    = row.value( \"HP\" ).toInt();\r\n\r\n\t\tm_parts.insert( ap.id, ap );\r\n\t}\r\n\r\n\tfor ( auto row : rows )\r\n\t{\r\n\t\tauto id     = Global::creaturePartLookUp.value( row.value( \"ID2\" ).toString() );\r\n\t\tauto parent = Global::creaturePartLookUp.value( row.value( \"Parent\" ).toString() );\r\n\r\n\t\tm_parts[parent].children.append( id );\r\n\t}\r\n}\r\n\r\nQVariantMap Anatomy::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"Type\", m_type );\r\n\tout.insert( \"Blood\", m_blood );\r\n\tout.insert( \"Bleeding\", m_bleeding );\r\n\tout.insert( \"Status\", m_status );\r\n\tout.insert( \"Aquatic\", m_isAquatic );\r\n\r\n\tQVariantList vlParts;\r\n\r\n\tfor ( auto part : m_parts )\r\n\t{\r\n\t\tQVariantMap vm;\r\n\t\tvm.insert( \"ID\", part.id );\r\n\t\tvm.insert( \"HP\", part.hp );\r\n\r\n\t\tvlParts.append( vm );\r\n\t}\r\n\tout.insert( \"Parts\", vlParts );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Anatomy::deserialize( QVariantMap in )\r\n{\r\n\tm_type = in.value( \"Type\" ).toString();\r\n\tinit( m_type, in.value( \"Aquatic\" ).toBool() );\r\n\r\n\tm_statusChanged = true;\r\n\tm_status        = (AnatomyStatus)in.value( \"Status\" ).toUInt();\r\n\tm_blood         = in.value( \"Blood\" ).toFloat();\r\n\tm_bleeding      = in.value( \"Bleeding\" ).toFloat();\r\n\r\n\tauto vl = in.value( \"Parts\" ).toList();\r\n\tfor ( auto vpart : vl )\r\n\t{\r\n\t\tauto vm         = vpart.toMap();\r\n\t\tCreaturePart id = (CreaturePart)vm.value( \"ID\" ).toUInt();\r\n\t\tif ( m_parts.contains( id ) )\r\n\t\t{\r\n\t\t\tm_parts[id].hp = vm.value( \"HP\" ).toFloat();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Anatomy::damage( Equipment* eq, DamageType dt, AnatomyHeight da, AnatomySide ds, int strength )\r\n{\r\n\t// get part that is hit\r\n\tCreaturePart hitPart = KCP_NONE;\r\n\r\n\tbool left   = (bool)( ds & AS_LEFT );\r\n\tbool right  = (bool)( ds & AS_RIGHT );\r\n\tbool center = (bool)( ds & AS_FRONT ) || (bool)( ds & AS_BACK );\r\n\r\n\tint ra;\r\n\tswitch ( da )\r\n\t{\r\n\t\tcase AH_LOW:\r\n\t\t{ // hit foot or leg\r\n\t\t\tif ( !left && !right )\r\n\t\t\t{\r\n\t\t\t\tra    = rand() % 100;\r\n\t\t\t\tleft  = ( ra > 50 );\r\n\t\t\t\tright = !left;\r\n\t\t\t}\r\n\t\t\tra = rand() % 100;\r\n\t\t\tif ( left )\r\n\t\t\t{\r\n\t\t\t\tif ( ra > 75 )\r\n\t\t\t\t{\r\n\t\t\t\t\thitPart = CP_LEFT_FOOT;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\thitPart = CP_LEFT_LEG;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tra = rand() % 100;\r\n\t\t\t\tif ( ra > 75 )\r\n\t\t\t\t{\r\n\t\t\t\t\thitPart = CP_RIGHT_FOOT;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\thitPart = CP_RIGHT_LEG;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase AH_MIDDLE:\r\n\t\t{\r\n\t\t\tif ( !left && !right )\r\n\t\t\t{\r\n\t\t\t\thitPart = CP_TORSO;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tra = rand() % 100;\r\n\t\t\t\tif ( left )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( ra > 50 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thitPart = CP_TORSO;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tra = rand() % 100;\r\n\t\t\t\t\t\tif ( ra > 75 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\thitPart = CP_LEFT_HAND;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\thitPart = CP_LEFT_ARM;\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\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( ra > 50 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\thitPart = CP_TORSO;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tra = rand() % 100;\r\n\t\t\t\t\t\t\tif ( ra > 75 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\thitPart = CP_RIGHT_HAND;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\thitPart = CP_RIGHT_ARM;\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\r\n\t\t\t// hit torso, arm or hand\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase AH_HIGH:\r\n\t\t{\r\n\t\t\t// hit head\r\n\t\t\thitPart = CP_HEAD;\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\tif ( m_parts.contains( hitPart ) )\r\n\t{\r\n\t\tAnatomyPart& part = m_parts[hitPart];\r\n\r\n\t\tif ( part.hp <= 0 )\r\n\t\t{\r\n\t\t\tif ( m_parts.contains( part.parent ) )\r\n\t\t\t{\r\n\t\t\t\thitPart = part.parent;\r\n\t\t\t\tpart    = m_parts[hitPart];\r\n\t\t\t\tif ( part.hp <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_parts.contains( part.parent ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\thitPart = part.parent;\r\n\t\t\t\t\t\tpart    = m_parts[hitPart];\r\n\t\t\t\t\t\tif ( part.hp <= 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( m_parts.contains( part.parent ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\thitPart = part.parent;\r\n\t\t\t\t\t\t\t\tpart    = m_parts[hitPart];\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tm_status        = AnatomyStatus( m_status | AS_DEAD );\r\n\t\t\t\t\t\t\t\tm_statusChanged = true;\r\n\t\t\t\t\t\t\t\treturn;\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\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_status        = AnatomyStatus( m_status | AS_DEAD );\r\n\t\t\t\t\t\tm_statusChanged = true;\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_status        = AnatomyStatus( m_status | AS_DEAD );\r\n\t\t\t\tm_statusChanged = true;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfloat dr          = eq->getDamageReduction( part.id );\r\n\t\tfloat finalDamage = strength - dr;\r\n\t\tpart.hp           = part.hp - finalDamage;\r\n\t\tif ( finalDamage > 0 )\r\n\t\t{\r\n\t\t\tm_status = AnatomyStatus( m_status | AS_WOUNDED );\r\n\t\t}\r\n\t\tif ( dt == DT_SLASH || dt == DT_PIERCING )\r\n\t\t{\r\n\t\t\tif ( finalDamage > ( ( part.maxHP / 100 ) * 10 ) )\r\n\t\t\t{\r\n\t\t\t\tm_bleeding += 0.5;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( part.hp <= 0 )\r\n\t\t{\r\n\t\t\tif ( part.isVital )\r\n\t\t\t{\r\n\t\t\t\tm_status        = AnatomyStatus( m_status | AS_DEAD );\r\n\t\t\t\tm_statusChanged = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Anatomy::statusChanged()\r\n{\r\n\t//m_hp = qMin( 100., m_hp + 0.025 );\r\n\r\n\tif ( m_bleeding > 0 )\r\n\t{\r\n\t\tm_blood -= m_bleeding;\r\n\r\n\t\tif ( m_blood < 1000 )\r\n\t\t{\r\n\t\t\tm_status        = AnatomyStatus( m_status | AS_DEAD );\r\n\t\t\tm_statusChanged = true;\r\n\t\t}\r\n\t\telse if ( m_blood < 3000 && !(bool)( m_status & AS_UNCONSCIOUS ) )\r\n\t\t{\r\n\t\t\tm_status        = AnatomyStatus( m_status | AS_UNCONSCIOUS );\r\n\t\t\tm_statusChanged = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( m_blood < 5000 )\r\n\t\t{\r\n\t\t\tm_blood += 0.25;\r\n\t\t\tif ( m_blood > 4000 && (bool)( m_status & AS_UNCONSCIOUS ) )\r\n\t\t\t{\r\n\t\t\t\tunsigned char mask = 0xFF ^ AS_UNCONSCIOUS;\r\n\t\t\t\tm_status           = ( AnatomyStatus )( m_status & mask );\r\n\t\t\t\tm_statusChanged    = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tbool out        = m_statusChanged;\r\n\tm_statusChanged = false;\r\n\treturn out;\r\n}\r\n\r\nAnatomyStatus Anatomy::status()\r\n{\r\n\treturn m_status;\r\n}\r\n\r\nvoid Anatomy::setFluidLevelonTile( unsigned char fluidLevel )\r\n{\r\n\tif ( fluidLevel > 5 && !m_isAquatic )\r\n\t{\r\n\t\tm_status        = AnatomyStatus( m_status | AS_DEAD );\r\n\t\tm_statusChanged = true;\r\n\t\tqDebug() << \"Anatomy: Dead! Drowned\";\r\n\t}\r\n}\r\n\r\nAnatomyHeight Anatomy::randomAttackHeight() const\r\n{\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\tauto ra = rand() % 100;\r\n\r\n\tif ( ra < 50 )\r\n\t\treturn AH_MIDDLE;\r\n\telse if ( ra < 75 )\r\n\t\treturn AH_LOW;\r\n\treturn AH_HIGH;\r\n}\r\n\r\nvoid Anatomy::heal()\r\n{\r\n\tif ( m_status | AS_WOUNDED )\r\n\t{\r\n\t\tbool stillWounded = false;\r\n\r\n\t\tfor ( auto& part : m_parts )\r\n\t\t{\r\n\t\t\tif ( part.hp > 0 && part.hp < part.maxHP )\r\n\t\t\t{\r\n\t\t\t\tpart.hp += 0.025;\r\n\t\t\t\tif ( part.hp < part.maxHP )\r\n\t\t\t\t{\r\n\t\t\t\t\tstillWounded = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( !stillWounded )\r\n\t\t{\r\n\t\t\tunsigned char mask = 0xFF ^ AS_WOUNDED;\r\n\t\t\tm_status           = ( AnatomyStatus )( m_status & mask );\r\n\t\t\tm_statusChanged    = true;\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/game/anatomy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/enums.h\"\r\n\r\n#include <QSet>\r\n#include <QString>\r\n#include <QVariantMap>\r\n\r\nstruct Equipment;\r\n\r\nstruct AnatomyPart\r\n{\r\n\tCreaturePart id;\r\n\r\n\tCreaturePart parent = (CreaturePart)KCP_NONE;\r\n\tQList<CreaturePart> children;\r\n\r\n\tbool isInside = false;\r\n\tbool isVital  = false;\r\n\r\n\tAnatomyHeight height;\r\n\tAnatomySide side;\r\n\r\n\tint hp;\r\n\tint maxHP;\r\n};\r\n\r\nclass Anatomy\r\n{\r\n\tfriend class GnomeWidget;\r\n\tfriend class MonsterWidget;\r\n\tfriend class AnimalWidget;\r\n\r\npublic:\r\n\tAnatomy();\r\n\t~Anatomy();\r\n\r\n\tvoid init( QString type, bool isAquatic );\r\n\tQVariantMap serialize() const;\r\n\tvoid deserialize( QVariantMap state );\r\n\r\n\tvoid damage( Equipment* eq, DamageType dt, AnatomyHeight da, AnatomySide ds, int strength );\r\n\r\n\tvoid heal();\r\n\r\n\tbool statusChanged();\r\n\tAnatomyStatus status();\r\n\r\n\tvoid setFluidLevelonTile( unsigned char fluidLevel );\r\n\r\n\tAnatomyHeight randomAttackHeight() const;\r\n\r\nprivate:\r\n\tQString m_type;\r\n\r\n\tbool m_isAquatic = false;\r\n\r\n\tfloat m_blood    = 5000;\r\n\tfloat m_bleeding = 0.0;\r\n\r\n\tbool m_statusChanged   = false;\r\n\tAnatomyStatus m_status = AS_HEALTHY;\r\n\r\n\tQHash<CreaturePart, AnatomyPart> m_parts;\r\n};\r\n"
  },
  {
    "path": "src/game/animal.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"animal.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n#include <QPixmap>\r\n\r\nAnimal::Animal( QString species, Position& pos, Gender gender, bool adult, Game* game ) :\r\n\tCreature( pos, species, gender, species, game )\r\n{\r\n\tinitTaskMap();\r\n\r\n\tQVariantMap avm = DB::selectRow( \"Animals\", m_species );\r\n\r\n\tm_aquatic  = avm.value( \"Aquatic\" ).toBool();\r\n\tm_btName   = avm.value( \"BehaviorTree\" ).toString();\r\n\tm_preyList = avm.value( \"Prey\" ).toString().split( \"|\" );\r\n\r\n\tm_isMulti = avm.value( \"IsMulti\" ).toBool();\r\n\r\n\tint hungerRand = ( rand() % 20 ) - 10;\r\n\tm_hunger       = 100 + hungerRand;\r\n\r\n\tif ( adult )\r\n\t{\r\n\t\tint numStates = DB::selectRows( \"Animals_States\", \"ID\", m_species ).size();\r\n\t\tsetState( numStates - 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetState( 0 );\r\n\t}\r\n\r\n\tm_type = CreatureType::ANIMAL;\r\n}\r\n\r\nAnimal::Animal( QVariantMap in, Game* game ) :\r\n\tCreature( in, game ),\r\n\t//bool m_tame = false;\r\n\tm_tame( in.value( \"Tame\" ).toBool() ),\r\n\tm_birthTick( in.value( \"BirthTick\" ).value<quint64>() ),\r\n\t//unsigned int m_pastureID = 0;\r\n\tm_pastureID( in.value( \"PastureID\" ).toUInt() ),\r\n\tm_inJob( in.value( \"InJob\" ).toUInt() ),\r\n\tm_produceTick( in.value( \"ProduceTick\" ).value<quint64>() ),\r\n\tm_lastSex( in.value( \"LastSex\" ).value<quint64>() ),\r\n\tm_currentPrey( in.value( \"CurrentPrey\" ).toUInt() ),\r\n\tm_inShed( in.value( \"InShed\" ).toUInt() ),\r\n\tm_producedAmount( in.value( \"ProducedAmount\" ).value<quint8>() ),\r\n\tm_produce( in.value( \"Produce\" ).toString() ),\r\n\tm_corpseToEat( in.value( \"CorpseToEat\" ).toUInt() ),\r\n\tm_dye( in.value( \"Dye\" ).toString() ),\r\n\tm_isMulti( in.value( \"IsMulti\" ).toBool() ),\r\n\tm_toButcher( in.value( \"ToButcher\" ).toBool() )\r\n{\r\n\tinitTaskMap();\r\n\r\n\tQVariantMap avm = DB::selectRow( \"Animals\", m_species );\r\n\r\n\tm_stateMap = DB::selectRows( \"Animals_States\", \"ID\", m_species ).at( m_state );\r\n\r\n\tm_aquatic  = avm.value( \"Aquatic\" ).toBool();\r\n\tm_preyList = avm.value( \"Prey\" ).toString().split( \"|\" );\r\n\r\n\tm_hunger = qMax( -10.f, in.value( \"Hunger\" ).toFloat() );\r\n\r\n\tsetState( m_state );\r\n\tm_stateChangeTick = in.value( \"sct\" ).value<quint64>();\r\n\r\n\tcheckInJob();\r\n}\r\n\r\nvoid Animal::serialize( QVariantMap& out )\r\n{\r\n\tcheckInJob(); // workaround until i find where the job leak is\r\n\r\n\t// animal\r\n\tout.insert( \"Tame\", m_tame );\r\n\tout.insert( \"BirthTick\", m_birthTick );\r\n\tout.insert( \"PastureID\", m_pastureID );\r\n\tout.insert( \"InJob\", m_inJob );\r\n\tout.insert( \"Hunger\", m_hunger );\r\n\r\n\tout.insert( \"BTName\", m_btName );\r\n\r\n\tout.insert( \"BirthTick\", m_birthTick );\r\n\tout.insert( \"ProduceTick\", m_produceTick );\r\n\tout.insert( \"LastSex\", m_lastSex );\r\n\tout.insert( \"CurrentPrey\", m_currentPrey );\r\n\tout.insert( \"InShed\", m_inShed );\r\n\tout.insert( \"ProducedAmount\", m_producedAmount );\r\n\tout.insert( \"Produce\", m_produce );\r\n\tout.insert( \"CorpseToEat\", m_corpseToEat );\r\n\tout.insert( \"Dye\", m_dye );\r\n\tout.insert( \"IsMulti\", m_isMulti );\r\n\tout.insert( \"ToButcher\", m_toButcher );\r\n\tCreature::serialize( out );\r\n}\r\n\r\nAnimal::Animal() :\r\n\tCreature( Position(), \"\", Gender::UNDEFINED, \"\", g )\r\n{\r\n\tinitTaskMap();\r\n}\r\n\r\nAnimal::~Animal()\r\n{\r\n}\r\n\r\nvoid Animal::checkInJob()\r\n{\r\n\tif ( m_inJob )\r\n\t{\r\n\t\tif ( !g->jm()->getJob( m_inJob ) )\r\n\t\t{\r\n\t\t\t//qDebug() << \"Animal:\" << m_id << \"has inJobID:\" << m_inJob << \" that doesn't exist\";\r\n\t\t\tm_inJob    = 0;\r\n\t\t\tm_followID = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Animal::init()\r\n{\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\r\n\r\n\tm_anatomy.init( \"Animal\", m_aquatic );\r\n\r\n\tloadBehaviorTree( m_btName );\r\n\r\n\tif ( m_btBlackBoard.contains( \"State\" ) )\r\n\t{\r\n\t\tQVariantMap btm = m_btBlackBoard.value( \"State\" ).toMap();\r\n\t\tif ( m_behaviorTree )\r\n\t\t{\r\n\t\t\tm_behaviorTree->deserialize( btm );\r\n\t\t\tm_btBlackBoard.remove( \"State\" );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Animal::updateSprite()\r\n{\r\n\tif ( m_isMulti )\r\n\t{\r\n\t\tm_multiSprites.clear();\r\n\t\tQString spriteName = m_stateMap.value( \"SpriteID\" ).toString();\r\n\t\tswitch ( m_facing )\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tspriteName += \"FR\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tspriteName += \"FL\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tspriteName += \"BL\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tspriteName += \"BR\";\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tauto rows = DB::selectRows( \"Creature_Layouts\", spriteName );\r\n\t\tfor ( const auto& row : rows )\r\n\t\t{\r\n\t\t\tauto spriteSID = row.value( \"Sprite\" ).toString();\r\n\t\t\tSprite* sprite = g->sf()->createAnimalSprite( spriteSID );\r\n\t\t\tif ( sprite )\r\n\t\t\t{\r\n\t\t\t\t//m_multiSprites.append( QPair<Position, unsigned int>( m_position + Position( row.value( \"Offset\" ) ), sprite->uID ) );\r\n\t\t\t\tm_multiSprites.append( { m_position + Position( row.value( \"Offset\" ) ), sprite->uID } );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSprite* sprite = nullptr;\r\n\t\tif ( m_dye.isEmpty() )\r\n\t\t{\r\n\t\t\tsprite = g->sf()->createAnimalSprite( m_stateMap.value( \"SpriteID\" ).toString() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprite = g->sf()->createAnimalSprite( m_stateMap.value( \"SpriteID\" ).toString() + m_dye );\r\n\t\t}\r\n\t\tif ( sprite )\r\n\t\t{\r\n\t\t\tm_hasTransparency = sprite->hasTransp;\r\n\t\t\tm_spriteID        = sprite->uID;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tqDebug() << \"*ERROR* failed to create sprite for \" << m_stateMap.value( \"ID\" ).toString() << \" state: \" << m_stateMap.value( \"ID2\" ).toString();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Animal::setDye( QString dye )\r\n{\r\n\tm_dye = dye;\r\n\tupdateSprite();\r\n}\r\n\r\nQString Animal::dye()\r\n{\r\n\treturn m_dye;\r\n}\r\n\r\nvoid Animal::updateMoveSpeed()\r\n{\r\n\t//TODO add animal values to movespeed table\r\n\t//int skill = getSkillLevel( \"Hauling\" );\r\n\tint speed   = 50; //DB::execQuery( \"SELECT Speed FROM MoveSpeed WHERE CREATURE = \\\"Gnome\\\" AND SkillLevel = \\\"\" + QString::number( skill ) + \"\\\"\" ).toInt();\r\n\tm_moveSpeed = qMax( 30, speed );\r\n}\r\n\r\nvoid Animal::initTaskMap()\r\n{\r\n\tusing namespace std::placeholders;\r\n\t//m_behaviors.insert( \"\", std::bind( &Animal::condition, this, _1 ) );\r\n\t//m_behaviors.insert( \"\", std::bind( &Animal::action, this, _1 ) );\r\n\tm_behaviors.insert( \"IsMale\", std::bind( &Animal::conditionIsMale, this, _1 ) );\r\n\tm_behaviors.insert( \"IsFemale\", std::bind( &Animal::conditionIsFemale, this, _1 ) );\r\n\tm_behaviors.insert( \"IsDay\", std::bind( &Animal::conditionIsDay, this, _1 ) );\r\n\tm_behaviors.insert( \"IsNight\", std::bind( &Animal::conditionIsNight, this, _1 ) );\r\n\tm_behaviors.insert( \"IsEgg\", std::bind( &Animal::conditionIsEgg, this, _1 ) );\r\n\tm_behaviors.insert( \"IsAdult\", std::bind( &Animal::conditionIsAdult, this, _1 ) );\r\n\tm_behaviors.insert( \"IsYoung\", std::bind( &Animal::conditionIsYoung, this, _1 ) );\r\n\tm_behaviors.insert( \"IsCarnivore\", std::bind( &Animal::conditionIsCarnivore, this, _1 ) );\r\n\tm_behaviors.insert( \"IsHerbivore\", std::bind( &Animal::conditionIsHerbivore, this, _1 ) );\r\n\tm_behaviors.insert( \"IsHungry\", std::bind( &Animal::conditionIsHungry, this, _1 ) );\r\n\tm_behaviors.insert( \"IsEggLayer\", std::bind( &Animal::conditionIsEggLayer, this, _1 ) );\r\n\tm_behaviors.insert( \"IsProducer\", std::bind( &Animal::conditionIsProducer, this, _1 ) );\r\n\tm_behaviors.insert( \"IsPregnant\", std::bind( &Animal::conditionIsPregnant, this, _1 ) );\r\n\tm_behaviors.insert( \"IsReadyToGiveBirth\", std::bind( &Animal::conditionIsReadyToGiveBirth, this, _1 ) );\r\n\tm_behaviors.insert( \"IsWoodVermin\", std::bind( &Animal::conditionIsWoodVermin, this, _1 ) );\r\n\tm_behaviors.insert( \"IsInShed\", std::bind( &Animal::conditionIsInShed, this, _1 ) );\r\n\tm_behaviors.insert( \"IsOnPasture\", std::bind( &Animal::conditionIsOnPasture, this, _1 ) );\r\n\tm_behaviors.insert( \"TargetAdjacent\", std::bind( &Animal::conditionTargetAdjacent, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"LayEgg\", std::bind( &Animal::actionLayEgg, this, _1 ) );\r\n\tm_behaviors.insert( \"Produce\", std::bind( &Animal::actionProduce, this, _1 ) );\r\n\tm_behaviors.insert( \"RandomMove\", std::bind( &Animal::actionRandomMove, this, _1 ) );\r\n\tm_behaviors.insert( \"TryHaveSex\", std::bind( &Animal::actionTryHaveSex, this, _1 ) );\r\n\tm_behaviors.insert( \"GiveBirth\", std::bind( &Animal::actionGiveBirth, this, _1 ) );\r\n\tm_behaviors.insert( \"FindPrey\", std::bind( &Animal::actionFindPrey, this, _1 ) );\r\n\tm_behaviors.insert( \"KillPrey\", std::bind( &Animal::actionKillPrey, this, _1 ) );\r\n\tm_behaviors.insert( \"EatPrey\", std::bind( &Animal::actionEatPrey, this, _1 ) );\r\n\tm_behaviors.insert( \"Move\", std::bind( &Animal::actionMove, this, _1 ) );\r\n\tm_behaviors.insert( \"FindRetreat\", std::bind( &Animal::actionFindRetreat, this, _1 ) );\r\n\tm_behaviors.insert( \"Sleep\", std::bind( &Animal::actionSleep, this, _1 ) );\r\n\tm_behaviors.insert( \"FindShed\", std::bind( &Animal::actionFindShed, this, _1 ) );\r\n\tm_behaviors.insert( \"EnterShed\", std::bind( &Animal::actionEnterShed, this, _1 ) );\r\n\tm_behaviors.insert( \"LeaveShed\", std::bind( &Animal::actionLeaveShed, this, _1 ) );\r\n\tm_behaviors.insert( \"FindRandomPastureField\", std::bind( &Animal::actionFindRandomPastureField, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"GuardDogGetTarget\", std::bind( &Animal::actionGuardDogGetTarget, this, _1 ) );\r\n\tm_behaviors.insert( \"GetTarget\", std::bind( &Animal::actionGetTarget, this, _1 ) );\r\n\tm_behaviors.insert( \"AttackTarget\", std::bind( &Animal::actionAttackTarget, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"Graze\", std::bind( &Animal::actionGraze, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"RandomMoveBig\", std::bind( &Animal::actionRandomMoveBig, this, _1 ) );\r\n}\r\n\r\nvoid Animal::setState( int state )\r\n{\r\n\tm_state = state;\r\n\r\n\tm_stateMap = DB::selectRows( \"Animals_States\", \"ID\", m_species ).at( state );\r\n\r\n\tloadBehaviorTree( m_stateMap.value( \"BehaviorTree\" ).toString() );\r\n\r\n\tupdateSprite();\r\n\r\n\tint days = m_stateMap.value( \"DaysToNextState\" ).toInt();\r\n\tif ( days )\r\n\t{\r\n\t\tm_stateChangeTick = GameState::tick + ( Global::util->ticksPerDayRandomized( 5 ) * days );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_stateChangeTick = 0;\r\n\t}\r\n\r\n\tQString behaviorID = m_species + m_stateMap.value( \"ID2\" ).toString();\r\n\r\n\tauto behaviorList = DB::selectRows( \"Animals_States_Behavior\", behaviorID );\r\n\tfor ( const auto& vBehavior : behaviorList )\r\n\t{\r\n\t\tQString behavior = vBehavior.value( \"ID2\" ).toString();\r\n\t\tm_stateMap.insert( behavior, vBehavior );\r\n\t}\r\n\r\n\tm_isProducer = [this]() {\r\n\t\tif ( m_stateMap.contains( \"Producer\" ) )\r\n\t\t{\r\n\t\t\tQVariantMap def = m_stateMap.value( \"Producer\" ).toMap();\r\n\t\t\tif ( def.contains( \"RequiredGender\" ) )\r\n\t\t\t{\r\n\t\t\t\tGender g = def.value( \"RequiredGender\" ).toString() == \"male\" ? Gender::MALE : Gender::FEMALE;\r\n\t\t\t\tif ( m_gender != g )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}();\r\n\r\n\tm_isEggLayer = [this]() {\r\n\t\tif ( m_gender == Gender::FEMALE )\r\n\t\t{\r\n\t\t\tif ( m_stateMap.contains( \"EggLayer\" ) )\r\n\t\t\t{\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\tm_isGrazer = [this]() {\r\n\t\tif ( m_stateMap.contains( \"Grazing\" ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}();\r\n\r\n\tm_isEgg   = isEgg();\r\n\tm_isYoung = isYoung();\r\n\tm_isAdult = isAdult();\r\n\r\n\tm_immobile            = m_stateMap.value( \"Immobile\" ).toBool();\r\n\tm_renderParamsChanged = true;\r\n\r\n\tm_foodValue = m_stateMap.value( \"Grazing\" ).toMap().value( \"FoodValue\" ).toInt();\r\n}\r\n\r\nCreatureTickResult Animal::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tprocessCooldowns( tickNumber );\r\n\r\n\tm_anatomy.setFluidLevelonTile( g->w()->fluidLevel( m_position ) );\r\n\r\n\tif ( m_anatomy.statusChanged() )\r\n\t{\r\n\t\tauto status = m_anatomy.status();\r\n\t\tif ( status & AS_DEAD )\r\n\t\t{\r\n\t\t\tGlobal::logger().log( LogType::COMBAT, \"The \" + m_name + \" died. Bummer!\", m_id );\r\n\t\t\tdie();\r\n\t\t\t// TODO check for other statuses\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_toDestroy )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::TODESTROY;\r\n\t}\r\n\tif ( isDead() )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::DEAD;\r\n\t}\r\n\r\n\tPosition oldPos = m_position;\r\n\r\n\tif ( m_followID && !m_followPosition.isZero() && m_position != m_followPosition )\r\n\t{\r\n\t\tm_position = m_followPosition;\r\n\t\tmove( oldPos );\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::OK;\r\n\t}\r\n\r\n\tif ( minuteChanged && !isEgg() )\r\n\t{\r\n\t\tm_hunger = qMax( -10., m_hunger - 0.075 );\r\n\t}\r\n\r\n\tif ( m_stateChangeTick != 0 && tickNumber >= m_stateChangeTick /* && m_currentAction == \"idle\" */ )\r\n\t{\r\n\t\t++m_state;\r\n\t\tsetState( m_state );\r\n\t}\r\n\r\n\tsetThoughtBubble( \"\" );\r\n\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tm_behaviorTree->tick();\r\n\t}\r\n\r\n\tmove( oldPos );\r\n\r\n\tm_lastOnTick = tickNumber;\r\n\r\n\treturn CreatureTickResult::OK;\r\n}\r\n\r\nvoid Animal::move( Position oldPos )\r\n{\r\n\tif ( m_isMulti )\r\n\t{\r\n\t\tif ( m_position != oldPos )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Creature_Layouts\", m_species );\r\n\t\t\tfor ( const auto& row : rows )\r\n\t\t\t{\r\n\t\t\t\tPosition offset( row.value( \"Offset\" ) );\r\n\t\t\t\tg->w()->setWallSprite( oldPos + offset, 0 );\r\n\t\t\t}\r\n\t\t\tfor ( const auto& row : rows )\r\n\t\t\t{\r\n\t\t\t\tPosition offset( row.value( \"Offset\" ) );\r\n\t\t\t\tg->w()->setWallSprite( m_position + offset, g->sf()->createSprite( row.value( \"Sprite\" ).toString(), { \"none\" } )->uID );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tCreature::move( oldPos );\r\n\t}\r\n}\r\n\r\nbool Animal::isEgg()\r\n{\r\n\treturn m_stateMap.value( \"ID2\" ).toString() == \"Egg\";\r\n}\r\n\r\nbool Animal::isYoung()\r\n{\r\n\treturn m_stateMap.value( \"ID2\" ).toString() == \"Young\";\r\n}\r\n\r\nbool Animal::isAdult()\r\n{\r\n\treturn m_stateMap.value( \"ID2\" ).toString() == \"Adult\";\r\n}\r\n\r\nBT_RESULT Animal::conditionIsEgg( bool halt )\r\n{\r\n\tif ( m_isEgg )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsYoung( bool halt )\r\n{\r\n\tif ( m_isYoung )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsAdult( bool halt )\r\n{\r\n\tif ( m_isAdult )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsHungry( bool halt )\r\n{\r\n\tif ( m_hunger < 30 )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsCarnivore( bool halt )\r\n{\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsHerbivore( bool halt )\r\n{\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsPregnant( bool halt )\r\n{\r\n\tif ( m_birthTick )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsReadyToGiveBirth( bool halt )\r\n{\r\n\tif ( m_birthTick && GameState::tick > m_birthTick )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsWoodVermin( bool halt )\r\n{\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsEggLayer( bool halt )\r\n{\r\n\tif ( m_isEggLayer )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionLayEgg( bool halt )\r\n{\r\n\tif ( m_pastureID == 0 )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( !m_birthTick )\r\n\t{\r\n\t\tQVariantMap def = m_stateMap.value( \"EggLayer\" ).toMap();\r\n\t\t//first visit;\r\n\t\tint days        = def.value( \"DaysBetween\" ).toInt();\r\n\t\tquint64 nextLay = GameState::tick + ( Global::util->ticksPerDayRandomized( 5 ) * days );\r\n\t\tm_birthTick     = nextLay;\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_birthTick && GameState::tick >= m_birthTick && m_hunger > 50 )\r\n\t{\r\n\t\tQVariantMap def  = m_stateMap.value( \"EggLayer\" ).toMap();\r\n\t\tbool collectEggs = false;\r\n\t\tif ( m_pastureID != 0 )\r\n\t\t{\r\n\t\t\tPasture* pasture = g->fm()->getPasture( m_pastureID );\r\n\t\t\tif ( pasture )\r\n\t\t\t{\r\n\t\t\t\tcollectEggs = pasture->harvest();\r\n\t\t\t}\r\n\t\t}\r\n\t\tint totalCount = g->cm()->count( m_species );\r\n\t\tif ( ( totalCount < GameState::maxAnimalsPerType && totalCount < 1000 ) || collectEggs )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < def.value( \"Amount\" ).toInt(); ++i )\r\n\t\t\t{\r\n\t\t\t\tif ( collectEggs )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( m_position, \"Egg\", { m_species } );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, def.value( \"EggID\" ).toString(), m_position, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE, false, m_tame );\r\n\t\t\t\t\tif ( g->cm()->count( m_species ) >= GameState::maxAnimalsPerType )\r\n\t\t\t\t\t{\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\tm_birthTick = 0;\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_birthTick = 0;\r\n\t\t}\r\n\t}\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsProducer( bool halt )\r\n{\r\n\tif ( m_isProducer )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionProduce( bool halt )\r\n{\r\n\tif ( !m_produceTick )\r\n\t{\r\n\t\t//first visit;\r\n\t\tQVariantMap def  = m_stateMap.value( \"Producer\" ).toMap();\r\n\t\tint days         = def.value( \"DaysBetween\" ).toInt();\r\n\t\tquint64 nextProd = GameState::tick + ( Global::util->ticksPerDayRandomized( 5 ) * days );\r\n\t\tm_produceTick    = nextProd;\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_produceTick && GameState::tick >= m_produceTick && m_hunger > 50 )\r\n\t{\r\n\t\t// produce item\r\n\t\tQVariantMap def = m_stateMap.value( \"Producer\" ).toMap();\r\n\t\tif ( def.value( \"Auto\" ).toBool() )\r\n\t\t{\r\n\t\t\tQString produce = def.value( \"ItemID\" ).toString();\r\n\t\t\tfor ( int i = 0; i < def.value( \"Amount\" ).toInt(); ++i )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->createItem( m_position, def.value( \"ItemID\" ).toString(), { m_species } );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint amount = def.value( \"Amount\" ).toInt();\r\n\t\t\tif ( m_producedAmount < amount )\r\n\t\t\t{\r\n\t\t\t\tm_produce = def.value( \"ItemID\" ).toString();\r\n\t\t\t\t++m_producedAmount;\r\n\t\t\t}\r\n\t\t}\r\n\t\tint days         = def.value( \"DaysBetween\" ).toInt();\r\n\t\tquint64 nextProd = GameState::tick + ( Global::util->ticksPerDayRandomized( 5 ) * days );\r\n\t\tm_produceTick    = nextProd;\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionTryHaveSex( bool halt )\r\n{\r\n\tif ( m_gender == Gender::MALE && m_isAdult && m_hunger > 50 )\r\n\t{\r\n\t\tint totalCount = g->cm()->count( m_species );\r\n\t\tif ( totalCount < GameState::maxAnimalsPerType && totalCount < 1000 )\r\n\t\t{\r\n\t\t\t//isOnPasture\r\n\t\t\tif ( m_pastureID )\r\n\t\t\t{\r\n\t\t\t\t//last sex longer than 24 hours ago\r\n\t\t\t\tif ( m_lastSex + Global::util->ticksPerDay < GameState::tick )\r\n\t\t\t\t{\r\n\t\t\t\t\t// non pregnant female on pasture\r\n\t\t\t\t\tPasture* pasture = g->fm()->getPasture( m_pastureID );\r\n\t\t\t\t\tif ( pasture )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto list = pasture->animals();\r\n\t\t\t\t\t\tfor ( auto id : list )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tauto a = g->cm()->animal( id );\r\n\t\t\t\t\t\t\tif ( a->gender() == Gender::FEMALE && !a->isPregnant() && a->isAdult() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\ta->setPregnant( true );\r\n\t\t\t\t\t\t\t\tm_lastSex = GameState::tick;\r\n\t\t\t\t\t\t\t\treturn BT_RESULT::SUCCESS;\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\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionGiveBirth( bool halt )\r\n{\r\n\t// birth tick reached\r\n\tif ( m_birthTick && GameState::tick > m_birthTick )\r\n\t{\r\n\t\tint totalCount = g->cm()->count( m_species );\r\n\t\tif ( ( totalCount < GameState::maxAnimalsPerType && totalCount < 1000 ) )\r\n\t\t{\r\n\t\t\t// create baby\r\n\t\t\tsetPregnant( false );\r\n\t\t\tunsigned int babyID = g->cm()->addCreature( CreatureType::ANIMAL, m_species, m_position, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE, false, m_tame );\r\n\t\t\t// if mother on pasture and space on pasture\r\n\t\t\tPasture* pasture = g->fm()->getPasture( m_pastureID );\r\n\t\t\tif ( pasture )\r\n\t\t\t{\r\n\t\t\t\tpasture->addAnimal( babyID );\r\n\t\t\t}\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nvoid Animal::setPregnant( bool pregnant )\r\n{\r\n\tif ( pregnant )\r\n\t{\r\n\t\tint days      = DB::select( \"GestationDays\", \"Animals\", m_species ).toInt();\r\n\t\tquint64 ticks = Global::util->ticksPerDayRandomized( 5 ) * days;\r\n\t\tm_birthTick   = GameState::tick + ticks;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_birthTick = 0;\r\n\t}\r\n}\r\n\r\nbool Animal::isPregnant()\r\n{\r\n\treturn m_birthTick != 0;\r\n}\r\n\r\nvoid Animal::setTame( bool tame )\r\n{\r\n\tm_tame = tame;\r\n}\r\n\r\nbool Animal::isTame()\r\n{\r\n\treturn m_tame;\r\n}\r\n\r\nbool Animal::isAggro()\r\n{\r\n\treturn m_stateMap.value( \"IsAggro\" ).toBool();\r\n}\r\n\r\nvoid Animal::setPastureID( unsigned int id )\r\n{\r\n\tm_pastureID = id;\r\n}\r\n\r\nunsigned int Animal::pastureID()\r\n{\r\n\treturn m_pastureID;\r\n}\r\n\r\nint Animal::numProduce()\r\n{\r\n\treturn m_producedAmount;\r\n}\r\n\r\nQString Animal::producedItem()\r\n{\r\n\treturn m_produce;\r\n}\r\n\r\nvoid Animal::harvest()\r\n{\r\n\tm_producedAmount = 0;\r\n\tm_produce        = \"\";\r\n\tif ( !m_dye.isEmpty() )\r\n\t{\r\n\t\tm_dye = \"\";\r\n\t\tupdateSprite();\r\n\t}\r\n}\r\n\r\nbool Animal::morph( QVariantMap def )\r\n{\r\n\tg->cm()->addCreature( CreatureType::ANIMAL, def.value( \"CreatureID\" ).toString(), m_position, m_gender, false, m_tame );\r\n\tm_toDestroy = true;\r\n\treturn true;\r\n}\r\n\r\nvoid Animal::setInJob( unsigned int id )\r\n{\r\n\tm_inJob = id;\r\n}\r\n\r\nunsigned int Animal::inJob()\r\n{\r\n\treturn m_inJob;\r\n}\r\n\r\nfloat Animal::hunger()\r\n{\r\n\treturn m_hunger;\r\n}\r\n\r\nBT_RESULT Animal::actionGraze( bool halt )\r\n{\r\n\tif ( m_hunger < 80 )\r\n\t{\r\n\t\tTile& tile = g->w()->getTile( m_position );\r\n\t\tif ( m_isGrazer )\r\n\t\t{\r\n\t\t\tif ( tile.flags & TileFlag::TF_GRASS && tile.vegetationLevel > 10 )\r\n\t\t\t{\r\n\t\t\t\tif ( tile.flags & TileFlag::TF_PASTURE )\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.vegetationLevel = qMax( 10, tile.vegetationLevel - 1 );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tm_hunger += m_foodValue;\r\n\r\n\t\t\t\tg->w()->addToUpdateList( m_position );\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( m_pastureID && (bool)( tile.flags & TileFlag::TF_PASTURE ) )\r\n\t\t{\r\n\t\t\tauto pasture =  g->fm()->getPastureAtPos( m_position );\r\n\t\t\tif ( pasture && pasture->id() == m_pastureID )\r\n\t\t\t{\r\n\t\t\t\tif ( pasture->eatFromTrough() )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_hunger += m_foodValue * 5;\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionFindPrey( bool halt )\r\n{\r\n\tfor ( const auto& sPrey : m_preyList )\r\n\t{\r\n\t\tAnimal* prey = g->cm()->getClosestAnimal( m_position, sPrey );\r\n\t\tif ( prey )\r\n\t\t{\r\n\t\t\tQList<Position> neighbs = Global::util->neighbors8( prey->getPos() );\r\n\t\t\tauto distances          = PriorityQueue<Position, int>();\r\n\t\t\tfor ( const auto& neigh : neighbs )\r\n\t\t\t{\r\n\t\t\t\tif ( g->w()->isWalkable( neigh ) && g->pf()->checkConnectedRegions( neigh, m_position ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tdistances.put( neigh, m_position.distSquare( neigh ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( distances.empty() )\r\n\t\t\t{\r\n\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t}\r\n\t\t\tsetCurrentTarget( distances.get() );\r\n\t\t\tm_currentPrey = prey->id();\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\tm_currentPrey = 0;\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionKillPrey( bool halt )\r\n{\r\n\t//TODO check if adjacent\r\n\r\n\tAnimal* prey = g->cm()->animal( m_currentPrey );\r\n\tif ( prey )\r\n\t{\r\n\t\tif ( prey->kill( true ) )\r\n\t\t{\r\n\t\t\tm_corpseToEat = g->inv()->createItem( prey->getPos(), \"AnimalCorpse\", { prey->species() } );\r\n\t\t\tm_currentPrey = 0;\r\n\t\t\tg->inv()->setInJob( m_corpseToEat, m_id );\r\n\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\tm_currentPrey = 0;\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionEatPrey( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\tm_corpseToEat = 0;\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( m_corpseToEat )\r\n\t{\r\n\t\tm_hunger += 0.5;\r\n\t\tif ( m_hunger >= 100 )\r\n\t\t{\r\n\t\t\tg->inv()->createItem( Position( g->inv()->getItemPos( m_corpseToEat ) ), \"Bone\", g->inv()->materialSID( m_corpseToEat ) + \"Bone\" );\r\n\r\n\t\t\tg->inv()->destroyObject( m_corpseToEat );\r\n\t\t\tm_corpseToEat = 0;\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tm_corpseToEat = 0;\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionMove( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\tm_currentPrey = 0;\r\n\t\tm_currentPath.clear();\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( m_immobile )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\t// gnome has a path, move on path and return\r\n\tif ( !m_currentPath.empty() )\r\n\t{\r\n\t\tif ( m_currentAttackTarget )\r\n\t\t{\r\n\t\t\tif ( conditionTargetAdjacent( false ) == BT_RESULT::SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\r\n\t\t\tif ( conditionTargetPositionValid( false ) == BT_RESULT::FAILURE )\r\n\t\t\t{\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !moveOnPath() )\r\n\t\t{\r\n\t\t\tm_currentPath.clear();\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tPosition targetPos = currentTarget();\r\n\r\n\t// check if we are already on the tile\r\n\tif ( m_position == targetPos )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tPathFinderResult pfr = g->pf()->getPath( m_id, m_position, targetPos, m_ignoreNoPass, m_currentPath );\r\n\tswitch ( pfr )\r\n\t{\r\n\t\tcase PathFinderResult::NoConnection:\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\tcase PathFinderResult::Running:\r\n\t\tcase PathFinderResult::FoundPath:\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Animal::actionFindRetreat( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tint randPos = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\r\n\tPosition pos( 0, 0, Global::dimZ - 1 );\r\n\tint border = rand() % 4;\r\n\tswitch ( border )\r\n\t{\r\n\t\tcase 0: //north\r\n\t\t\tpos.x = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\t\t\tpos.y = qMax( 2, rand() % 10 );\r\n\t\t\tbreak;\r\n\t\tcase 1: //east\r\n\t\t\tpos.x = Global::dimX - qMax( 2, rand() % 10 );\r\n\t\t\tpos.y = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\t\t\tbreak;\r\n\t\tcase 2: //south\r\n\t\t\tpos.x = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\t\t\tpos.y = Global::dimX - qMax( 2, rand() % 10 );\r\n\t\t\tbreak;\r\n\t\tcase 3: // west\r\n\t\t\tpos.x = qMax( 2, rand() % 10 );\r\n\t\t\tpos.y = qMax( 2, rand() % ( Global::dimX - 2 ) );\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tg->w()->getFloorLevelBelow( pos, false );\r\n\r\n\tif ( g->w()->fluidLevel( pos ) == 0 )\r\n\t{\r\n\t\tif ( g->pf()->checkConnectedRegions( pos, m_position ) )\r\n\t\t{\r\n\t\t\tsetCurrentTarget( pos );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionSleep( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tsetThoughtBubble( \"Sleeping\" );\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsInShed( bool halt )\r\n{\r\n\tif ( m_inShed )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::conditionIsOnPasture( bool halt )\r\n{\r\n\tif ( m_pastureID )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionFindShed( bool halt )\r\n{\r\n\tif ( m_pastureID )\r\n\t{\r\n\t\tPasture* pasture = g->fm()->getPasture( m_pastureID );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tPosition pos = pasture->findShed();\r\n\t\t\tif ( !pos.isZero() )\r\n\t\t\t{\r\n\t\t\t\tsetCurrentTarget( pos );\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionFindRandomPastureField( bool halt )\r\n{\r\n\tif ( m_pastureID )\r\n\t{\r\n\t\tPasture* pasture = g->fm()->getPasture( m_pastureID );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tint random = rand() % pasture->countTiles();\r\n\t\t\tsetCurrentTarget( pasture->randomFieldPos() );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionEnterShed( bool halt )\r\n{\r\n\tm_inShed = true;\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Animal::actionLeaveShed( bool halt )\r\n{\r\n\tm_inShed = false;\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Animal::actionGetTarget( bool halt )\r\n{\r\n\tif ( m_aggroList.size() )\r\n\t{\r\n\t\tunsigned int targetID = m_aggroList.first().id;\r\n\t\tCreature* creature    = g->cm()->creature( targetID );\r\n\t\tif ( !creature )\r\n\t\t{\r\n\t\t\tcreature = g->gm()->gnome( targetID );\r\n\t\t}\r\n\t\tif ( creature && !creature->isDead() )\r\n\t\t{\r\n\t\t\tm_currentAttackTarget = targetID;\r\n\t\t\tsetCurrentTarget( creature->getPos() );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_aggroList.removeFirst();\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//TODO even though aggro list is empty, check for other threats around\r\n\t}\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionGuardDogGetTarget( bool halt )\r\n{\r\n\tauto foxes = g->cm()->animalsByDistance( m_position, \"Fox\" );\r\n\tif ( !foxes.empty() )\r\n\t{\r\n\t\tauto fox = foxes.get();\r\n\t\tif ( m_position.distSquare( fox->getPos() ) < 40 )\r\n\t\t{\r\n\t\t\t//qDebug() << \"fox alert\";\r\n\t\t\tAggroEntry ae { 100, fox->id() };\r\n\t\t\tm_aggroList.append( ae );\r\n\t\t}\r\n\t}\r\n\treturn actionGetTarget( halt );\r\n}\r\n\r\nBT_RESULT Animal::actionAttackTarget( bool halt )\r\n{\r\n\tCreature* creature = g->gm()->gnome( m_currentAttackTarget );\r\n\tif ( !creature )\r\n\t{\r\n\t\tcreature = g->cm()->creature( m_currentAttackTarget );\r\n\t}\r\n\r\n\tif ( creature && !creature->isDead() )\r\n\t{\r\n\t\tm_facing = getFacing( m_position, creature->getPos() );\r\n\r\n\t\tif ( m_globalCooldown <= 0 )\r\n\t\t{\r\n\t\t\tif ( m_biteCooldown <= 0 )\r\n\t\t\t{\r\n\t\t\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" attacks \" + creature->name(), m_id );\r\n\t\t\t\t// attack with main hand\r\n\r\n\t\t\t\tint attackSkill  = m_stateMap.value( \"Attack\" ).toInt();\r\n\t\t\t\tint attackDamage = m_stateMap.value( \"Damage\" ).toInt();\r\n\r\n\t\t\t\tcreature->attack( DT_PIERCING, AH_LOW, attackSkill, attackDamage, m_position, m_id );\r\n\t\t\t\tm_biteCooldown   = 10;\r\n\t\t\t\tm_globalCooldown = 5;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\tm_currentAttackTarget = 0;\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Animal::actionRandomMoveBig( bool halt )\r\n{\r\n\t// get new possible location\r\n\r\n\t// remove old sprites\r\n\r\n\t// set new sprites\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nbool Animal::attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID )\r\n{\r\n\t// from which side is the attack coming\r\n\tAnatomySide ds = AS_CENTER;\r\n\tswitch ( m_facing )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tif ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_FRONT;\r\n\t\t\telse if ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_BACK;\r\n\t\t\tif ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_RIGHT );\r\n\t\t\telse if ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_LEFT );\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tif ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_LEFT;\r\n\t\t\telse if ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_RIGHT;\r\n\t\t\tif ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_FRONT );\r\n\t\t\telse if ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_BACK );\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tif ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_FRONT;\r\n\t\t\telse if ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_BACK;\r\n\t\t\tif ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_RIGHT );\r\n\t\t\telse if ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_LEFT );\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tif ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_LEFT;\r\n\t\t\telse if ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_RIGHT;\r\n\t\t\tif ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_FRONT );\r\n\t\t\telse if ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_BACK );\r\n\t\t\tbreak;\r\n\t}\r\n\t// attacker skill vs our dodge or block chance\r\n\r\n\tint dodge = getSkillLevel( \"Dodge\" );\r\n\tif ( ds & AS_BACK )\r\n\t{\r\n\t\tskill *= 1.5;\r\n\t}\r\n\r\n\tbool hit = skill >= dodge;\r\n\tif ( dodge > skill )\r\n\t{\r\n\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\tint diff = dodge - skill;\r\n\t\tdiff     = qMax( 5, 20 - diff );\r\n\t\thit |= rand() % 100 > diff;\r\n\t}\r\n\r\n\tif ( hit )\r\n\t{\r\n\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" took \" + QString::number( strength ) + \" damage.\", m_id );\r\n\t\tm_anatomy.damage( &m_equipment, dt, da, ds, strength );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" dogded the attack. Skill:\" + QString::number( skill ) + \" Dodge: \" + QString::number( dodge ), m_id );\r\n\t}\r\n\r\n\tbool aeExists = false;\r\n\tfor ( auto& ae : m_aggroList )\r\n\t{\r\n\t\tif ( ae.id == attackerID )\r\n\t\t{\r\n\t\t\tae.aggro += strength;\r\n\t\t\taeExists = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !aeExists )\r\n\t{\r\n\t\tAggroEntry newAE { strength, attackerID };\r\n\t\tm_aggroList.append( newAE );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool Animal::toButcher()\r\n{\r\n\treturn m_toButcher;\r\n}\r\n\r\nvoid Animal::setToButcher( bool value )\r\n{\r\n\tm_toButcher = value;\r\n}"
  },
  {
    "path": "src/game/animal.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"creature.h\"\r\n\r\n#include <QString>\r\n#include <QtGlobal>\r\n\r\nclass Animal : public Creature\r\n{\r\n\tfriend class AnimalWidget;\r\n\r\npublic:\r\n\tAnimal( QString species, Position& pos, Gender gender, bool adult, Game* game );\r\n\tAnimal( QVariantMap in, Game* game );\r\n\tAnimal();\r\n\t~Animal();\r\n\r\n\tvirtual void init();\r\n\r\n\tvirtual void updateSprite();\r\n\r\n\tvirtual void serialize( QVariantMap& out );\r\n\r\n\tvoid setState( int state );\r\n\r\n\tCreatureTickResult onTick( quint64 tick, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid setTame( bool tame );\r\n\tbool isTame();\r\n\r\n\tvoid setPregnant( bool pregnant );\r\n\tbool isPregnant();\r\n\r\n\tbool isEgg();\r\n\tbool isYoung();\r\n\tbool isAdult();\r\n\r\n\tbool isAggro();\r\n\r\n\tbool toButcher();\r\n\tvoid setToButcher( bool value );\r\n\r\n\tbool attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID );\r\n\r\n\tBT_RESULT conditionIsEgg( bool halt = false );\r\n\tBT_RESULT conditionIsYoung( bool halt = false );\r\n\tBT_RESULT conditionIsAdult( bool halt = false );\r\n\r\n\tBT_RESULT conditionIsHungry( bool halt = false );\r\n\tBT_RESULT conditionIsCarnivore( bool halt = false );\r\n\tBT_RESULT conditionIsHerbivore( bool halt = false );\r\n\r\n\tBT_RESULT conditionIsEggLayer( bool halt = false );\r\n\tBT_RESULT conditionIsProducer( bool halt = false );\r\n\r\n\tBT_RESULT conditionIsPregnant( bool halt = false );\r\n\r\n\tBT_RESULT conditionIsInShed( bool halt = false );\r\n\tBT_RESULT conditionIsOnPasture( bool halt = false );\r\n\r\n\tBT_RESULT conditionIsReadyToGiveBirth( bool halt = false );\r\n\tBT_RESULT conditionIsWoodVermin( bool halt = false );\r\n\tBT_RESULT actionLayEgg( bool halt );\r\n\tBT_RESULT actionProduce( bool halt );\r\n\r\n\tBT_RESULT actionTryHaveSex( bool halt );\r\n\tBT_RESULT actionGiveBirth( bool halt );\r\n\r\n\tBT_RESULT actionFindPrey( bool halt );\r\n\tBT_RESULT actionKillPrey( bool halt );\r\n\tBT_RESULT actionEatPrey( bool halt );\r\n\tBT_RESULT actionMove( bool halt );\r\n\r\n\tBT_RESULT actionFindRetreat( bool halt );\r\n\tBT_RESULT actionSleep( bool halt );\r\n\r\n\tBT_RESULT actionFindShed( bool halt );\r\n\tBT_RESULT actionFindRandomPastureField( bool halt );\r\n\tBT_RESULT actionEnterShed( bool halt );\r\n\tBT_RESULT actionLeaveShed( bool halt );\r\n\r\n\tBT_RESULT actionGetTarget( bool halt );\r\n\tBT_RESULT actionGuardDogGetTarget( bool halt );\r\n\tBT_RESULT actionAttackTarget( bool halt );\r\n\r\n\tBT_RESULT actionGraze( bool halt );\r\n\r\n\tBT_RESULT actionRandomMoveBig( bool halt );\r\n\r\n\tvoid setPastureID( unsigned int id );\r\n\tunsigned int pastureID();\r\n\r\n\tvoid setInJob( unsigned int id );\r\n\tunsigned int inJob();\r\n\r\n\tint numProduce();\r\n\tQString producedItem();\r\n\tvoid harvest();\r\n\r\n\tfloat hunger();\r\n\r\n\tvirtual void updateMoveSpeed();\r\n\r\n\tvoid setDye( QString dye );\r\n\tQString dye();\r\n\r\n\tbool isMulti()\r\n\t{\r\n\t\treturn m_isMulti;\r\n\t}\r\n\tQList<QPair<Position, unsigned int>> multiSprites()\r\n\t{\r\n\t\treturn m_multiSprites;\r\n\t};\r\n\r\nprivate:\r\n\tvoid initTaskMap();\r\n\r\n\tvoid checkInJob();\r\n\r\n\r\n\tbool m_isMulti = false;\r\n\tbool m_tame    = false;\r\n\r\n\tunsigned int m_pastureID = 0;\r\n\r\n\tunsigned int m_inJob = 0;\r\n\tfloat m_hunger       = 50;\r\n\tint m_foodValue      = 1;\r\n\r\n\tQVariantMap m_stateMap;\r\n\r\n\tbool m_isProducer = false;\r\n\tbool m_isEggLayer = false;\r\n\tbool m_isGrazer   = false;\r\n\r\n\tbool m_isEgg   = false;\r\n\tbool m_isYoung = false;\r\n\tbool m_isAdult = false;\r\n\r\n\tbool m_toButcher = false;\r\n\r\n\t//also used for egg laying\r\n\tquint64 m_birthTick = 0;\r\n\r\n\tquint64 m_produceTick = 0;\r\n\r\n\tquint64 m_lastSex = 0;\r\n\r\n\tQStringList m_preyList;\r\n\r\n\tunsigned int m_currentPrey = 0;\r\n\r\n\tbool m_inShed = false;\r\n\r\n\tquint8 m_producedAmount = 0;\r\n\tQString m_produce;\r\n\r\n\tunsigned int m_corpseToEat = 0;\r\n\r\n\tQString m_dye;\r\n\r\n\tvoid move( Position oldPos );\r\n\r\n\t// behaviors\r\n\tbool morph( QVariantMap def );\r\n\r\n\tQList<QPair<Position, unsigned int>> m_multiSprites;\r\n};\r\n"
  },
  {
    "path": "src/game/automaton.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"automaton.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QDebug>\r\n\r\nAutomaton::Automaton( Position pos, unsigned int automatonItem, Game* game ) :\r\n\tGnome( pos, \"Automaton\", Gender::UNDEFINED, game ),\r\n\tm_automatonItem( automatonItem )\r\n{\r\n\tm_type = CreatureType::AUTOMATON;\r\n\r\n\tinit();\r\n}\r\n\r\nAutomaton::Automaton( QVariantMap& in, Game* game ) :\r\n\tGnome( in, game )\r\n{\r\n\tm_type = CreatureType::AUTOMATON;\r\n\r\n\tm_core            = in.value( \"Core\" ).toUInt();\r\n\tm_fuel            = in.value( \"Fuel\" ).toFloat();\r\n\tm_automatonItem   = in.value( \"AutoItem\" ).toInt();\r\n\tm_coreType        = in.value( \"CoreType\" ).toString();\r\n\tm_uninstallCore   = in.value( \"UninstallFlag\" ).toBool();\r\n\tunsigned int maintenaceJobID = in.value( \"MaintenanceJob\" ).toUInt();\r\n\tif( maintenaceJobID )\r\n\t{\r\n\t\tm_maintenaceJob = game->jm()->getJob( maintenaceJobID );\r\n\t}\r\n\r\n\tm_maintJobChanged = in.value( \"MaintJobChanged\" ).toBool();\r\n\tm_refuel          = in.value( \"Refuel\" ).toBool();\r\n\r\n\tinit();\r\n}\r\n\r\nvoid Automaton::serialize( QVariantMap& out )\r\n{\r\n\tGnome::serialize( out );\r\n\r\n\tout.insert( \"Core\", m_core );\r\n\tout.insert( \"Fuel\", m_fuel );\r\n\tout.insert( \"AutoItem\", m_automatonItem );\r\n\tout.insert( \"CoreType\", m_coreType );\r\n\tout.insert( \"UninstallFlag\", m_uninstallCore );\r\n\tout.insert( \"MaintenanceJob\", maintenanceJobID() );\r\n\tout.insert( \"MaintJobChanged\", m_maintJobChanged );\r\n\tout.insert( \"Refuel\", m_refuel );\r\n}\r\n\r\nAutomaton::~Automaton()\r\n{\r\n}\r\n\r\nvoid Automaton::init()\r\n{\r\n\tinitTaskMap();\r\n\r\n\tif ( m_core )\r\n\t{\r\n\t\tQString itemSID = g->inv()->itemSID( m_core );\r\n\r\n\t\tauto row = DB::selectRow( \"Automaton_Cores\", itemSID );\r\n\t\tloadBehaviorTree( row.value( \"BehaviorTree\" ).toString() );\r\n\r\n\t\tif ( m_btBlackBoard.contains( \"State\" ) )\r\n\t\t{\r\n\t\t\tQVariantMap btm = m_btBlackBoard.value( \"State\" ).toMap();\r\n\t\t\tif ( m_behaviorTree )\r\n\t\t\t{\r\n\t\t\t\tm_behaviorTree->deserialize( btm );\r\n\t\t\t\tm_btBlackBoard.remove( \"State\" );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_needs.remove( \"Sleep\" );\r\n\tm_needs.remove( \"Hunger\" );\r\n\tm_needs.remove( \"Thirst\" );\r\n\tm_needs.remove( \"Happiness\" );\r\n\tm_needs.insert( \"Fuel\", m_fuel );\r\n\r\n\t/*\r\n\tm_skills.clear();\r\n\tm_skillActive.clear();\r\n\tm_skillPriorities.clear();\r\n\t*/\r\n\tupdateSprite();\r\n}\r\n\r\nvoid Automaton::updateSprite()\r\n{\r\n\tQString material = g->inv()->materialSID( m_automatonItem );\r\n\r\n\tauto components = g->inv()->components( m_automatonItem );\r\n\tQMap<QString, QString> compMats;\r\n\tfor ( auto vcomp : components )\r\n\t{\r\n\t\tauto comp = vcomp.toMap();\r\n\t\tauto it = comp.value( \"ItSID\" ).toString();\r\n\t\tauto ma = comp.value( \"MaSID\" ).toString();\r\n\r\n\t\tif ( it.endsWith( \"Leg\" ) || it.endsWith( \"Arm\" ) )\r\n\t\t{\r\n\t\t\tif ( compMats.contains( it + \"Left\" ) )\r\n\t\t\t{\r\n\t\t\t\tcompMats.insert( it + \"Right\", ma );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcompMats.insert( it + \"Left\", ma );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcompMats.insert( it, ma );\r\n\t\t}\r\n\t}\r\n\tQString itemSID = g->inv()->itemSID( m_automatonItem );\r\n\tauto parts      = DB::selectRows( \"Creature_Parts\", itemSID );\r\n\r\n\tQVariantMap ordered;\r\n\tfor ( auto pm : parts )\r\n\t{\r\n\t\tordered.insert( pm.value( \"Order\" ).toString(), pm );\r\n\t}\r\n\r\n\tQVariantMap randTemp;\r\n\r\n\tQVariantList def;\r\n\tfor ( auto vpm : ordered )\r\n\t{\r\n\t\tauto pm = vpm.toMap();\r\n\t\tif ( pm.value( \"BaseSprite\" ).toString().startsWith( \"#\" ) )\r\n\t\t{\r\n\t\t\tQString bsa = pm.value( \"BaseSprite\" ).toString();\r\n\t\t\tbsa.remove( 0, 1 );\r\n\t\t\tauto bsl = bsa.split( \"|\" );\r\n\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\t\tint rn = rand() % bsl.size();\r\n\t\t\trandTemp.insert( pm.value( \"Part\" ).toString() + \"Rand\", rn );\r\n\t\t\tpm.insert( \"BaseSprite\", bsl[rn] );\r\n\t\t}\r\n\t\tQString idPart = pm.value( \"ID\" ).toString() + pm.value( \"Part\" ).toString();\r\n\t\tif ( compMats.contains( idPart ) )\r\n\t\t{\r\n\t\t\tpm.insert( \"Material\", compMats.value( idPart ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpm.insert( \"Material\", material );\r\n\t\t}\r\n\t\tif ( idPart == \"AutomatonEye\" )\r\n\t\t{\r\n\t\t\tif ( m_fuel > 0 )\r\n\t\t\t{\r\n\t\t\t\tdef.append( pm );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdef.append( pm );\r\n\t\t}\r\n\t}\r\n\r\n\tauto partsBack = DB::selectRows( \"Creature_Parts\", itemSID + \"Back\" );\r\n\r\n\tQVariantMap orderedBack;\r\n\tfor ( auto pm : partsBack )\r\n\t{\r\n\t\torderedBack.insert( pm.value( \"Order\" ).toString(), pm );\r\n\t}\r\n\r\n\tQVariantList defBack;\r\n\tfor ( auto vpm : orderedBack )\r\n\t{\r\n\t\tauto pm = vpm.toMap();\r\n\t\tif ( pm.value( \"BaseSprite\" ).toString().startsWith( \"#\" ) )\r\n\t\t{\r\n\t\t\tQString bsa = pm.value( \"BaseSprite\" ).toString();\r\n\t\t\tbsa.remove( 0, 1 );\r\n\t\t\tauto bsl = bsa.split( \"|\" );\r\n\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\t\tint rn = randTemp.value( pm.value( \"Part\" ).toString() + \"Rand\" ).toInt();\r\n\t\t\tpm.insert( \"BaseSprite\", bsl[rn] + \"Back\" );\r\n\t\t}\r\n\t\tQString aid = pm.value( \"ID\" ).toString();\r\n\t\taid.chop( 4 );\r\n\t\tQString idPart = aid + pm.value( \"Part\" ).toString();\r\n\r\n\t\tif ( compMats.contains( idPart ) )\r\n\t\t{\r\n\t\t\tpm.insert( \"Material\", compMats.value( idPart ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tpm.insert( \"Material\", material );\r\n\t\t}\r\n\r\n\t\tif ( idPart == \"AutomatonFlame\" )\r\n\t\t{\r\n\t\t\tif ( m_fuel > 0 )\r\n\t\t\t{\r\n\t\t\t\tdefBack.append( pm );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tdefBack.append( pm );\r\n\t\t}\r\n\t}\r\n\r\n\tm_spriteID = g->sf()->setCreatureSprite( m_id, def, defBack, isDead() )->uID;\r\n\r\n\tm_renderParamsChanged = true;\r\n}\r\n\r\nCreatureTickResult Automaton::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tif ( m_fuel <= 0 )\r\n\t{\r\n\t\treturn CreatureTickResult::NOFUEL;\r\n\t}\r\n\t--m_fuel;\r\n\tif ( m_fuel <= 0 )\r\n\t{\r\n\t\tupdateSprite();\r\n\t}\r\n\r\n\tm_needs.insert( \"Fuel\", m_fuel );\r\n\r\n\tprocessCooldowns( tickNumber );\r\n\r\n\tm_jobChanged    = false;\r\n\tPosition oldPos = m_position;\r\n\r\n\tif ( checkFloor() )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::NOFLOOR;\r\n\t}\r\n\r\n\tif ( m_job && ( m_job->isAborted() || m_job->isCanceled() ) )\r\n\t{\r\n\t\tcleanUpJob( false );\r\n\t\tm_behaviorTree->halt();\r\n\t}\r\n\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tm_behaviorTree->tick();\r\n\t}\r\n\r\n\tmove( oldPos );\r\n\tupdateLight( oldPos, m_position );\r\n\r\n\tm_lastOnTick = tickNumber;\r\n\r\n\tif ( m_jobChanged )\r\n\t{\r\n\t\treturn CreatureTickResult::JOBCHANGED;\r\n\t}\r\n\treturn CreatureTickResult::OK;\r\n}\r\n\r\nvoid Automaton::installCore( unsigned int itemID )\r\n{\r\n\tif ( m_core )\r\n\t{\r\n\t\t//drop existing core\r\n\t\tg->inv()->setInJob( m_core, 0 );\r\n\t\tg->inv()->putDownItem( m_core, m_position );\r\n\t\tm_core = 0;\r\n\r\n\t\tm_behaviorTree.reset();\r\n\r\n\t\tm_skills.clear();\r\n\t\tm_skillActive.clear();\r\n\t\tm_skillPriorities.clear();\r\n\r\n\t\tm_uninstallCore = false;\r\n\t\tm_coreType      = \"\";\r\n\t}\r\n\t//install core\r\n\tif ( itemID )\r\n\t{\r\n\t\tQString itemSID = g->inv()->itemSID( itemID );\r\n\t\tif ( itemSID.startsWith( \"AutomatonCore\" ) )\r\n\t\t{\r\n\t\t\tm_core = itemID;\r\n\t\t\tg->inv()->pickUpItem( itemID, m_id );\r\n\r\n\t\t\tauto row = DB::selectRow( \"Automaton_Cores\", itemSID );\r\n\r\n\t\t\tloadBehaviorTree( row.value( \"BehaviorTree\" ).toString() );\r\n\t\t\tfor ( auto row2 : DB::selectRows( \"Automaton_Cores_Skills\", itemSID ) )\r\n\t\t\t{\r\n\t\t\t\tQString skillID = row2.value( \"SkillID\" ).toString();\r\n\t\t\t\tint value       = row2.value( \"SkillValue\" ).toInt();\r\n\r\n\t\t\t\tm_skills.insert( skillID, value );\r\n\t\t\t\tm_skillActive.insert( skillID, true );\r\n\t\t\t\tm_skillPriorities.append( skillID );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int Automaton::coreItem()\r\n{\r\n\treturn m_core;\r\n}\r\n\r\nbool Automaton::getRefuelFlag()\r\n{\r\n\treturn m_refuel;\r\n}\r\n\r\nvoid Automaton::setRefuelFlag( bool flag )\r\n{\r\n\tm_refuel = flag;\r\n}\r\n\r\nvoid Automaton::setCoreType( QString coreSID )\r\n{\r\n\tif( !m_coreType.isEmpty() && coreSID.isEmpty() )\r\n\t{\r\n\t\tm_uninstallCore = true;\r\n\t}\r\n\tm_coreType        = coreSID;\r\n\tm_maintJobChanged = true;\r\n}\r\n\r\nQString Automaton::coreType()\r\n{\r\n\treturn m_coreType;\r\n}\r\n\r\nvoid Automaton::uninstallCore( bool uninstall )\r\n{\r\n\tm_uninstallCore   = uninstall;\r\n\tm_maintJobChanged = true;\r\n}\r\n\r\nbool Automaton::uninstallFlag()\r\n{\r\n\treturn m_uninstallCore;\r\n}\r\n\r\nvoid Automaton::setMaintenanceJob( QSharedPointer<Job> job )\r\n{\r\n\tm_maintenaceJob   = job;\r\n\tm_maintJobChanged = true;\r\n}\r\n\r\nunsigned int Automaton::maintenanceJobID()\r\n{\r\n\tif( m_maintenaceJob )\r\n\t{\r\n\t\tauto job = m_maintenaceJob.toStrongRef();\r\n\t\treturn job->id();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Automaton::maintenanceJobChanged()\r\n{\r\n\tbool out          = m_maintJobChanged;\r\n\tm_maintJobChanged = false;\r\n\treturn out;\r\n}\r\n\r\nint Automaton::getFuelLevel()\r\n{\r\n\treturn m_fuel;\r\n}\r\n\r\nvoid Automaton::fillUp( int burnValue )\r\n{\r\n\tm_fuel = burnValue;\r\n\tupdateSprite();\r\n}"
  },
  {
    "path": "src/game/automaton.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/gnome.h\"\r\n#include \"../game/job.h\"\r\n\r\nclass GnomeManager;\r\n\r\nclass Automaton : public Gnome\r\n{\r\npublic:\r\n\tAutomaton( Position pos, unsigned int automatonItem, Game* game );\r\n\tAutomaton( QVariantMap& in, Game* game );\r\n\t~Automaton();\r\n\r\n\tvirtual void init();\r\n\r\n\tvirtual void serialize( QVariantMap& out );\r\n\r\n\tvirtual void updateSprite();\r\n\r\n\tvirtual CreatureTickResult onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid installCore( unsigned int itemID );\r\n\tunsigned int coreItem();\r\n\r\n\tunsigned int automatonItem()\r\n\t{\r\n\t\treturn m_automatonItem;\r\n\t}\r\n\r\n\tbool getRefuelFlag();\r\n\tvoid setRefuelFlag( bool flag );\r\n\r\n\tvoid setCoreType( QString coreSID );\r\n\tQString coreType();\r\n\r\n\tvoid uninstallCore( bool uninstall );\r\n\tbool uninstallFlag();\r\n\r\n\tvoid setMaintenanceJob( QSharedPointer<Job> job );\r\n\tunsigned int maintenanceJobID();\r\n\r\n\tbool maintenanceJobChanged();\r\n\r\n\tint getFuelLevel();\r\n\tvoid fillUp( int burnValue );\r\n\r\nprotected:\r\n\tunsigned int m_automatonItem = 0;\r\n\tunsigned int m_core          = 0;\r\n\tfloat m_fuel                 = 0;\r\n\tbool m_refuel                = true;\r\n\tQString m_coreType;\r\n\tbool m_uninstallCore = false;\r\n\r\n\tQWeakPointer<Job> m_maintenaceJob;\r\n\tbool m_maintJobChanged       = false;\r\n};\r\n"
  },
  {
    "path": "src/game/canwork.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"canwork.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/automaton.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/room.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/stockpile.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshop.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n//#include \"../gui/strings.h\"\r\n\r\n#include <exprtk.hpp>\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QDebug>\r\n\r\ntypedef exprtk::symbol_table<double> symbol_table_t;\r\ntypedef exprtk::expression<double> expression_t;\r\ntypedef exprtk::parser<double> parser_t;\r\ntypedef exprtk::parser_error::type _error_t;\r\n\r\nCanWork::CanWork( Position& pos, QString name, Gender gender, QString species, Game* game ) :\r\n\tCreature( pos, name, gender, species, game )\r\n{\r\n}\r\n\r\nCanWork::CanWork( QVariantMap in, Game* game ) :\r\n\tCreature( in, game )\r\n{\r\n\tm_jobID = in.value( \"JobID\" ).toUInt();\r\n\r\n\tif ( m_jobID )\r\n\t{\r\n\t\tm_job = g->jm()->getJob( m_jobID );\r\n\r\n\t\tm_currentTask = in.value( \"CurrentTask\" ).toMap();\r\n\r\n\t\tPriorityQueue<Position, int> sq;\r\n\t\tQVariantList sql = in.value( \"WorkPositionQueue\" ).toList();\r\n\t\tfor ( auto sqli : sql )\r\n\t\t{\r\n\t\t\tsq.put( Position( sqli.toMap().value( \"second\" ).toString() ), sqli.toMap().value( \"first\" ).toInt() );\r\n\t\t}\r\n\t\tm_workPositionQueue = sq;\r\n\r\n\t\tm_workPosition = Position( in.value( \"WorkPosition\" ) );\r\n\r\n\t\tm_totalDurationTicks = in.value( \"TotalDurationTicks\" ).toFloat();\r\n\t\tm_repeatJob          = in.value( \"RepeatJob\" ).toBool();\r\n\r\n\t\tm_assignedWorkshop = in.value( \"AssignedWorkshop\" ).toUInt();\r\n\r\n\t\tif ( in.contains( \"EffectedTiles\" ) )\r\n\t\t{\r\n\t\t\tm_effectedTiles = Global::util->variantList2Position( in.value( \"EffectedTiles\" ).toList() );\r\n\t\t}\r\n\r\n\t\tm_animal          = in.value( \"Animal\" ).toUInt();\r\n\t\tm_itemToPickUp    = in.value( \"ItemToPickUp\" ).toUInt();\r\n\t\tm_startedEating   = in.value( \"StartedEating\" ).toBool();\r\n\t\tm_startedDrinking = in.value( \"StartedDrinking\" ).toBool();\r\n\r\n\t\tm_taskFinishTick = in.value( \"TaskFinishTick\" ).value<quint64>();\r\n\r\n\t\tQVariantList tl;\r\n\t\tfor ( auto task : m_taskList )\r\n\t\t{\r\n\t\t\ttl.append( task );\r\n\t\t}\r\n\t\tin.value( \"TaskList\", tl );\r\n\r\n\t\tin.value( \"TrainCounter\", m_trainCounter );\r\n\t\tin.value( \"TrainingGround\", m_trainingGround );\r\n\t}\r\n}\r\n\r\nvoid CanWork::serialize( QVariantMap& out )\r\n{\r\n\tCreature::serialize( out );\r\n\r\n\tout.insert( \"JobID\", m_jobID );\r\n\tif ( m_jobID )\r\n\t{\r\n\t\tout.insert( \"WorkPosition\", m_workPosition.toString() );\r\n\t\tout.insert( \"CurrentTask\", m_currentTask );\r\n\r\n\t\t// Copy original queue for iteration\r\n\t\tauto vp = m_workPositionQueue;\r\n\t\tQVariantList sql;\r\n\t\twhile ( !vp.empty() )\r\n\t\t{\r\n\t\t\tconst auto& entry = vp.top();\r\n\t\t\tQVariantMap qEntry;\r\n\t\t\tqEntry.insert( \"first\", entry.first );\r\n\t\t\tqEntry.insert( \"second\", entry.second.toString() );\r\n\t\t\tsql.append( qEntry );\r\n\t\t\tvp.pop();\r\n\t\t}\r\n\t\tout.insert( \"WorkPositionQueue\", sql );\r\n\r\n\t\tout.insert( \"AssignedWorkshop\", m_assignedWorkshop );\r\n\r\n\t\tout.insert( \"TotalDurationTicks\", m_totalDurationTicks );\r\n\t\tout.insert( \"TaskFinishTick\", m_taskFinishTick );\r\n\t\tout.insert( \"RepeatJob\", m_repeatJob );\r\n\r\n\t\tif ( m_effectedTiles.size() )\r\n\t\t{\r\n\t\t\tQVariantList et;\r\n\t\t\tfor ( auto pos : m_effectedTiles )\r\n\t\t\t{\r\n\t\t\t\tet.append( pos.toString() );\r\n\t\t\t}\r\n\t\t\tout.insert( \"EffectedTiles\", et );\r\n\t\t}\r\n\r\n\t\tout.insert( \"Animal\", m_animal );\r\n\t\tout.insert( \"ItemToPickUp\", m_itemToPickUp );\r\n\t\tout.insert( \"StartedEating\", m_startedEating );\r\n\t\tout.insert( \"StartedDrinking\", m_startedDrinking );\r\n\r\n\t\tQVariantList tl;\r\n\t\tfor ( auto task : m_taskList )\r\n\t\t{\r\n\t\t\ttl.append( task );\r\n\t\t}\r\n\t\tout.insert( \"TaskList\", tl );\r\n\r\n\t\tout.insert( \"TrainCounter\", m_trainCounter );\r\n\t\tout.insert( \"TrainingGround\", m_trainingGround );\r\n\t}\r\n}\r\n\r\nbool CanWork::getSkillActive( QString id )\r\n{\r\n\tif ( m_skillActive.contains( id ) )\r\n\t{\r\n\t\treturn m_skillActive.value( id ).toBool();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid CanWork::setSkillActive( QString id, bool active )\r\n{\r\n\tm_skillActive[id] = active;\r\n\r\n\tif ( m_job )\r\n\t{\r\n\t\tQString skillID = m_job->requiredSkill();\r\n\r\n\t\tif ( ( id == skillID ) && !active )\r\n\t\t{\r\n\t\t\tm_job->setAborted( true );\r\n\t\t}\r\n\t}\r\n\r\n\tQString group = DB::select( \"SkillGroup\", \"Skills\", id ).toString();\r\n\tif ( group == \"Combat\" || group == \"Defense\" )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( active )\r\n\t{\r\n\t\tif ( !m_skillPriorities.contains( id ) )\r\n\t\t{\r\n\t\t\tm_skillPriorities.push_back( id );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor ( int i = 0; i < m_skillPriorities.size(); ++i )\r\n\t\t{\r\n\t\t\tif ( m_skillPriorities[i] == id )\r\n\t\t\t{\r\n\t\t\t\tm_skillPriorities.removeAt( i );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid CanWork::clearAllSkills()\r\n{\r\n\tsetAllSkillsActive( false );\r\n}\r\n\r\nvoid CanWork::setAllSkillsActive( bool active )\r\n{\r\n\tif ( !active )\r\n\t{\r\n\t\tm_skillPriorities.clear();\r\n\t\tif ( m_job )\r\n\t\t{\r\n\t\t\tm_job->setAborted( true );\r\n\t\t}\r\n\t}\r\n\tfor ( auto& p : m_skillActive )\r\n\t{\r\n\t\tp = active;\r\n\t}\r\n}\r\n\r\nvoid CanWork::resetJobVars()\r\n{\r\n\tm_jobID         = 0;\r\n\tm_currentAction = \"idle\";\r\n\t//m_currentPath.clear();\r\n\r\n\tm_itemToPickUp = 0;\r\n\tm_claimedItems.clear();\r\n\tm_carriedItems.clear();\r\n\r\n\tm_totalDurationTicks = 0;\r\n\tm_taskFinishTick     = 0;\r\n\r\n\tm_currentTask.clear();\r\n\tm_taskList.clear();\r\n\r\n\tm_animal = 0;\r\n\tm_effectedTiles.clear();\r\n\r\n\tm_facingAfterMove = -1;\r\n\r\n\tm_repeatJob = false;\r\n\r\n\tm_btBlackBoard.remove( \"JobType\" );\r\n}\r\n\r\nvoid CanWork::cleanUpJob( bool finished )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"cleanUpJob\" );\r\n\tbool spriteNeedsUpdate = false;\r\n\tif ( m_jobID && m_job )\r\n\t{\r\n\t\t// do stuff we need variables from the job object first\r\n\t\t// pointer may become invalid after giveBackJob or finishJob\r\n\r\n\t\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\t\tif ( a )\r\n\t\t{\r\n\t\t\ta->setFollowID( 0 );\r\n\t\t\ta->setImmobile( false );\r\n\t\t\tm_animal = 0;\r\n\t\t}\r\n\r\n\t\tif ( finished )\r\n\t\t{\r\n\t\t\tQVariant sgv = DB::select( \"SkillGain\", \"Jobs\", m_job->type() );\r\n\t\t\tgainSkill( sgv, m_job );\r\n\t\t\tQVariant tgv = DB::select( \"TechGain\", \"Jobs\", m_job->type() );\r\n\t\t\tgainTech( tgv, m_job );\r\n\r\n\t\t\tg->jm()->finishJob( m_jobID );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// input pos is different from work pos for workshop jobs\r\n\t\t\t// this is for other job\r\n\t\t\t// so input pos gets cleared for reassignment when the gnome is expelled from a tile\r\n\t\t\tif ( m_job->posItemInput() == m_job->workPos() )\r\n\t\t\t{\r\n\t\t\t\tm_job->setPosItemInput( Position( 0, 0, 0 ) );\r\n\t\t\t}\r\n\t\t\tm_job->setAborted( false );\r\n\t\t\tg->jm()->giveBackJob( m_jobID );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !claimedItems().empty() )\r\n\t{\r\n\t\tfor ( auto itemID : claimedItems() )\r\n\t\t{\r\n\t\t\tg->inv()->setInJob( itemID, 0 );\r\n\t\t\tif ( ( g->inv()->isHeldBy( itemID ) == m_id ) && !g->inv()->isConstructed( itemID ) )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->putDownItem( itemID, m_position );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( m_btBlackBoard.contains( \"ClaimedUniformItem\" ) )\r\n\t{\r\n\t\tauto itemID = m_btBlackBoard.value( \"ClaimedUniformItem\" ).toUInt();\r\n\t\tg->inv()->setInJob( itemID, 0 );\r\n\t\tm_btBlackBoard.remove( \"ClaimedUniformItem\" );\r\n\t\tm_btBlackBoard.remove( \"ClaimedUniformItemSlot\" );\r\n\t}\r\n\r\n\tfor ( auto itemID : m_carriedItems )\r\n\t{\r\n\t\tif ( ( g->inv()->isHeldBy( itemID ) == m_id ) && !g->inv()->isConstructed( itemID ) )\r\n\t\t{\r\n\t\t\tg->inv()->putDownItem( itemID, m_position );\r\n\t\t}\r\n\t\tg->inv()->setInJob( itemID, 0 );\r\n\t}\r\n\tm_carriedItems.clear();\r\n\r\n\tspriteNeedsUpdate = dropEquippedItem();\r\n\r\n\t// clean up magic\r\n\tfor ( auto pos : m_effectedTiles )\r\n\t{\r\n\t\tg->w()->clearJobSprite( pos, false );\r\n\t}\r\n\r\n\tm_currentPath.clear();\r\n\tresetJobVars();\r\n\tm_currentAction = \"idle\";\r\n\tm_jobID         = 0;\r\n\tm_job.reset();\r\n\tm_jobChanged    = true;\r\n\r\n\tif ( spriteNeedsUpdate )\r\n\t{\r\n\t\tupdateSprite();\r\n\t}\r\n}\r\n\r\nint CanWork::getDurationTicks( QVariant value, QSharedPointer<Job> job )\r\n{\r\n\tif ( value.toString() == \"$Craft\" )\r\n\t{\r\n\t\tvalue = DB::select( \"ProductionTime\", \"Crafts\", job->craftID() );\r\n\t}\r\n\r\n\tint ticks = value.toInt() * Global::util->ticksPerMinute;\r\n\t//if( Global::debugMode ) qDebug() << m_name << \"getDurationTicks: \" << job->type() << ticks;\r\n\treturn ticks;\r\n}\r\n\r\nvoid CanWork::gainSkill( QVariant skillGain, QSharedPointer<Job> job )\r\n{\r\n\tif ( skillGain.toString().isEmpty() )\r\n\t{\r\n\t\tQString skillID = job->requiredSkill();\r\n\t\tfloat current   = m_skills.value( skillID ).toFloat() + 1;\r\n\t\tm_skills.insert( skillID, current );\r\n\r\n\t\tif ( skillID == \"Hauling\" )\r\n\t\t{\r\n\t\t\tupdateMoveSpeed();\r\n\r\n\t\t\t//if( Global::debugMode ) qDebug() << name() << \"now has move speed\" << m_moveSpeed << \"(\" << m_moveDelay << \")\";\r\n\t\t}\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( skillGain.toString() == \"$Craft\" )\r\n\t{\r\n\t\tskillGain = DB::selectRow( \"Crafts_SkillGain\", job->craftID() );\r\n\t}\r\n\r\n\tQVariantMap sgm = skillGain.toMap();\r\n\tQString skillID = sgm.value( \"SkillID\" ).toString();\r\n\tfloat gain      = 0;\r\n\r\n\tif ( skillID.isEmpty() )\r\n\t{\r\n\t\tskillID = job->requiredSkill();\r\n\t}\r\n\r\n\tgain = parseGain( sgm );\r\n\r\n\tif ( gain > 0 )\r\n\t{\r\n\t\tfloat current = m_skills.value( skillID ).toFloat();\r\n\t\tm_skills.insert( skillID, current + gain );\r\n\t\t//if( Global::debugMode )\tqDebug() << name() << \" gain skill: \" << skillID << gain;\r\n\t}\r\n}\r\n\r\nvoid CanWork::gainSkill( QString skillID, int gain )\r\n{\r\n\tint current = m_skills.value( skillID ).toInt();\r\n\tm_skills.insert( skillID, current + gain );\r\n\t//if( Global::debugMode )\tqDebug() << name() << \" gain skill: \" << skillID << gain;\r\n}\r\n\r\nvoid CanWork::gainTech( QVariant techGain, QSharedPointer<Job> job )\r\n{\r\n\tif ( techGain.toString() == \"$Craft\" )\r\n\t{\r\n\t\ttechGain = DB::selectRow( \"Crafts_TechGain\", job->craftID() );\r\n\t}\r\n\tQVariantMap tgm = techGain.toMap();\r\n\tQString techID  = tgm.value( \"TechID\" ).toString();\r\n\tfloat gain      = 0;\r\n\r\n\tif ( techID.isEmpty() )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tgain = parseGain( tgm );\r\n\t}\r\n\tif ( gain > 0 )\r\n\t{\r\n\t\t//if( Global::debugMode ) qDebug() << \"Gain tech: \" << techID << gain;\r\n\t\tfloat current = GameState::techs.value( techID ).toFloat();\r\n\t\tGameState::techs.insert( techID, current + gain );\r\n\t}\r\n}\r\n\r\ndouble CanWork::parseGain( QVariantMap gainMap )\r\n{\r\n\tif ( gainMap.contains( \"Value\" ) )\r\n\t{\r\n\t\treturn parseValue( gainMap.value( \"Value\" ) );\r\n\t}\r\n\r\n\tdouble gain         = 1;\r\n\tstd::string formula = gainMap.value( \"Formula\" ).toString().toStdString();\r\n\tsymbol_table_t symbol_table;\r\n\tsymbol_table.add_constants();\r\n\tQVariantMap args = gainMap.value( \"Args\" ).toMap();\r\n\r\n\tQList<std::pair<std::string, double>> values;\r\n\r\n\tfor ( auto arg : args.toStdMap() )\r\n\t{\r\n\t\tstd::pair<std::string, double> vpair( arg.first.toStdString(), parseValue( arg.second ) );\r\n\t\tvalues.push_back( vpair );\r\n\t\tsymbol_table.add_variable( values.last().first, values.last().second );\r\n\t}\r\n\r\n\texpression_t expression;\r\n\texpression.register_symbol_table( symbol_table );\r\n\r\n\t// Instantiate parser and compile the expression\r\n\tparser_t parser;\r\n\r\n\tif ( !parser.compile( formula, expression ) )\r\n\t{\r\n\t\tprintf( \"Error: %s\\tExpression: %s\\n\", parser.error().c_str(), formula.c_str() );\r\n\r\n\t\tfor ( std::size_t i = 0; i < parser.error_count(); ++i )\r\n\t\t{\r\n\t\t\tconst _error_t error = parser.get_error( i );\r\n\t\t\tprintf( \"Error: %02d Position: %02d Type: [%s] Msg: %s Expr: %s\\n\", static_cast<int>( i ), static_cast<int>( error.token.position ), exprtk::parser_error::to_str( error.mode ).c_str(), error.diagnostic.c_str(), formula.c_str() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Evaluate and assign result\r\n\t\tgain = expression.value();\r\n\t}\r\n\treturn gain;\r\n}\r\n\r\ndouble CanWork::parseValue( QVariant v )\r\n{\r\n\tQString var = v.toString();\r\n\tif ( var.startsWith( \"$Tech\" ) )\r\n\t{\r\n\t\tvar.remove( 0, 1 );\r\n\t\treturn GameState::techs.value( var ).toDouble();\r\n\t}\r\n\telse if ( var.startsWith( \"$Attrib\" ) )\r\n\t{\r\n\t\tvar.remove( 0, 7 );\r\n\t\treturn m_attributes.value( var ).toDouble();\r\n\t}\r\n\telse if ( var.startsWith( \"$\" ) )\r\n\t{\r\n\t\tvar.remove( 0, 1 );\r\n\t\treturn m_skills.value( var ).toDouble();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn v.toDouble();\r\n\t}\r\n}\r\n\r\nbool CanWork::dropEquippedItem()\r\n{\r\n\t// release a claimed tool if this is run before the gnome picked it up\r\n\tunsigned int claimedItem = m_btBlackBoard.value( \"ClaimedTool\" ).toUInt();\r\n\tif ( claimedItem )\r\n\t{\r\n\t\tg->inv()->setInJob( claimedItem, 0 );\r\n\t}\r\n\tm_btBlackBoard.remove( \"ClaimedTool\" );\r\n\r\n\tunsigned int equippedItem = m_equipment.rightHandHeld.itemID;\r\n\tif ( equippedItem )\r\n\t{\r\n\t\t// check if item belongs to uniform\r\n\t\tif ( m_roleID )\r\n\t\t{\r\n\t\t\tauto uniform = g->mil()->uniform( m_roleID );\r\n\t\t\tif ( uniform )\r\n\t\t\t{\r\n\t\t\t\tQString rhi = uniform->parts[\"RightHandHeld\"].item;\r\n\t\t\t\tQString rhm = uniform->parts[\"RightHandHeld\"].material;\r\n\t\t\t\tif ( rhi == m_equipment.rightHandHeld.item && ( rhm == \"any\" || rhm == m_equipment.rightHandHeld.material ) )\r\n\t\t\t\t{\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\r\n\t\tg->inv()->putDownItem( equippedItem, m_position );\r\n\t\tg->inv()->gravity( m_position );\r\n\t\tg->inv()->setInJob( equippedItem, 0 );\r\n\t\tm_equipment.rightHandHeld.itemID = 0;\r\n\t\tm_equipment.rightHandHeld.item.clear();\r\n\t\tm_equipment.rightHandHeld.materialID = 0;\r\n\t\tm_equipment.rightHandHeld.material.clear();\r\n\r\n\t\tequipHand( 0, \"Right\" );\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid CanWork::equipHand( unsigned int item, QString side )\r\n{\r\n\tif ( item )\r\n\t{\r\n\t\tif ( side == \"Left\" )\r\n\t\t{\r\n\t\t\tm_leftHandAttackSkill = getSkillLevel( \"Melee\" );\r\n\t\t\tm_leftHandAttackValue = g->inv()->attackValue( item );\r\n\t\t\tm_leftHandArmed       = true;\r\n\t\t\tif ( g->inv()->isWeapon( item ) )\r\n\t\t\t{\r\n\t\t\t\tm_leftHandHasWeapon = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_leftHandHasWeapon = false;\r\n\t\t\t}\r\n\r\n\t\t\tm_lightIntensity = DB::select( \"LightIntensity\", \"Items\", g->inv()->itemSID( item ) ).toInt();\r\n\t\t\tif ( m_lightIntensity )\r\n\t\t\t{\r\n\t\t\t\tg->w()->addLight( m_id, m_position, m_lightIntensity );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_rightHandAttackSkill = getSkillLevel( \"Melee\" );\r\n\t\t\tm_rightHandAttackValue = g->inv()->attackValue( item );\r\n\t\t\tm_rightHandArmed       = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( side == \"Left\" )\r\n\t\t{\r\n\t\t\tm_leftHandAttackSkill = getSkillLevel( \"Unarmed\" );\r\n\t\t\tm_leftHandAttackValue = m_leftHandAttackSkill;\r\n\t\t\tm_leftHandArmed       = false;\r\n\t\t\tm_leftHandHasWeapon   = false;\r\n\r\n\t\t\tm_lightIntensity = 0;\r\n\t\t\tg->w()->removeLight( m_id );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_rightHandAttackSkill = getSkillLevel( \"Unarmed\" );\r\n\t\t\tm_rightHandAttackValue = m_rightHandAttackSkill;\r\n\t\t\tm_rightHandArmed       = false;\r\n\t\t}\r\n\t}\r\n\tupdateSprite();\r\n}\r\n\r\nbool CanWork::mineWall()\r\n{\r\n\t// remove the wall\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tauto mats = g->w()->mineWall( pos, m_workPosition );\r\n\r\n\tGlobal::util->createRawMaterialItem( pos, mats.first );\r\n\tGlobal::util->createRawMaterialItem( pos, mats.second );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::mineFloor()\r\n{\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\tauto mat = g->w()->removeFloor( pos, m_position );\r\n\r\n\tQString materialSID = \"None\";\r\n\tQString type        = \"None\";\r\n\tmaterialSID         = DBH::materialSID( mat );\r\n\ttype                = DB::select( \"Type\", \"Materials\", materialSID ).toString();\r\n\r\n\tif ( type == \"Soil\" )\r\n\t{\r\n\t\tg->inv()->createItem( m_job->workPos(), \"RawSoil\", materialSID );\r\n\t}\r\n\telse if ( type == \"Stone\" )\r\n\t{\r\n\t\tg->inv()->createItem( m_job->workPos(), \"RawStone\", materialSID );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::digHole()\r\n{\r\n\t// remove the wall\r\n\tPosition offset( 0, 0, -1 );\r\n\tPosition pos( m_job->pos() );\r\n\r\n\t/*\r\n\tif( g->w()->checkTrapGnomeFloor( pos, m_position ) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\t*/\r\n\r\n\tg->w()->removeFloor( pos, m_position );\r\n\tauto mats = g->w()->mineWall( pos + offset, m_position );\r\n\r\n\tGlobal::util->createRawMaterialItem( m_position, mats.first );\r\n\tGlobal::util->createRawMaterialItem( m_position, mats.second );\r\n\r\n\tPosition rp( m_job->pos() + offset );\r\n\tg->w()->createRamp( rp.x, rp.y, rp.z );\r\n\tg->w()->createRamp( rp.x + 1, rp.y, rp.z );\r\n\tg->w()->createRamp( rp.x - 1, rp.y, rp.z );\r\n\tg->w()->createRamp( rp.x, rp.y + 1, rp.z );\r\n\tg->w()->createRamp( rp.x, rp.y - 1, rp.z );\r\n\r\n\tg->w()->updateRampAtPos( rp.northOf() );\r\n\tg->w()->updateRampAtPos( rp.southOf() );\r\n\tg->w()->updateRampAtPos( rp.eastOf() );\r\n\tg->w()->updateRampAtPos( rp.westOf() );\r\n\r\n\tg->w()->addToUpdateList( pos );\r\n\tg->w()->addToUpdateList( rp );\r\n\r\n\tg->w()->addToUpdateList( pos.northOf() );\r\n\tg->w()->addToUpdateList( pos.southOf() );\r\n\tg->w()->addToUpdateList( pos.eastOf() );\r\n\tg->w()->addToUpdateList( pos.westOf() );\r\n\r\n\tg->w()->addToUpdateList( rp.northOf() );\r\n\tg->w()->addToUpdateList( rp.southOf() );\r\n\tg->w()->addToUpdateList( rp.eastOf() );\r\n\tg->w()->addToUpdateList( rp.westOf() );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::explorativeMineWall()\r\n{\r\n\t// remove the wall\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tauto mats = g->w()->mineWall( pos, m_workPosition );\r\n\r\n\tGlobal::util->createRawMaterialItem( pos, mats.first );\r\n\tGlobal::util->createRawMaterialItem( pos, mats.second );\r\n\r\n\tif ( mats.second )\r\n\t{\r\n\t\t//check neighbor tiles for ore and create jobs\r\n\t\tconst Position candidates[] = {\r\n\t\t\tpos.northOf(),\r\n\t\t\tpos.southOf(),\r\n\t\t\tpos.eastOf(),\r\n\t\t\tpos.westOf()\r\n\t\t};\r\n\t\tfor ( const auto& candidate : candidates )\r\n\t\t{\r\n\t\t\tif ( g->w()->getTile(candidate).embeddedMaterial == mats.second )\r\n\t\t\t{\r\n\t\t\t\tg->jm()->addJob( \"ExplorativeMine\", candidate, 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::removeRamp()\r\n{\r\n\t// remove the wall\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tunsigned short materialInt = g->w()->removeRamp( pos, m_workPosition );\r\n\r\n\tGlobal::util->createRawMaterialItem( pos, materialInt );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::removeWall()\r\n{\r\n\tPosition offset;\r\n\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tg->w()->removeWall( pos, m_workPosition );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::removeFloor()\r\n{\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\tg->w()->removeFloor( pos, m_position );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::constructAnimate()\r\n{\r\n\t// item to build wasn't set, so this construction job was created otherwise, for instance dig stairs down\r\n\tif ( m_job->item() == \"\" )\r\n\t{\r\n\t\tm_job->setItem( m_currentTask.value( \"ConstructionID\" ).toString() );\r\n\t}\r\n\tQVariantMap con = DB::selectRow( \"Constructions\", m_job->item() );\r\n\r\n\tif ( con.contains( \"IntermediateSprites\" ) )\r\n\t{\r\n\t\tQVariantList isl = con.value( \"IntermediateSprites\" ).toList();\r\n\t\tQString spriteID;\r\n\t\tQString type;\r\n\t\tQString offset;\r\n\t\tint percent;\r\n\t\tfor ( auto isv : isl )\r\n\t\t{\r\n\t\t\tauto ism = isv.toMap();\r\n\t\t\tspriteID = ism.value( \"SpriteID\" ).toString();\r\n\t\t\ttype     = ism.value( \"Type\" ).toString();\r\n\t\t\toffset   = ism.value( \"Offset\" ).toString();\r\n\t\t\tpercent  = ism.value( \"Percent\" ).toInt();\r\n\r\n\t\t\tif ( ( 100. * ( m_taskFinishTick - GameState::tick ) ) / m_totalDurationTicks > percent )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tPosition pos( m_job->pos() + offset );\r\n\r\n\t\tQStringList materials;\r\n\r\n\t\tif ( !claimedItems().empty() )\r\n\t\t{\r\n\t\t\tfor ( auto item : claimedItems() )\r\n\t\t\t{\r\n\t\t\t\tmaterials.push_back( g->inv()->materialSID( item ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\t// paint the intermediate sprite and return\r\n\t\tif ( !spriteID.isEmpty() )\r\n\t\t{\r\n\t\t\tbool isFloor = false;\r\n\t\t\tif ( type == \"Floor\" )\r\n\t\t\t{\r\n\t\t\t\tisFloor = true;\r\n\t\t\t}\r\n\t\t\tSprite* s = g->sf()->createSprite( spriteID, { materials.first() } );\r\n\t\t\tg->w()->setJobSprite( pos, s->uID, m_job->rotation(), isFloor, m_jobID, false );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::constructDugStairs()\r\n{\r\n\tPosition offset( m_currentTask.value( \"Offset\" ) );\r\n\r\n\tm_currentTask.insert( \"Offset\", ( offset + Position( 0, 0, 1 ) ).toString() );\r\n\tremoveWall();\r\n\tremoveFloor();\r\n\tm_currentTask.insert( \"Offset\", offset.toString() );\r\n\r\n\tPosition pos( m_job->pos() + offset );\r\n\tauto wallMat = g->w()->wallMaterial( pos );\r\n\tremoveWall();\r\n\r\n\tauto item = Global::util->createRawMaterialItem( pos, wallMat );\r\n\tif ( item )\r\n\t{\r\n\t\taddClaimedItem( item, m_job->id() );\r\n\t}\r\n\r\n\tauto cil = claimedItems();\r\n\tif ( cil.empty() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tunsigned itemID     = cil.first();\r\n\tQString materialSID = g->inv()->materialSID( itemID );\r\n\tQString type        = DB::select( \"Type\", \"Materials\", materialSID ).toString();\r\n\r\n\tbool result = false;\r\n\tif ( type == \"Soil\" || type == \"Sand\" || type == \"Clay\" )\r\n\t{\r\n\t\tm_job->setItem( \"SoilStairs\" );\r\n\t\t//result = g->w()->construct( \"SoilStairs\", m_job->pos(), m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\telse if ( type == \"Stone\" )\r\n\t{\r\n\t\tm_job->setItem( \"StoneStairs\" );\r\n\t\t//result = g->w()->construct( \"StoneStairs\", m_job->pos(), m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\r\n\treturn construct();\r\n}\r\n\r\nbool CanWork::constructDugRamp()\r\n{\r\n\tm_currentTask.insert( \"Offset\", \"0 0 0\" );\r\n\tremoveWall();  // offset 0 0 0\r\n\tremoveFloor(); // offset 0 0 0\r\n\tm_currentTask.insert( \"Offset\", \"0 0 -1\" );\r\n\r\n\tPosition pos( m_job->pos() + Position( 0, 0, -1 ) );\r\n\tauto wallMat = g->w()->wallMaterial( pos );\r\n\tremoveWall(); // offset 0 0 -1\r\n\r\n\tauto item = Global::util->createRawMaterialItem( pos, wallMat );\r\n\tif ( item )\r\n\t{\r\n\t\taddClaimedItem( item, m_job->id() );\r\n\t}\r\n\r\n\tauto cil = claimedItems();\r\n\tif ( cil.empty() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tunsigned itemID = cil.first();\r\n\r\n\tQString materialSID = g->inv()->materialSID( itemID );\r\n\tQString type        = DB::select( \"Type\", \"Materials\", materialSID ).toString();\r\n\r\n\tif ( type == \"Soil\" || type == \"Sand\" || type == \"Clay\" )\r\n\t{\r\n\t\tm_job->setItem( \"SoilRamp\" );\r\n\t\t//result = g->w()->construct( \"SoilStairs\", m_job->pos(), m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\telse if ( type == \"Stone\" )\r\n\t{\r\n\t\tm_job->setItem( \"StoneRamp\" );\r\n\t\t//result = g->w()->construct( \"StoneStairs\", m_job->pos(), m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\treturn construct();\r\n}\r\n\r\nbool CanWork::construct()\r\n{\r\n\tif ( claimedItems().empty() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t//qDebug() << \"#\" << m_job->type() << m_job->item();\r\n\r\n\tif ( m_job->item() == \"\" )\r\n\t{\r\n\t\tm_job->setItem( m_currentTask.value( \"ConstructionID\" ).toString() );\r\n\t}\r\n\r\n\tPosition offset( m_currentTask.value( \"Offset\" ).toString() );\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tbool result = false;\r\n\r\n\tif ( m_job->type() == \"BuildWorkshop\" )\r\n\t{\r\n\t\tresult = g->w()->constructWorkshop( m_job->item(), pos, m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\telse if ( m_job->type() == \"BuildItem\" )\r\n\t{\r\n\t\tresult = g->w()->constructItem( m_job->item(), pos, m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tresult = g->w()->construct( m_job->item(), pos, m_job->rotation(), claimedItems(), m_position );\r\n\t}\r\n\r\n\tif ( result )\r\n\t{\r\n\t\tfor ( auto itemUID : claimedItems() )\r\n\t\t{\r\n\t\t\tg->inv()->setInJob( itemUID, 0 );\r\n\r\n\t\t\tif ( !g->inv()->isConstructed( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"destroy items after construction\";\r\n\t\t\t\tg->inv()->pickUpItem( itemUID, m_id ); // update item sprites on tile\r\n\t\t\t\tg->inv()->destroyObject( itemUID );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_claimedItems.clear();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::createItem()\r\n{\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\tif ( m_currentTask.contains( \"Items\" ) )\r\n\t{\r\n\t\tQVariantList items = m_currentTask.value( \"Items\" ).toList();\r\n\t\tfor ( auto item : items )\r\n\t\t{\r\n\t\t\tQVariantMap im      = item.toMap();\r\n\t\t\tQString materialSID = \"None\";\r\n\t\t\tQString type        = \"None\";\r\n\t\t\tif ( im.contains( \"Material\" ) )\r\n\t\t\t{\r\n\t\t\t\tmaterialSID = im.value( \"Material\" ).toString();\r\n\t\t\t}\r\n\t\t\tQString condition = im.value( \"Condition\" ).toString();\r\n\t\t\tif ( condition == \"MaterialType\" )\r\n\t\t\t{\r\n\t\t\t\tif ( type == im.value( \"ConditionValue\" ).toString() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( pos, im.value( \"ItemID\" ).toString(), materialSID );\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\tqDebug() << \"create item failed\";\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::harvest()\r\n{\r\n\t// get Tree\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\tQMap<unsigned int, Plant>& plants = g->w()->plants();\r\n\tif ( plants.contains( pos.toInt() ) )\r\n\t{\r\n\t\tPlant& plant = plants[pos.toInt()];\r\n\t\tif ( plant.harvest( m_position ) ) // plant.harvest() returns true if the plant is to be destroyed after harvest\r\n\t\t{\r\n\t\t\t// remove plant;\r\n\t\t\tif ( plant.isPlant() )\r\n\t\t\t{\r\n\t\t\t\tg->w()->clearTileFlag( pos, TileFlag::TF_TILLED );\r\n\t\t\t\tSprite* s = g->sf()->createSprite( \"RoughFloor\", { DBH::materialSID( g->w()->floorMaterial( pos ) ) } );\r\n\t\t\t\tg->w()->setFloorSprite( pos, s->uID );\r\n\t\t\t\tg->w()->setWallSprite( pos, 0 );\r\n\t\t\t\tg->w()->removeGrass( pos );\r\n\t\t\t}\r\n\t\t\tplants.remove( pos.toInt() );\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif ( plant.harvestable() )\r\n\t\t{\r\n\t\t\tm_repeatJob      = true;\r\n\t\t\tm_taskFinishTick = GameState::tick + m_currentTask.value( \"Duration\" ).toInt() * Global::util->ticksPerMinute;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\tm_repeatJob = false;\r\n\r\n\tif ( g->fm()->isBeehive( pos ) )\r\n\t{\r\n\r\n\t\tif ( g->fm()->harvestBeehive( pos ) )\r\n\t\t{\r\n\t\t\tg->inv()->createItem( pos, \"Honey\", \"Bee\" );\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::harvestHay()\r\n{\r\n\t// get Tree\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tif ( g->w()->hasMaxGrass( pos ) )\r\n\t{\r\n\t\tg->inv()->createItem( pos, \"Hay\", \"Grass\" );\r\n\t\tg->w()->setVegetationLevel( pos, 30 );\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::plantTree()\r\n{\r\n\tif ( !claimedItems().empty() )\r\n\t{\r\n\t\tg->w()->plantTree( m_job->pos(), m_job->item() );\r\n\t\tg->inv()->pickUpItem( claimedItems().first(), m_id );\r\n\t\tdestroyClaimedItems();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::plant()\r\n{\r\n\tif ( !claimedItems().empty() )\r\n\t{\r\n\t\tg->w()->plant( m_job->pos(), claimedItems().first() );\r\n\t\tg->inv()->pickUpItem( claimedItems().first(), m_id );\r\n\t\tdestroyClaimedItems();\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::removePlant()\r\n{\r\n\tg->w()->removePlant( m_job->pos() );\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::till()\r\n{\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\tg->w()->setTileFlag( pos, TileFlag::TF_TILLED );\r\n\tg->w()->removeGrass( pos );\r\n\tSprite* s = g->sf()->createSprite( \"TilledSoil\", { DBH::materialSID( g->w()->floorMaterial( pos ) ) } );\r\n\tg->w()->setFloorSprite( pos, s->uID );\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::craft()\r\n{\r\n\tfloat skillLevel = getSkillLevel( m_job->requiredSkill() );\r\n\r\n\tint qSize = DB::numRows( \"Quality\" );\r\n\r\n\tint qIndex = skillLevel / 20. * qSize;\r\n\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\tint qRand = rand() % 100;\r\n\tif ( qRand < 20 )\r\n\t{\r\n\t\tqIndex = qMax( 0, qIndex - 1 );\r\n\t}\r\n\tif ( qRand > 96 )\r\n\t{\r\n\t\tqIndex = qMin( qSize - 1, qIndex + 1 );\r\n\t}\r\n\r\n\tQString resultMaterial = m_job->material();\r\n\r\n\tfor ( int i = 0; i < m_job->amount(); ++i )\r\n\t{\r\n\t\tif ( !resultMaterial.isEmpty() )\r\n\t\t{\r\n\t\t\tif ( resultMaterial == \"RandomMetal\" )\r\n\t\t\t{\r\n\t\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\t\t\t\tif ( rand() % 100 > 50 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( claimedItems().size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto item = claimedItems().first();\r\n\r\n\t\t\t\t\t\tauto sourceMaterial = g->inv()->materialSID( item );\r\n\t\t\t\t\t\tauto material       = Global::util->randomMetalSliver( sourceMaterial );\r\n\t\t\t\t\t\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), m_job->item(), material );\r\n\t\t\t\t\t\tg->inv()->setMadeBy( itemID, id() );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), m_job->item(), resultMaterial );\r\n\t\t\t\tg->inv()->setMadeBy( itemID, id() );\r\n\t\t\t\tg->inv()->setQuality( itemID, qIndex );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( m_job->conversionMaterial().isEmpty() )\r\n\t\t{\r\n\t\t\tif ( claimedItems().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), m_job->item(), claimedItems() );\r\n\t\t\tg->inv()->setMadeBy( itemID, id() );\r\n\t\t\tg->inv()->setQuality( itemID, qIndex );\r\n\t\t\tif ( m_job->item() == \"Automaton\" )\r\n\t\t\t{\r\n\t\t\t\tAutomaton* a = new Automaton( m_job->posItemOutput(), itemID, g );\r\n\t\t\t\t//a->setSpriteID( g->sf()->setAutomatonSprite( a->id(), g->inv()->spriteID( itemID ) ) );\r\n\t\t\t\t//a->updateSprite();\r\n\r\n\t\t\t\tg->gm()->addAutomaton( a );\r\n\t\t\t\tg->inv()->pickUpItem( itemID, a->id() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( m_job->conversionMaterial() == \"$Dye\" )\r\n\t\t\t{\r\n\t\t\t\tunsigned int dyeItem    = 0;\r\n\t\t\t\tunsigned int sourceItem = 0;\r\n\t\t\t\tfor ( auto item : claimedItems() )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( g->inv()->itemSID( item ) == \"Dye\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdyeItem = item;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsourceItem = item;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tQString sourceMaterial = g->inv()->materialSID( sourceItem );\r\n\t\t\t\tQString dyeMaterial    = g->inv()->materialSID( dyeItem );\r\n\r\n\t\t\t\tQString targetMaterial = Global::util->addDyeMaterial( sourceMaterial, dyeMaterial );\r\n\r\n\t\t\t\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), m_job->item(), targetMaterial );\r\n\t\t\t\tg->inv()->setMadeBy( itemID, id() );\r\n\t\t\t\tg->inv()->setQuality( itemID, g->inv()->quality( sourceItem ) );\r\n\t\t\t}\r\n\t\t\telse if ( m_job->conversionMaterial() == \"$GnomeHair\" )\r\n\t\t\t{\r\n\t\t\t\tif ( claimedItems().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\t//abortJob( \"error claimed items empty\" );\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t\tunsigned int sourceItem = claimedItems().first();\r\n\t\t\t\tQString sourceMaterial  = g->inv()->materialSID( sourceItem );\r\n\t\t\t\tQString dyeColor        = DB::select( \"Color\", \"Materials\", sourceMaterial ).toString();\r\n\t\t\t\tauto keys               = DB::ids( \"Materials\", \"Type\", \"Dye\" );\r\n\t\t\t\tint id                  = 0;\r\n\t\t\t\tfor ( auto key : keys )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString keyColor = DB::select( \"Color\", \"Materials\", key ).toString();\r\n\t\t\t\t\tif ( keyColor == dyeColor )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.hairColor = id;\r\n\t\t\t\t\t\tupdateSprite();\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t++id;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( m_job->conversionMaterial() == \"$Leather\" )\r\n\t\t\t{\r\n\t\t\t\tunsigned int sourceItem = claimedItems().first();\r\n\t\t\t\tQString sourceMaterial  = g->inv()->materialSID( sourceItem );\r\n\r\n\t\t\t\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), m_job->item(), sourceMaterial + \"Leather\" );\r\n\t\t\t\tg->inv()->setMadeBy( itemID, id() );\r\n\t\t\t\tg->inv()->setQuality( itemID, qIndex );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), m_job->item(), m_job->conversionMaterial() );\r\n\t\t\t\tg->inv()->setMadeBy( itemID, id() );\r\n\t\t\t\tg->inv()->setQuality( itemID, qIndex );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tdestroyClaimedItems();\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::fellTree()\r\n{\r\n\t// get Tree\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\tQMap<unsigned int, Plant>& plants = g->w()->plants();\r\n\tif ( plants.contains( pos.toInt() ) )\r\n\t{\r\n\t\tPlant& plant = plants[pos.toInt()];\r\n\t\tif ( plant.fell() )\r\n\t\t{\r\n\t\t\t// remove plant;\r\n\t\t\tg->w()->removePlant( pos );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::deconstruct()\r\n{\r\n\tPosition offset;\r\n\tif ( m_currentTask.contains( \"Offset\" ) )\r\n\t{\r\n\t\toffset = Position( m_currentTask.value( \"Offset\" ).toString() );\r\n\t}\r\n\tPosition pos( m_job->pos() + offset );\r\n\r\n\tg->w()->deconstruct( pos, m_position, false );\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::butcherFish()\r\n{\r\n\tfor ( auto itemUID : claimedItems() )\r\n\t{\r\n\t\tQString materialSID = g->inv()->materialSID( itemUID );\r\n\r\n\t\tg->inv()->createItem( m_job->posItemOutput(), \"Meat\", materialSID );\r\n\t\tg->inv()->createItem( m_job->posItemOutput(), \"FishBone\", materialSID );\r\n\t}\r\n\tdestroyClaimedItems();\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::butcherCorpse()\r\n{\r\n\tfor ( auto itemUID : claimedItems() )\r\n\t{\r\n\t\tQString materialSID = g->inv()->materialSID( itemUID );\r\n\r\n\t\tg->inv()->createItem( m_job->posItemOutput(), \"Meat\", materialSID );\r\n\t\tg->inv()->createItem( m_job->posItemOutput(), \"Bone\", materialSID );\r\n\t}\r\n\tdestroyClaimedItems();\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::fish()\r\n{\r\n\tunsigned int itemID = g->inv()->createItem( m_job->posItemOutput(), \"Fish\", \"GreenFish\" );\r\n\tg->inv()->setMadeBy( itemID, id() );\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::prepareSpell()\r\n{\r\n\tQString jobID = m_job->type();\r\n\r\n\tQStringList jobParts = jobID.split( \"_\" );\r\n\tQString spellID      = jobParts.last();\r\n\r\n\tQString radiusString = DB::select( \"Radius\", \"Spells\", spellID ).toString();\r\n\tbool ok              = false;\r\n\tint radius           = radiusString.toInt( &ok );\r\n\tif ( !ok )\r\n\t{\r\n\t\tif ( radiusString == \"HalfSkill\" )\r\n\t\t{\r\n\t\t\tradius = qMax( 1, getSkillLevel( m_job->requiredSkill() ) / 2 );\r\n\t\t}\r\n\t\telse if ( radiusString == \"Skill\" )\r\n\t\t{\r\n\t\t\tradius = qMin( 10, qMax( 1, getSkillLevel( m_job->requiredSkill() ) ) );\r\n\t\t}\r\n\t}\r\n\tint radius2 = radius * radius;\r\n\tm_effectedTiles.clear();\r\n\r\n\tPosition center        = m_job->pos();\r\n\tunsigned int spriteUID = g->sf()->createSprite( \"Sparkles\", { \"None\" } )->uID + 2048;\r\n\r\n\tint xMin = qMax( 1, center.x - radius );\r\n\tint yMin = qMax( 1, center.y - radius );\r\n\tint xMax = qMin( Global::dimX - 2, center.x + radius );\r\n\tint yMax = qMin( Global::dimX - 2, center.y + radius );\r\n\tfor ( int x = xMin; x < xMax; ++x )\r\n\t{\r\n\t\tfor ( int y = yMin; y < yMax; ++y )\r\n\t\t{\r\n\t\t\tif ( center.distSquare( x, y, center.z ) <= radius2 )\r\n\t\t\t{\r\n\t\t\t\tm_effectedTiles.append( Position( x, y, center.z ).toString() );\r\n\t\t\t\tg->w()->setJobSprite( Position( x, y, center.z ), spriteUID, 0, false, m_job->id(), true );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::castSpell()\r\n{\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::castSpellAnimate()\r\n{\r\n\t//\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::finishSpell()\r\n{\r\n\tQString jobID        = m_job->type();\r\n\tQStringList jobParts = jobID.split( \"_\" );\r\n\tQString spellID      = jobParts.last();\r\n\r\n\tauto spellMap        = DB::selectRow( \"Spells\", spellID );\r\n\tQVariantList reqs    = spellMap.value( \"EffectRequirements\" ).toList();\r\n\tQVariantList effects = spellMap.value( \"Effects\" ).toList();\r\n\r\n\tfor ( auto pos : m_effectedTiles )\r\n\t{\r\n\t\tbool effected = true;\r\n\t\tfor ( auto vReq : reqs )\r\n\t\t{\r\n\t\t\tQString sReq = vReq.toString();\r\n\t\t\tif ( sReq == \"Plant\" )\r\n\t\t\t{\r\n\t\t\t\teffected &= g->w()->plants().contains( pos.toInt() );\r\n\t\t\t}\r\n\t\t\telse if ( sReq == \"RoughWall\" )\r\n\t\t\t{\r\n\t\t\t\teffected &= ( g->w()->wallType( pos ) == WT_ROUGH );\r\n\t\t\t}\r\n\t\t\telse if ( sReq == \"EmbeddedMaterial\" )\r\n\t\t\t{\r\n\t\t\t\teffected &= ( g->w()->embeddedMaterial( pos ) != 0 );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( effected )\r\n\t\t{\r\n\t\t\tfor ( auto vEffect : effects )\r\n\t\t\t{\r\n\t\t\t\tQString sEffect = vEffect.toString();\r\n\t\t\t\tif ( sEffect == \"Reveal\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->w()->clearTileFlag( pos, TileFlag::TF_UNDISCOVERED );\r\n\t\t\t\t\tg->w()->addToUpdateList( pos );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( sEffect == \"PlantGrowth\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->w()->plants()[pos.toInt()].speedUpGrowth( Global::util->ticksPerDay * getSkillLevel( m_job->requiredSkill() ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tg->w()->clearJobSprite( pos, false );\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool CanWork::switchMechanism()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tg->mcm()->toggleActive( m_job->mechanism() );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::invertMechanism()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tg->mcm()->toggleInvert( m_job->mechanism() );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::refuel()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tint burnValue = DB::select( \"BurnValue\", \"Items\", m_job->requiredItems().first().itemSID ).toInt();\r\n\r\n\t\tif ( m_job->automaton() )\r\n\t\t{\r\n\t\t\tauto a = g->gm()->automaton( m_job->automaton() );\r\n\t\t\tif ( a )\r\n\t\t\t{\r\n\t\t\t\ta->fillUp( burnValue );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( m_job->mechanism() )\r\n\t\t{\r\n\t\t\tg->mcm()->refuel( m_job->mechanism(), burnValue );\r\n\t\t}\r\n\r\n\t\tdestroyClaimedItems();\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::install()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\r\n\t\tif ( m_job->automaton() )\r\n\t\t{\r\n\t\t\tauto a = g->gm()->automaton( m_job->automaton() );\r\n\t\t\tif ( a )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : claimedItems() )\r\n\t\t\t\t{\r\n\t\t\t\t\ta->installCore( item );\r\n\t\t\t\t}\r\n\t\t\t\tm_claimedItems.clear();\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::uninstall()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tif ( m_job->automaton() )\r\n\t\t{\r\n\t\t\tauto a = g->gm()->automaton( m_job->automaton() );\r\n\t\t\tif ( a )\r\n\t\t\t{\r\n\t\t\t\ta->installCore( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::fillTrough()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tauto pasture = g->fm()->getPastureAtPos( m_job->pos() );\r\n\t\tif ( pasture && m_claimedItems.size() == 1 )\r\n\t\t{\r\n\t\t\tpasture->addFood( m_claimedItems.first() );\r\n\r\n\t\t\tdestroyClaimedItems();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\r\n\t\t\tfor ( auto item : claimedItems() )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->setInJob( item, 0 );\r\n\t\t\t}\r\n\t\t\tm_claimedItems.clear();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool CanWork::soundAlarm()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tif ( GameState::alarm == 1 )\r\n\t\t{\r\n\t\t\tauto room = g->rm()->getRoomAtPos( m_job->pos() );\r\n\t\t\tif ( room )\r\n\t\t\t{\r\n\t\t\t\tGameState::alarmRoomID = room->id();\r\n\t\t\t\tGameState::alarm       = 2;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n"
  },
  {
    "path": "src/game/canwork.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/creature.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/jobmanager.h\"\r\n\r\nclass CanWork : public Creature\r\n{\r\npublic:\r\n\tCanWork( Position& pos, QString name, Gender gender, QString species, Game* game );\r\n\tCanWork( QVariantMap in, Game* game );\r\n\t~CanWork() {};\r\n\r\n\tvirtual void serialize( QVariantMap& out );\r\n\r\n\tvirtual CreatureTickResult onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged ) = 0;\r\n\r\n\tbool getSkillActive( QString id );\r\n\tvoid setSkillActive( QString id, bool active );\r\n\tvoid clearAllSkills();\r\n\tvoid setAllSkillsActive( bool active );\r\n\r\nprotected:\r\n\tunsigned int m_jobID = 0;\r\n\r\n\tPriorityQueue<Position, int> m_workPositionQueue;\r\n\tPosition m_workPosition;\r\n\tQVariantMap m_currentTask;\r\n\r\n\tunsigned int m_assignedWorkshop = 0;\r\n\tint m_totalDurationTicks        = 0;\r\n\tquint64 m_taskFinishTick        = 0;\r\n\tbool m_repeatJob                = false;\r\n\tQList<Position> m_effectedTiles;\r\n\tunsigned int m_animal       = 0;\r\n\tunsigned int m_itemToPickUp = 0;\r\n\tbool m_startedEating        = false;\r\n\tbool m_startedDrinking      = false;\r\n\tQList<QVariantMap> m_taskList;\r\n\tint m_trainCounter            = -1;\r\n\tunsigned int m_trainingGround = 0;\r\n\t////////////////////////////////////////////////////////////////////////////\r\n\r\n\tQSharedPointer<Job> m_job;\r\n\tbool m_jobChanged = false;\r\n\r\n\tvoid resetJobVars();\r\n\tvoid cleanUpJob( bool finished );\r\n\r\n\tint getDurationTicks( QVariant value, QSharedPointer<Job> job );\r\n\r\n\tbool dropEquippedItem();\r\n\tvoid equipHand( unsigned int item, QString side );\r\n\r\n\tvoid gainTech( QVariant techGain, QSharedPointer<Job> job );\r\n\tvoid gainSkill( QVariant skillGain, QSharedPointer<Job> job );\r\n\tvoid gainSkill( QString skill, int value );\r\n\tdouble parseValue( QVariant v );\r\n\tdouble parseGain( QVariantMap gainMap );\r\n\r\n\t// Tasks\r\n\tbool mineWall();\r\n\tbool mineFloor();\r\n\tbool digHole();\r\n\tbool explorativeMineWall();\r\n\tbool removeWall();\r\n\tbool removeRamp();\r\n\tbool removeFloor();\r\n\tbool construct();\r\n\tbool constructDugStairs();\r\n\tbool constructDugRamp();\r\n\tbool constructAnimate();\r\n\tbool createItem();\r\n\tbool plantTree();\r\n\tbool fellTree();\r\n\tbool harvest();\r\n\tbool harvestHay();\r\n\tbool plant();\r\n\tbool removePlant();\r\n\tbool till();\r\n\tbool craft();\r\n\tbool deconstruct();\r\n\tbool fish();\r\n\tbool butcherFish();\r\n\tbool butcherCorpse();\r\n\tbool prepareSpell();\r\n\tbool castSpell();\r\n\tbool castSpellAnimate();\r\n\tbool finishSpell();\r\n\tbool switchMechanism();\r\n\tbool invertMechanism();\r\n\tbool refuel();\r\n\tbool install();\r\n\tbool uninstall();\r\n\tbool fillTrough();\r\n\tbool soundAlarm();\r\n};"
  },
  {
    "path": "src/game/creature.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creature.h\"\r\n#include \"../game/game.h\"\r\n\r\n#include \"../base/behaviortree/bt_factory.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/logger.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/eventmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/room.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nCreature::Creature( const Position& pos, QString name, Gender gender, QString species, Game* game ) :\r\n\tg( game ),\r\n\tObject( pos ),\r\n\tm_name( name ),\r\n\tm_gender( gender ),\r\n\tm_species( species ),\r\n\tm_moveDelay( 250 ),\r\n\tm_moveCooldown( m_moveDelay ),\r\n\tm_moveSpeed( 30 ),\r\n\tm_facing( 0 )\r\n{\r\n}\r\n\r\nCreature::Creature( QVariantMap in, Game* game ) :\r\n\tg( game ),\r\n\tObject( in ),\r\n\tm_attributes( in.value( \"Attributes\" ).toMap() ),\r\n\tm_skills( in.value( \"Skills\" ).toMap() ),\r\n\t//QMap<QString, unsigned int> m_spriteUIDs;\r\n\tm_spriteUIDs( in.value( \"spritUIDs\" ).toMap() ),\r\n\tm_spriteDef( in.value( \"SpriteDef\" ).toList() ),\r\n\tm_spriteDefBack( in.value( \"SpriteDefBack\" ).toList() ),\r\n\t//float m_moveDelay;\r\n\t//m_moveDelay( in.value( \"MoveDelay\" ).toFloat() ),\r\n\tm_moveDelay( 250 ),\r\n\tm_moveCooldown( in.value( \"MoveCooldown\" ).toFloat() ),\r\n\t//float m_moveSpeed;\r\n\tm_moveSpeed( in.value( \"Speed\" ).toFloat() ),\r\n\t//quint8 m_facing;\r\n\tm_facing( in.value( \"Orientation\" ).value<quint8>() ),\r\n\t//unsigned int m_followID = 0;\r\n\tm_followID( in.value( \"FollowID\" ).toUInt() ),\r\n\t//Position m_followPosition;\r\n\tm_followPosition( in.value( \"FollowPosition\" ) ),\r\n\t//Gender m_gender = UNDEFINED;\r\n\tm_gender( (Gender)in.value( \"Gender\" ).value<quint8>() ),\r\n\tm_species( in.value( \"Species\" ).toString() ),\r\n\t//QString m_name = \"not_initialized\";\r\n\tm_name( in.value( \"Name\" ).toString() ),\r\n\t//bool m_immobile = false;\r\n\tm_immobile( in.value( \"Immobile\" ).toBool() ),\r\n\t//bool m_renderParamsChanged = true;\r\n\tm_renderParamsChanged( in.value( \"rpc\" ).toBool() ),\r\n\t//QString m_currentAction = \"idle\";\r\n\tm_currentAction( in.value( \"CurrentAction\" ).toString() ),\r\n\t//int m_state = 0;\r\n\tm_state( in.value( \"State\" ).toInt() ),\r\n\t//quint64 m_stateChangeTick = 0;\r\n\tm_stateChangeTick( in.value( \"sct\" ).value<quint64>() ),\r\n\t//bool m_isDead = false;\r\n\tm_isDead( in.value( \"IsDead\" ).toBool() ),\r\n\t//bool m_toDestroy = false;\r\n\tm_toDestroy( in.value( \"ToDestroy\" ).toBool() ),\r\n\t//unsigned char m_type = CreatureType::UNDEFINED\r\n\tm_type( (CreatureType)in.value( \"Type\" ).value<quint8>() ),\r\n\tm_ignoreNoPass( in.value( \"IgnoreNoPass\" ).toBool() ),\r\n\tm_lightIntensity( in.value( \"LightIntensity\" ).toInt() ),\r\n\tm_roleID( in.value( \"Role\" ).toUInt() ),\r\n\r\n\tm_currentTargetPosition( Position( in.value( \"CurrentTargetPos\" ) ) ),\r\n\r\n\tm_facingAfterMove( in.value( \"FacingAfterMove\" ).toUInt() ),\r\n\r\n\tm_expires( in.value( \"Expires\" ).value<quint64>() ),\r\n\r\n\tm_currentAttackTarget( in.value( \"CurrentAttackTarget\" ).toUInt() ),\r\n\r\n\tm_goneOffMap( in.value( \"GoneOffMap\" ).toBool() ),\r\n\r\n\t//combat variables\r\n\tm_lastOnTick( in.value( \"LastonTick\" ).value<quint64>() ),\r\n\tm_globalCooldown( in.value( \"globalCooldown\" ).toInt() ),\r\n\tm_kickCooldown( in.value( \"kickCooldown\" ).toInt() ),\r\n\tm_leftHandCooldown( in.value( \"leftHandCooldown\" ).toInt() ),\r\n\tm_rightHandCooldown( in.value( \"rightHandCooldown\" ).toInt() ),\r\n\tm_specialAttackCoolDown( in.value( \"specialAttackCoolDown\" ).toInt() ),\r\n\tm_jobCooldown( in.value( \"jobCoolDown\" ).toInt() ),\r\n\r\n\tm_leftHandAttackValue( in.value( \"leftHandAttackValue\" ).toInt() ),\r\n\tm_leftHandAttackSkill( in.value( \"leftHandAttackSkill\" ).toInt() ),\r\n\tm_rightHandAttackValue( in.value( \"rightHandAttackValue\" ).toInt() ),\r\n\tm_rightHandAttackSkill( in.value( \"rightHandAttackSkill\" ).toInt() ),\r\n\r\n\tm_leftHandArmed( in.value( \"leftHandArmed\" ).toBool() ),\r\n\tm_rightHandArmed( in.value( \"rightHandArmed\" ).toBool() ),\r\n\tm_leftHandHasWeapon( in.value( \"leftHandHasWeapon\" ).toBool() ),\r\n\r\n\tm_isOnMission( in.value( \"IsOnMission\" ).toBool() ),\r\n\tm_mission( in.value( \"Mission\" ).toUInt() ),\r\n\tm_nextCheckTick( in.value( \"NextCheckTick\" ).value<quint64>() ),\r\n\r\n\tm_btName( in.value( \"BTName\" ).toString() ),\r\n\r\n\tm_btBlackBoard( in.value( \"BTBlackBoard\" ).toMap() )\r\n{\r\n\tm_currentPath.clear();\r\n\r\n\tfor ( auto cpp : in.value( \"CurrentPath\" ).toList() )\r\n\t{\r\n\t\tm_currentPath.push_back( Position( cpp ) );\r\n\t}\r\n\r\n\tif ( in.contains( \"BehaviorTreeState\" ) )\r\n\t{\r\n\t\tm_btBlackBoard.insert( \"State\", in.value( \"BehaviorTreeState\" ) );\r\n\t}\r\n\tif ( in.contains( \"Anatomy\" ) )\r\n\t{\r\n\t\tm_anatomy.deserialize( in.value( \"Anatomy\" ).toMap() );\r\n\t}\r\n\tif ( in.contains( \"ClaimedItems\" ) )\r\n\t{\r\n\t\tm_claimedItems = Global::util->variantList2UInt( in.value( \"ClaimedItems\" ).toList() );\r\n\t}\r\n\tif ( in.contains( \"CarriedItems\" ) )\r\n\t{\r\n\t\tm_carriedItems = Global::util->variantList2UInt( in.value( \"CarriedItems\" ).toList() );\r\n\t}\r\n\tif ( in.contains( \"InventoryItems\" ) )\r\n\t{\r\n\t\tm_inventoryItems = Global::util->variantList2UInt( in.value( \"InventoryItems\" ).toList() );\r\n\t}\r\n\tif( m_lightIntensity )\r\n\t{\r\n\t\tg->w()->addLight( m_id, m_position, m_lightIntensity );\r\n\t}\r\n}\r\n\r\nvoid Creature::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"Species\", m_species );\r\n\t//std::vector<Position>m_currentPath;\r\n\tif ( m_currentPath.size() )\r\n\t{\r\n\t\tQVariantList curPa;\r\n\t\tfor ( auto cpp : m_currentPath )\r\n\t\t{\r\n\t\t\tcurPa.append( cpp.toString() );\r\n\t\t}\r\n\t\tout.insert( \"CurrentPath\", curPa );\r\n\t}\r\n\tout.insert( \"Attributes\", m_attributes );\r\n\tout.insert( \"Skills\", m_skills );\r\n\r\n\tout.insert( \"BTBlackBoard\", m_btBlackBoard );\r\n\r\n\t//QMap<QString, unsigned int> m_spriteUIDs;\r\n\tout.insert( \"spritUIDs\", m_spriteUIDs );\r\n\tout.insert( \"SpriteDef\", m_spriteDef );\r\n\tout.insert( \"SpriteDefBack\", m_spriteDefBack );\r\n\t//float m_moveDelay;\r\n\tout.insert( \"MoveDelay\", m_moveDelay );\r\n\tout.insert( \"MoveCooldown\", m_moveCooldown );\r\n\t//float m_moveSpeed;\r\n\tout.insert( \"Speed\", m_moveSpeed );\r\n\t//quint8 m_facing;\r\n\tout.insert( \"Orientation\", m_facing );\r\n\t//unsigned int m_followID = 0;\r\n\tout.insert( \"FollowID\", m_followID ),\r\n\t//Position m_followPosition;\r\n\tout.insert( \"FollowPosition\", m_followPosition.toString() ),\r\n\t//Gender m_gender = UNDEFINED;\r\n\tout.insert( \"Gender\", (unsigned char)m_gender );\r\n\t//QString m_name = \"not_initialized\";\r\n\tout.insert( \"Name\", m_name );\r\n\t//bool m_immobile = false;\r\n\tout.insert( \"Immobile\", m_immobile );\r\n\t//bool m_renderParamsChanged = true;\r\n\tout.insert( \"rpc\", m_renderParamsChanged );\r\n\t//QString m_currentAction = \"idle\";\r\n\tout.insert( \"CurrentAction\", m_currentAction );\r\n\t//int m_state = 0;\r\n\tout.insert( \"State\", m_state );\r\n\t//quint64 m_stateChangeTick = 0;\r\n\tout.insert( \"sct\", m_stateChangeTick );\r\n\r\n\t//bool m_isDead = false;\r\n\tout.insert( \"IsDead\", m_isDead );\r\n\t//bool m_toDestroy = false;\r\n\tout.insert( \"ToDestroy\", m_toDestroy );\r\n\r\n\tout.insert( \"Type\", (unsigned char)m_type );\r\n\r\n\tout.insert( \"IgnoreNoPass\", m_ignoreNoPass );\r\n\tout.insert( \"Role\", m_roleID );\r\n\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tout.insert( \"BehaviorTreeState\", m_behaviorTree->serialize() );\r\n\t}\r\n\r\n\tout.insert( \"Anatomy\", m_anatomy.serialize() );\r\n\r\n\tout.insert( \"LightIntensity\", m_lightIntensity );\r\n\r\n\tout.insert( \"CurrentTargetPos\", m_currentTargetPosition.toString() );\r\n\r\n\tout.insert( \"CurrentAttackTarget\", m_currentAttackTarget );\r\n\r\n\tout.insert( \"FacingAfterMove\", m_facingAfterMove );\r\n\tout.insert( \"Expires\", m_expires );\r\n\r\n\tout.insert( \"GoneOffMap\", m_goneOffMap );\r\n\r\n\tif ( m_claimedItems.size() )\r\n\t{\r\n\t\tout.insert( \"ClaimedItems\", Global::util->uintList2Variant( m_claimedItems ) );\r\n\t}\r\n\tif ( m_carriedItems.size() )\r\n\t{\r\n\t\tout.insert( \"CarriedItems\", Global::util->uintList2Variant( m_carriedItems ) );\r\n\t}\r\n\tif ( m_inventoryItems.size() )\r\n\t{\r\n\t\tout.insert( \"InventoryItems\", Global::util->uintList2Variant( m_inventoryItems ) );\r\n\t}\r\n\r\n\t//combat variables\r\n\tout.insert( \"LastOnTick\", m_lastOnTick );\r\n\tout.insert( \"globalCooldown\", m_globalCooldown );\r\n\tout.insert( \"kickCooldown\", m_kickCooldown );\r\n\tout.insert( \"leftHandCooldown\", m_leftHandCooldown );\r\n\tout.insert( \"rightHandCooldown\", m_rightHandCooldown );\r\n\tout.insert( \"specialAttackCoolDown\", m_specialAttackCoolDown );\r\n\tout.insert( \"jobCoolDown\", m_jobCooldown );\r\n\r\n\tout.insert( \"leftHandAttackValue\", m_leftHandAttackValue );\r\n\tout.insert( \"leftHandAttackSkill\", m_leftHandAttackSkill );\r\n\tout.insert( \"rightHandAttackValue\", m_rightHandAttackValue );\r\n\tout.insert( \"rightHandAttackSkill\", m_rightHandAttackSkill );\r\n\r\n\tout.insert( \"leftHandArmed\", m_leftHandArmed );\r\n\tout.insert( \"rightHandArmed\", m_rightHandArmed );\r\n\tout.insert( \"leftHandHasWeapon\", m_leftHandHasWeapon );\r\n\r\n\tout.insert( \"IsOnMission\", m_isOnMission );\r\n\tout.insert( \"Mission\", m_mission );\r\n\tout.insert( \"NextCheckTick\", m_nextCheckTick );\r\n\r\n\tout.insert( \"BTName\", m_btName );\r\n\r\n\tObject::serialize( out );\r\n}\r\n\r\nCreature::~Creature()\r\n{\r\n}\r\n\r\nvoid Creature::setRole( unsigned int roleID )\r\n{\r\n\tm_roleID = roleID;\r\n}\r\n\r\nvoid Creature::processCooldowns( quint64 tickNumber )\r\n{\r\n\tint diff = tickNumber - m_lastOnTick;\r\n\r\n\tm_moveCooldown -= diff * m_moveSpeed;\r\n\r\n\tm_globalCooldown -= diff;\r\n\tm_kickCooldown -= diff;\r\n\tm_biteCooldown -= diff;\r\n\tm_leftHandCooldown -= diff;\r\n\tm_rightHandCooldown -= diff;\r\n\tm_specialAttackCoolDown -= diff;\r\n\tm_jobCooldown -= diff;\r\n}\r\n\r\nvoid Creature::loadBehaviorTree( QString id )\r\n{\r\n\tm_behaviorTree.reset( BT_Factory::load( id, m_behaviors, m_btBlackBoard ) );\r\n\r\n\tif ( !m_behaviorTree )\r\n\t{\r\n\t\tqCritical() << \"failed to load behavior tree!\" << id;\r\n\t}\r\n}\r\n\r\nvoid Creature::addAttribute( QString id, int level )\r\n{\r\n\tm_attributes.insert( id, level );\r\n}\r\n\r\nint Creature::attribute( QString id ) const\r\n{\r\n\tif ( m_attributes.contains( id ) )\r\n\t{\r\n\t\treturn m_attributes[id].toInt();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Creature::addSkill( QString id, int level )\r\n{\r\n\tm_skills.insert( id, level );\r\n\tm_skillActive.insert( id, false );\r\n}\r\n\r\nint Creature::getSkillLevel( QString id ) const\r\n{\r\n\tif ( m_skills.contains( id ) )\r\n\t{\r\n\t\treturn Global::util->reverseFib( m_skills.value( id ).toInt() );\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nint Creature::getSkillXP( QString id ) const\r\n{\r\n\tif ( m_skills.contains( id ) )\r\n\t{\r\n\t\treturn m_skills.value( id ).toInt();\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\nvoid Creature::setSkillLevel( QString id, int level )\r\n{\r\n\tm_skills[id] = level;\r\n}\r\n\r\nvoid Creature::forceMove( const Position& to )\r\n{\r\n\t//qDebug() << name() << \" force move from \" << m_position.toString() << \" to \" << to.toString();\r\n\tg->w()->removeCreatureFromPosition( m_position, m_id );\r\n\tm_position = to;\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n}\r\n\r\nvoid Creature::randomMove()\r\n{\r\n\tif ( m_immobile )\r\n\t\treturn;\r\n\tm_moveCooldown -= m_moveSpeed;\r\n\r\n\tif ( m_moveCooldown <= 0 )\r\n\t{\r\n\t\tbool move = !( rand() % 25 );\r\n\t\tPosition newPos;\r\n\t\tPosition testPos;\r\n\t\tqint8 newFacing = -1;\r\n\t\tif ( move )\r\n\t\t{\r\n\t\t\tif ( m_aquatic )\r\n\t\t\t{\r\n\t\t\t\tint dir = rand() % 6;\r\n\r\n\t\t\t\tswitch ( dir )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 0:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttestPos = m_position.westOf();\r\n\t\t\t\t\t\tif ( ( g->w()->getTileFlag( testPos ) & TileFlag::TF_WATER ) || g->w()->fluidLevel( testPos ) > 6 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewPos    = testPos;\r\n\t\t\t\t\t\t\tnewFacing = 2;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 1:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttestPos = m_position.eastOf();\r\n\t\t\t\t\t\tif ( ( g->w()->getTileFlag( testPos ) & TileFlag::TF_WATER ) || g->w()->fluidLevel( testPos ) > 6 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewPos    = testPos;\r\n\t\t\t\t\t\t\tnewFacing = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttestPos = m_position.northOf();\r\n\t\t\t\t\t\tif ( ( g->w()->getTileFlag( testPos ) & TileFlag::TF_WATER ) || g->w()->fluidLevel( testPos ) > 6 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewPos    = testPos;\r\n\t\t\t\t\t\t\tnewFacing = 3;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttestPos = m_position.southOf();\r\n\t\t\t\t\t\tif ( ( g->w()->getTileFlag( testPos ) & TileFlag::TF_WATER ) || g->w()->fluidLevel( testPos ) > 6 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewPos    = testPos;\r\n\t\t\t\t\t\t\tnewFacing = 1;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 4:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttestPos = m_position.aboveOf();\r\n\t\t\t\t\t\tif ( ( g->w()->getTileFlag( testPos ) & TileFlag::TF_WATER ) || g->w()->fluidLevel( testPos ) > 6 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewPos    = testPos;\r\n\t\t\t\t\t\t\tnewFacing = m_facing;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 5:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttestPos = m_position.belowOf();\r\n\t\t\t\t\t\tif ( ( g->w()->getTileFlag( testPos ) & TileFlag::TF_WATER ) || g->w()->fluidLevel( testPos ) > 6 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewPos    = testPos;\r\n\t\t\t\t\t\t\tnewFacing = m_facing;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( newFacing != -1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_position = newPos;\r\n\t\t\t\t\tm_facing   = newFacing;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tauto neighbors = g->w()->connectedNeighbors( m_position );\r\n\t\t\t\tif ( neighbors.size() > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tint dir   = rand() % neighbors.size();\r\n\t\t\t\t\tnewPos    = neighbors[dir];\r\n\t\t\t\t\tif ( !g->w()->isWalkableGnome( newPos ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tnewFacing = m_facing;\r\n\t\t\t\t\tif ( m_position.x != newPos.x )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( m_position.x - newPos.x > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewFacing = 2;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewFacing = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( m_position.y != newPos.y )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( m_position.y - newPos.y > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewFacing = 3;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tnewFacing = 1;\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\tswitch ( m_type )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase CreatureType::GNOME:\r\n\t\t\t\t\tcase CreatureType::GNOME_TRADER:\r\n\t\t\t\t\t\tif ( g->cm()->monstersAtPosition( newPos ).size() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( g->w()->getTileFlag( newPos ) & TileFlag::TF_NOPASS )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CreatureType::ANIMAL:\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( g->rm()->isDoor( newPos.toInt() ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( g->rm()->blockAnimals( newPos.toInt() ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn;\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\tbreak;\r\n\t\t\t\t\tcase CreatureType::MONSTER:\r\n\t\t\t\t\t\tif ( g->gm()->gnomesAtPosition( newPos ).size() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\tif ( newFacing != -1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_position = newPos;\r\n\t\t\t\t\tm_facing   = newFacing;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_moveCooldown = m_moveDelay;\r\n\t}\r\n}\r\n\r\nint Creature::moveSpeed() const\r\n{\r\n\treturn m_moveSpeed;\r\n}\r\n\r\nbool Creature::moveOnPath()\r\n{\r\n\tif ( m_moveCooldown <= 0 )\r\n\t{\r\n\t\t//get position from path\r\n\t\tif ( !m_currentPath.empty() )\r\n\t\t{\r\n\t\t\tPosition p = m_currentPath.back();\r\n\t\t\tm_currentPath.pop_back();\r\n\r\n\t\t\t// check if we can move onto the next position\r\n\t\t\tif ( !g->w()->isWalkableGnome( p ) )\r\n\t\t\t{\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\tqDebug() << \"moveOnPath tile blocked \" << p.toString();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tDoor* door = g->rm()->getDoor( p.toInt() );\r\n\t\t\tif ( door )\r\n\t\t\t{\r\n\t\t\t\tswitch ( m_type )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase CreatureType::GNOME:\r\n\t\t\t\t\tcase CreatureType::GNOME_TRADER:\r\n\t\t\t\t\t\tif ( door->blockGnomes )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_currentPath.clear();\r\n\t\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\t\tqDebug() << \"moveOnPath door closed for gnomes \" << p.toString();\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CreatureType::ANIMAL:\r\n\t\t\t\t\t\tif ( door->blockAnimals )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_currentPath.clear();\r\n\t\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\t\tqDebug() << \"moveOnPath door closed for animals \" << p.toString();\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase CreatureType::MONSTER:\r\n\t\t\t\t\t\tif ( door->blockMonsters )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_currentPath.clear();\r\n\t\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\t\tqDebug() << \"moveOnPath door closed for monsters \" << p.toString();\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tswitch ( m_type )\r\n\t\t\t{\r\n\t\t\t\tcase CreatureType::GNOME:\r\n\t\t\t\tcase CreatureType::GNOME_TRADER:\r\n\t\t\t\t\tif ( g->cm()->monstersAtPosition( p ).size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_currentPath.clear();\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tqDebug() << \"moveOnPath gnome can't move onto a tile occupied by monsters \" << p.toString();\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase CreatureType::ANIMAL:\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase CreatureType::MONSTER:\r\n\t\t\t\t\tif ( g->gm()->gnomesAtPosition( p ).size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_currentPath.clear();\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tqDebug() << \"moveOnPath monster can't move onto a tile occupied by gnomes \" << p.toString();\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t// move on path\r\n\t\t\tm_facing   = getFacing( m_position, p );\r\n\t\t\tm_position = p;\r\n\r\n\t\t\t//m_sprite.dimX = 32;\r\n\t\t\t//m_sprite.dimY = 32;\r\n\t\t\tif ( m_currentPath.empty() )\r\n\t\t\t{\r\n\t\t\t\tif ( m_facingAfterMove != -1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_facing = m_facingAfterMove;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_renderParamsChanged = true;\r\n\t\tm_moveCooldown        = m_moveDelay; // TODO movedelay =\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nint Creature::getFacing( Position posFrom, Position posTo )\r\n{\r\n\tint dx = posTo.x - posFrom.x;\r\n\tint dy = posTo.y - posFrom.y;\r\n\r\n\tif ( ( dx == 1 && dy == 0 ) || ( dx == 1 && dy == 1 ) )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\tif ( ( dx == 0 && dy == 1 ) || ( dx == -1 && dy == 1 ) )\r\n\t{\r\n\t\treturn 1;\r\n\t}\r\n\tif ( ( dx == -1 && dy == 0 ) || ( dx == -1 && dy == -1 ) )\r\n\t{\r\n\t\treturn 2;\r\n\t}\r\n\tif ( ( dx == 0 && dy == -1 ) || ( dx == 1 && dy == -1 ) )\r\n\t{\r\n\t\treturn 3;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Creature::setFollowID( unsigned int id )\r\n{\r\n\tm_followID = id;\r\n}\r\n\r\nunsigned int Creature::followID() const\r\n{\r\n\treturn m_followID;\r\n}\r\n\r\nvoid Creature::setFollowPosition( Position pos )\r\n{\r\n\tm_followPosition = pos;\r\n\tint dx           = pos.x - m_position.x;\r\n\tint dy           = pos.y - m_position.y;\r\n\r\n\tif ( ( dx == 1 && dy == 0 ) || ( dx == 1 && dy == 1 ) )\r\n\t{\r\n\t\tm_facing = 0;\r\n\t}\r\n\tif ( ( dx == 0 && dy == 1 ) || ( dx == -1 && dy == 1 ) )\r\n\t{\r\n\t\tm_facing = 1;\r\n\t}\r\n\tif ( ( dx == -1 && dy == 0 ) || ( dx == -1 && dy == -1 ) )\r\n\t{\r\n\t\tm_facing = 2;\r\n\t}\r\n\tif ( ( dx == 0 && dy == -1 ) || ( dx == 1 && dy == -1 ) )\r\n\t{\r\n\t\tm_facing = 3;\r\n\t}\r\n}\r\n\r\nvoid Creature::setSpriteUID( QString name, unsigned int spriteUID )\r\n{\r\n\tm_spriteUIDs.insert( name, spriteUID );\r\n}\r\n\r\nunsigned int Creature::spriteUID( QString name ) const\r\n{\r\n\tif ( !m_spriteUIDs.empty() )\r\n\t{\r\n\t\treturn m_spriteUIDs.value( name ).toUInt();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn m_spriteID;\r\n\t}\r\n}\r\n\r\nunsigned int Creature::spriteUID() const\r\n{\r\n\treturn m_spriteID;\r\n}\r\n\r\nvoid Creature::setGender( Gender gender )\r\n{\r\n\tm_gender = gender;\r\n}\r\n\r\nvoid Creature::move( Position oldPos )\r\n{\r\n\tif ( m_position != oldPos )\r\n\t{\r\n\t\tg->w()->removeCreatureFromPosition( oldPos, m_id );\r\n\t\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\r\n\t\tif( m_hasTransparency )\r\n\t\t{\r\n\t\t\tg->w()->setTileFlag( m_position, TileFlag::TF_TRANSPARENT );\r\n\t\t\t// check if no other creatures with transparency on tile\r\n\t\t\tbool transp = false;\r\n\t\t\tfor( const auto& c : g->cm()->creaturesAtPosition( oldPos ) )\r\n\t\t\t{\r\n\t\t\t\tif( c->hasTransparency() )\r\n\t\t\t\t{\r\n\t\t\t\t\ttransp = true;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif( !transp )\r\n\t\t\t{\r\n\t\t\t\tg->w()->clearTileFlag( oldPos, TileFlag::TF_TRANSPARENT );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_renderParamsChanged = true;\r\n\t}\r\n}\r\n\r\nbool Creature::renderParamsChanged()\r\n{\r\n\tbool out              = m_renderParamsChanged;\r\n\tm_renderParamsChanged = false;\r\n\treturn out;\r\n}\r\n\r\nvoid Creature::setImmobile( bool immobile )\r\n{\r\n\tm_immobile = immobile;\r\n}\r\n\r\nvoid Creature::setIgnoreNoPass( bool state )\r\n{\r\n\tm_ignoreNoPass = state;\r\n}\r\n\r\nbool Creature::ignoreNoPass() const\r\n{\r\n\treturn m_ignoreNoPass;\r\n}\r\n\r\nvoid Creature::setType( CreatureType type )\r\n{\r\n\tm_type = type;\r\n}\r\n\r\nCreatureType Creature::type() const\r\n{\r\n\treturn m_type;\r\n}\r\n\r\nBT_RESULT Creature::actionRandomMove( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tPosition oldPos = m_position;\r\n\r\n\trandomMove();\r\n\r\n\tif ( m_lightIntensity && m_position != oldPos )\r\n\t{\r\n\t\tg->w()->moveLight( m_id, m_position, m_lightIntensity );\r\n\t}\r\n\r\n\tm_currentAction = \"random move\";\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsMale( bool halt )\r\n{\r\n\tif ( m_gender == Gender::MALE )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsFemale( bool halt )\r\n{\r\n\tif ( m_gender == Gender::FEMALE )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsDay( bool halt )\r\n{\r\n\tif ( GameState::daylight )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsNight( bool halt )\r\n{\r\n\tif ( !GameState::daylight )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nvoid Creature::setCurrentTarget( Position pos )\r\n{\r\n\tm_currentTargetPosition = pos;\r\n\t//m_variables.insert( \"CurrentTargetPos\", pos.toString() );\r\n}\r\n\r\nPosition Creature::currentTarget() const\r\n{\r\n\treturn m_currentTargetPosition;\r\n\t//return Position( m_variables.value( \"CurrentTargetPos\" ) );\r\n}\r\n\r\nbool Creature::kill( bool nocorpse )\r\n{\r\n\tif ( !toDestroy() && !isDead() )\r\n\t{\r\n\t\t//kill succeeds\r\n\t\tif( nocorpse )\r\n\t\t{\r\n\t\t\tdestroy();\r\n\t\t}\r\n\t\tdie();\r\n\t\treturn true;\r\n\t}\r\n\t// already dead or something else destroyed it\r\n\treturn false;\r\n}\r\n\r\nvoid Creature::setThoughtBubble( QString thought )\r\n{\r\n\tm_thoughtBubble = thought;\r\n}\r\n\r\nQString Creature::thoughtBubble() const\r\n{\r\n\treturn m_thoughtBubble;\r\n}\r\n\r\nquint64 Creature::expires() const\r\n{\r\n\treturn m_expires;\r\n}\r\n\r\nBT_RESULT Creature::conditionTargetAdjacent( bool halt )\r\n{\r\n\tCreature* creature = nullptr;\r\n\tif ( m_currentAttackTarget )\r\n\t{\r\n\t\tcreature = resolveTarget( m_currentAttackTarget );\r\n\t}\r\n\r\n\tif ( creature )\r\n\t{\r\n\t\tPosition cPos = creature->getPos();\r\n\t\tif ( m_position.z == cPos.z )\r\n\t\t{\r\n\t\t\tif ( abs( m_position.x - cPos.x ) < 2 && abs( m_position.y - cPos.y ) < 2 )\r\n\t\t\t{\r\n\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\tqDebug() << m_name << \"Target is adjacent\";\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << m_name << \"Target is not adjacent\";\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionTargetPositionValid( bool halt )\r\n{\r\n\tCreature* creature = nullptr;\r\n\tif ( m_currentAttackTarget )\r\n\t{\r\n\t\tcreature = resolveTarget( m_currentAttackTarget );\r\n\t}\r\n\tif (creature)\r\n\t{\r\n\t\tif ( creature->getPos() == m_currentTargetPosition )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsInCombat( bool halt )\r\n{\r\n\tif ( m_currentAttackTarget )\r\n\t{\r\n\t\tconst Creature* creature = g->cm()->creature( m_currentAttackTarget );\r\n\t\tif ( !creature || creature->isDead() || !g->cm()->hasPathTo( m_position, m_currentAttackTarget ) )\r\n\t\t{\r\n\t\t\tm_currentAttackTarget = 0;\r\n\t\t}\r\n\t}\r\n\tif ( m_aggroList.size() || m_currentAttackTarget )\r\n\t{\r\n\t\tsetThoughtBubble( \"Combat\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\tif ( m_thoughtBubble == \"Combat\" )\r\n\t{\r\n\t\tsetThoughtBubble( \"\" );\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsOnMission( bool halt )\r\n{\r\n\tif ( m_isOnMission )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::actionGetExitPosition( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( m_mission )\r\n\t{\r\n\t\tauto mission = g->em()->getMission( m_mission );\r\n\t\tif ( mission )\r\n\t\t{\r\n\t\t\tif ( mission->leavePos != Position( 0, 0, 0 ) )\r\n\t\t\t{\r\n\t\t\t\tsetCurrentTarget( mission->leavePos );\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbool found        = false;\r\n\t\t\t\tPosition leavePos = Global::util->reachableBorderPos( m_position, found );\r\n\t\t\t\tif ( found )\r\n\t\t\t\t{\r\n\t\t\t\t\tmission->leavePos = leavePos;\r\n\t\t\t\t\tsetCurrentTarget( leavePos );\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_mission = 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tbool found        = false;\r\n\t\tPosition leavePos = Global::util->reachableBorderPos( m_position, found );\r\n\t\tif ( found )\r\n\t\t{\r\n\t\t\tsetCurrentTarget( leavePos );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Creature::actionLeaveMap( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tg->w()->removeCreatureFromPosition( m_position, m_id );\r\n\tm_goneOffMap = true;\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Creature::actionEnterMap( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\tm_goneOffMap = false;\r\n\r\n\tm_mission     = 0;\r\n\tm_isOnMission = false;\r\n\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nQList<AggroEntry>& Creature::aggroList()\r\n{\r\n\treturn m_aggroList;\r\n}\r\n\r\nvoid Creature::addAggro( unsigned int target, int value )\r\n{\r\n\tbool exists = false;\r\n\tfor ( auto& ae : m_aggroList )\r\n\t{\r\n\t\tif ( ae.id == target )\r\n\t\t{\r\n\t\t\tae.aggro += value;\r\n\t\t\texists = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !exists )\r\n\t{\r\n\t\tAggroEntry ae { value, target };\r\n\t\tm_aggroList.append( ae );\r\n\t}\r\n\tstd::sort( m_aggroList.begin(), m_aggroList.end() );\r\n}\r\n\r\nvoid Creature::updateAttackValues()\r\n{\r\n\tm_leftHandAttackSkill  = getSkillLevel( \"Unarmed\" );\r\n\tm_leftHandAttackValue  = m_leftHandAttackSkill;\r\n\tm_rightHandAttackSkill = getSkillLevel( \"Unarmed\" );\r\n\tm_rightHandAttackValue = m_rightHandAttackSkill;\r\n}\r\n\r\nvoid Creature::die()\r\n{\r\n\tm_isDead = true;\r\n\tdropInventory();\r\n\tdropEquipment();\r\n\tupdateSprite();\r\n}\r\n\r\nvoid Creature::dropInventory()\r\n{\r\n\tfor ( const unsigned int it : inventoryItems() )\r\n\t{\r\n\t\tg->inv()->putDownItem( it, m_position );\r\n\t}\r\n\tm_inventoryItems.clear();\r\n}\r\n\r\nvoid Creature::dropEquipment()\r\n{\r\n\tfor ( const unsigned int it : m_equipment.wornItems() )\r\n\t{\r\n\t\tg->inv()->putDownItem( it, m_position );\r\n\t}\r\n\tm_equipment.clearAllItems();\r\n}\r\n\r\nvoid Creature::addClaimedItem( unsigned int item, unsigned int job )\r\n{\r\n\tif( job == m_id )\r\n\t{\r\n\t\tg->inv()->setIsUsedBy( item, job );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tg->inv()->setInJob( item, job );\r\n\t}\r\n\tm_claimedItems.append( item );\r\n}\r\n\r\nvoid Creature::unclaimAll()\r\n{\r\n\tif ( !m_claimedItems.empty() )\r\n\t{\r\n\t\tfor ( auto item : m_claimedItems )\r\n\t\t{\r\n\t\t\tg->inv()->setInJob( item, 0 );\r\n\t\t\tg->inv()->setIsUsedBy( item, 0 );\r\n\t\t\tif ( g->inv()->isHeldBy( item ) == m_id )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->putDownItem( item, m_position );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_claimedItems.clear();\r\n}\r\n\r\nvoid Creature::destroyClaimedItems()\r\n{\r\n\tfor ( auto item : m_claimedItems )\r\n\t{\r\n\t\tg->inv()->pickUpItem( item, m_id );\r\n\t\tg->inv()->destroyObject( item );\r\n\t}\r\n\tm_claimedItems.clear();\r\n}\r\n\r\nCreature* Creature::resolveTarget( unsigned int creatureId )\r\n{\r\n\tCreature* creature = g->cm()->creature( m_currentAttackTarget );\r\n\tif ( !creature )\r\n\t{\r\n\t\tcreature = g->gm()->gnome( m_currentAttackTarget );\r\n\t}\r\n\treturn creature;\r\n}\r\n\r\nvoid Creature::log( QString txt )\r\n{\r\n\tif ( m_log.size() > 0 )\r\n\t{\r\n\t\tif ( m_log.last().endsWith( txt ) )\r\n\t\t{\r\n\t\t\t++m_sameMsgCounter;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( m_sameMsgCounter > 0 )\r\n\t\t\t{\r\n\t\t\t\tm_log.last() += \" x\" + QString::number( m_sameMsgCounter );\r\n\t\t\t\tm_sameMsgCounter = 0;\r\n\t\t\t}\r\n\t\t\tm_log.append( GameState::currentDayTime + \": \" + txt );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_log.append( GameState::currentDayTime + \": \" + txt );\r\n\t}\r\n\tif ( m_log.size() > 50 )\r\n\t{\r\n\t\tfor ( int i = 0; i < 25; ++i )\r\n\t\t{\r\n\t\t\tm_log.takeFirst();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQStringList Creature::needIDs() const\r\n{\r\n\treturn m_needs.keys();\r\n}\r\n\r\nQStringList Creature::availableSkillIDs() const\r\n{\r\n\treturn m_skills.keys();\r\n}\r\n\r\nBT_RESULT Creature::conditionAlarm( bool halt )\r\n{\r\n\tif ( GameState::alarm == 2 )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::conditionIsInSafeRoom( bool halt )\r\n{\r\n\tauto room = g->rm()->getRoomAtPos( m_position );\r\n\tif ( room )\r\n\t{\r\n\t\tif ( room->id() == GameState::alarmRoomID )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Creature::actionGetSafeRoomPosition( bool halt )\r\n{\r\n\tauto room = g->rm()->getRoom( GameState::alarmRoomID );\r\n\tif ( room )\r\n\t{\r\n\t\tauto pos = room->randomTilePos();\r\n\t\tif ( pos.isZero() )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_currentTargetPosition = pos;\r\n\t\t\tm_thoughtBubble         = \"\";\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nbool Creature::equipmentChanged()\r\n{\r\n\tbool tmp = m_equipmentChanged;\r\n\tm_equipmentChanged = false;\r\n\treturn tmp;\r\n}"
  },
  {
    "path": "src/game/creature.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/behaviortree/bt_node.h\"\r\n#include \"../base/pathfinder.h\"\r\n#include \"../base/priorityqueue.h\"\r\n#include \"../game/anatomy.h\"\r\n#include \"object.h\"\r\n\r\n#include <QPixmap>\r\n\r\nclass QPainter;\r\nclass Game;\r\n\r\nstruct AggroEntry\r\n{\r\n\tint aggro       = 0;\r\n\tunsigned int id = 0;\r\n\r\n\tbool operator==( const AggroEntry& other )\r\n\t{\r\n\t\treturn this->aggro == other.aggro;\r\n\t}\r\n\tbool operator!=( const AggroEntry& other )\r\n\t{\r\n\t\treturn this->aggro != other.aggro;\r\n\t}\r\n\tbool operator<( const AggroEntry& other )\r\n\t{\r\n\t\treturn this->aggro < other.aggro;\r\n\t}\r\n\tfriend bool operator<( const AggroEntry& lhs, const AggroEntry& rhs )\r\n\t{\r\n\t\treturn lhs.aggro < rhs.aggro;\r\n\t}\r\n};\r\n\r\nenum class Gender : unsigned char\r\n{\r\n\tUNDEFINED = 0,\r\n\tMALE      = 1,\r\n\tFEMALE    = 2\r\n};\r\n\r\nenum class CreatureType : unsigned char\r\n{\r\n\tUNDEFINED = 0,\r\n\tGNOME     = 1,\r\n\tGNOME_TRADER,\r\n\tANIMAL,\r\n\tMONSTER,\r\n\tAUTOMATON\r\n};\r\n\r\nenum class CreatureTickResult : unsigned char\r\n{\r\n\tDEAD,\r\n\tOK,\r\n\tJOBCHANGED,\r\n\tTODESTROY,\r\n\tNOFLOOR,\r\n\tLEFTMAP,\r\n\tNOFUEL,\r\n\tNOCORE\r\n};\r\n\r\nstruct EquipmentItem\r\n{\r\n\tQString item            = \"\";\r\n\tQString material        = \"\";\r\n\tunsigned int itemID     = 0;\r\n\tunsigned int materialID = 0;\r\n\tQStringList allMats;\r\n\r\n\tQVariantMap serialize();\r\n\tEquipmentItem( const QVariantMap& in );\r\n\r\n\tEquipmentItem() {};\r\n};\r\n\r\nstruct Equipment\r\n{\r\n\tQString hair       = \"GnomeHair1\";\r\n\tQString facialHair = \"\";\r\n\tint hairColor      = 0;\r\n\tQString shirt      = \"GnomeShirt1\";\r\n\tint shirtColor     = 0;\r\n\r\n\tunsigned int uniformID = 0;\r\n\tunsigned int roomID    = 0;\r\n\r\n\tEquipmentItem head;\r\n\tEquipmentItem chest;\r\n\tEquipmentItem arm;\r\n\tEquipmentItem hand;\r\n\tEquipmentItem leg;\r\n\tEquipmentItem foot;\r\n\tEquipmentItem leftHandHeld;\r\n\tEquipmentItem rightHandHeld;\r\n\tEquipmentItem back;\r\n\r\n\tQList<unsigned int> wornItems() const;\r\n\tQVariantMap serialize();\r\n\tvoid clearAllItems();\r\n\tEquipment( const QVariantMap& in );\r\n\tfloat getDamageReduction( CreaturePart part );\r\n\tEquipmentItem& getSlot( CreaturePart part );\r\n\r\n\tEquipment() {};\r\n};\r\n\r\nclass Creature : public Object\r\n{\r\npublic:\r\n\tCreature( const Position& pos, QString name, Gender gender, QString species, Game* game );\r\n\tCreature( QVariantMap in, Game* game );\r\n\t~Creature();\r\n\r\n\tbool operator<( const Creature& other ) const\r\n\t{\r\n\t\treturn this->m_name < other.m_name;\r\n\t}\r\n\r\n\tvirtual void serialize( QVariantMap& out ) const;\r\n\r\n\tvirtual void init() = 0;\r\n\r\n\tvirtual void updateSprite() = 0;\r\n\r\n\tvoid forceMove( const Position& to );\r\n\r\n\tvirtual CreatureTickResult onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged ) = 0;\r\n\r\n\tquint8 facing() const\r\n\t{\r\n\t\treturn m_facing;\r\n\t}\r\n\r\n\tvoid setGender( Gender gender );\r\n\tGender gender() const\r\n\t{\r\n\t\treturn m_gender;\r\n\t}\r\n\r\n\tQString species() const\r\n\t{\r\n\t\treturn m_species;\r\n\t}\r\n\r\n\tvoid setSpriteUID( QString name, unsigned int spriteUID );\r\n\tunsigned int spriteUID( QString name ) const;\r\n\tunsigned int spriteUID() const;\r\n\r\n\tbool renderParamsChanged();\r\n\r\n\tbool isDead() const\r\n\t{\r\n\t\treturn m_isDead;\r\n\t};\r\n\tbool toDestroy() const\r\n\t{\r\n\t\treturn m_toDestroy;\r\n\t}\r\n\tvoid destroy()\r\n\t{\r\n\t\tm_toDestroy = true;\r\n\t}\r\n\r\n\tvoid setImmobile( bool immobile );\r\n\r\n\tvoid addAttribute( QString id, int level );\r\n\tint attribute( QString id ) const;\r\n\tvoid addSkill( QString id, int level );\r\n\tint getSkillLevel( QString id ) const;\r\n\tvoid setSkillLevel( QString id, int level );\r\n\tint getSkillXP( QString id ) const;\r\n\r\n\tvirtual void updateMoveSpeed() = 0;\r\n\tint moveSpeed() const;\r\n\r\n\tQString name() const\r\n\t{\r\n\t\treturn m_name;\r\n\t}\r\n\tvoid setName( QString name )\r\n\t{\r\n\t\tm_name = name;\r\n\t}\r\n\r\n\tvoid setIgnoreNoPass( bool state );\r\n\tbool ignoreNoPass() const;\r\n\r\n\tvoid setType( CreatureType type );\r\n\tCreatureType type() const;\r\n\r\n\tunsigned int followID() const;\r\n\tvoid setFollowID( unsigned int id );\r\n\tvoid setFollowPosition( Position pos );\r\n\r\n\tvoid setCurrentTarget( Position pos );\r\n\tPosition currentTarget() const;\r\n\r\n\tbool kill( bool nocorpse );\r\n\tvirtual bool attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID ) = 0;\r\n\r\n\tQString thoughtBubble() const;\r\n\tvoid setThoughtBubble( QString thought );\r\n\r\n\tquint64 expires() const;\r\n\r\n\tQList<AggroEntry>& aggroList();\r\n\r\n\tvoid addAggro( unsigned int target, int value );\r\n\r\n\tvirtual void updateAttackValues();\r\n\r\n\tQStringList needIDs() const;\r\n\tQStringList availableSkillIDs() const;\r\n\r\n\tbool isOnMission() const\r\n\t{\r\n\t\treturn m_isOnMission;\r\n\t}\r\n\tvoid setOnMission( bool v )\r\n\t{\r\n\t\tm_isOnMission = v;\r\n\t}\r\n\tvoid setMission( unsigned int mission )\r\n\t{\r\n\t\tm_mission = mission;\r\n\t}\r\n\r\n\tbool goneOffMap() const\r\n\t{\r\n\t\treturn m_goneOffMap;\r\n\t}\r\n\r\n\tunsigned int roleID()\r\n\t{\r\n\t\treturn m_roleID;\r\n\t}\r\n\r\n\tvoid setRole( unsigned int roleID );\r\n\r\n\tQList<unsigned int> inventoryItems() const\r\n\t{\r\n\t\treturn m_inventoryItems;\r\n\t}\r\n\r\n\tQList<unsigned int> carriedItems() const\r\n\t{\r\n\t\treturn m_carriedItems;\r\n\t}\r\n\r\n\tQList<unsigned int> claimedItems()\r\n\t{\r\n\t\treturn m_claimedItems;\r\n\t}\r\n\r\n\tbool isAnimal() { return m_type == CreatureType::ANIMAL; }\r\n\tbool isMonster() { return m_type == CreatureType::MONSTER; }\r\n\r\n\tbool hasTransparency() { return m_hasTransparency; }\r\n\r\n\tbool equipmentChanged();\r\n\r\nprotected:\r\n\tQPointer<Game> g;\r\n\r\n\tvirtual void loadBehaviorTree( QString id ) final;\r\n\tvirtual void initTaskMap() = 0;\r\n\r\n\tvoid processCooldowns( quint64 tickNumber );\r\n\r\n\tvirtual void move( Position oldPos );\r\n\r\n\tvoid randomMove();\r\n\r\n\tbool moveOnPath();\r\n\r\n\tint getFacing( Position posFrom, Position posTo );\r\n\r\n\tQStringList& getLog()\r\n\t{\r\n\t\treturn m_log;\r\n\t}\r\n\r\n\tQStringList m_log;\r\n\tint m_sameMsgCounter = 0;\r\n\tvoid log( QString txt );\r\n\r\n\tCreatureType m_type = CreatureType::UNDEFINED;\r\n\tQString m_species   = \"not_initialized\";\r\n\tQString m_name      = \"not_initialized\";\r\n\tGender m_gender     = Gender::UNDEFINED;\r\n\r\n\tbool m_immobile     = false;\r\n\tbool m_aquatic      = false;\r\n\tbool m_ignoreNoPass = true;\r\n\r\n\tAnatomy m_anatomy;\r\n\r\n\tbool m_isDead     = false;\r\n\tbool m_toDestroy  = false;\r\n\tquint64 m_expires = 0;\r\n\r\n\t//variables formerlin in QVariantMap Creature::m_variables\r\n\tQVariantList m_spriteDef;\r\n\tQVariantList m_spriteDefBack;\r\n\r\n\tQVariantMap m_spriteUIDs;\r\n\tQString m_thoughtBubble    = \"\";\r\n\tbool m_renderParamsChanged = true;\r\n\r\n\tPosition m_currentTargetPosition;\r\n\tstd::vector<Position> m_currentPath;\r\n\tqint8 m_facingAfterMove = -1;\r\n\r\n\tunsigned int m_currentAttackTarget = 0;\r\n\tbool m_goneOffMap = false;\r\n\r\n\tQVariantMap m_btBlackBoard;\r\n\r\n\tQVariantMap m_attributes;\r\n\tQVariantMap m_skills;\r\n\tQVariantMap m_skillActive;\r\n\tQStringList m_skillPriorities;\r\n\tQVariantMap m_needs;\r\n\r\n\tEquipment m_equipment;\r\n\tunsigned int m_roleID = 0;\r\n\r\n\tbool m_equipmentChanged = true;\r\n\r\n\t//move cooldown cache, set to m_moveCooldown after succesful move\r\n\tfloat m_moveDelay = 1000;\r\n\t// current cooldown, prohibits move if >0\r\n\tfloat m_moveCooldown = 1000;\r\n\t// subtracted from moveCooldown every tick\r\n\tfloat m_moveSpeed       = 50;\r\n\tquint8 m_facing         = 0;\r\n\tunsigned int m_followID = 0;\r\n\tPosition m_followPosition;\r\n\r\n\t//unsigned char m_currentPriority = 0;\r\n\tQString m_currentAction = \"idle\";\r\n\r\n\tint m_state               = 0;\r\n\tquint64 m_stateChangeTick = 0;\r\n\r\n\tunsigned char m_lightIntensity = 0;\r\n\r\n\tquint64 m_lastOnTick        = 0;\r\n\tint m_globalCooldown        = 0;\r\n\tint m_kickCooldown          = 0;\r\n\tint m_biteCooldown          = 0;\r\n\tint m_leftHandCooldown      = 0;\r\n\tint m_rightHandCooldown     = 0;\r\n\tint m_specialAttackCoolDown = 0;\r\n\tint m_jobCooldown           = 0;\r\n\r\n\tint m_leftHandAttackValue  = 0;\r\n\tint m_leftHandAttackSkill  = 0;\r\n\tint m_rightHandAttackValue = 0;\r\n\tint m_rightHandAttackSkill = 0;\r\n\r\n\tbool m_leftHandArmed     = false;\r\n\tbool m_rightHandArmed    = false;\r\n\tbool m_leftHandHasWeapon = false;\r\n\r\n\tbool m_isOnMission      = false;\r\n\tunsigned int m_mission  = 0;\r\n\tquint64 m_nextCheckTick = 0;\r\n\r\n\tbool m_hasTransparency = false;\r\n\r\n\tQHash<QString, std::function<BT_RESULT( bool )>> m_behaviors;\r\n\tQHash<QString, std::function<bool( void )>> m_taskFunctions;\r\n\r\n\tQList<AggroEntry> m_aggroList;\r\n\r\n\tQString m_btName        = \"\";\r\n\tQScopedPointer<BT_Node> m_behaviorTree;\r\n\r\n\tBT_RESULT conditionIsMale( bool halt );\r\n\tBT_RESULT conditionIsFemale( bool halt );\r\n\tBT_RESULT conditionIsDay( bool halt );\r\n\tBT_RESULT conditionIsNight( bool halt );\r\n\r\n\tBT_RESULT conditionAlarm( bool halt );\r\n\tBT_RESULT conditionIsInSafeRoom( bool halt );\r\n\r\n\tBT_RESULT conditionIsInCombat( bool halt );\r\n\tBT_RESULT conditionIsOnMission( bool halt );\r\n\tBT_RESULT conditionTargetAdjacent( bool halt );\r\n\tBT_RESULT conditionTargetPositionValid( bool halt );\r\n\r\n\tBT_RESULT actionRandomMove( bool halt );\r\n\tBT_RESULT actionGetExitPosition( bool halt );\r\n\tBT_RESULT actionGetSafeRoomPosition( bool halt );\r\n\tBT_RESULT actionLeaveMap( bool halt );\r\n\tBT_RESULT actionEnterMap( bool halt );\r\n\r\n\tQList<unsigned int> m_claimedItems;\r\n\tQList<unsigned int> m_carriedItems;\r\n\tQList<unsigned int> m_inventoryItems;\r\n\r\n\tvirtual void die();\r\n\r\n\tvoid dropInventory();\r\n\tvoid dropEquipment();\r\n\r\n\tvoid addClaimedItem( unsigned int item, unsigned int job );\r\n\tvoid unclaimAll();\r\n\tvoid destroyClaimedItems();\r\n\r\n\tCreature* resolveTarget( unsigned int creatureId );\r\n};\r\n\r\nstruct CreatureCompare\r\n{\r\n\tbool operator()( const Creature* a, const Creature* b )\r\n\t{\r\n\t\treturn ( *a < *b );\r\n\t}\r\n};"
  },
  {
    "path": "src/game/creatureEquipment.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creature.h\"\r\n\r\nQVariantMap EquipmentItem::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Item\", item );\r\n\tout.insert( \"Material\", material );\r\n\tout.insert( \"ItemID\", itemID );\r\n\tout.insert( \"MaterialID\", materialID );\r\n\tout.insert( \"AllMats\", allMats );\r\n\treturn out;\r\n}\r\n\r\nEquipmentItem::EquipmentItem( const QVariantMap& in )\r\n{\r\n\titem       = in.value( \"Item\" ).toString();\r\n\tmaterial   = in.value( \"Material\" ).toString();\r\n\titemID     = in.value( \"ItemID\" ).toUInt();\r\n\tmaterialID = in.value( \"MaterialID\" ).toUInt();\r\n\tallMats\t   = in.value( \"AllMats\" ).toStringList();\r\n}\r\n\r\nQList<unsigned int> Equipment::wornItems() const\r\n{\r\n\tQList<unsigned int> items;\r\n\tEquipmentItem const *const equipmentSlots[] = {\r\n\t\t&head,\r\n\t\t&chest,\r\n\t\t&arm,\r\n\t\t&hand,\r\n\t\t&leg,\r\n\t\t&foot,\r\n\t\t&leftHandHeld,\r\n\t\t&rightHandHeld,\r\n\t\t&back,\r\n\t};\r\n\tfor ( const auto& slot : equipmentSlots )\r\n\t{\r\n\t\tif (slot->itemID)\r\n\t\t{\r\n\t\t\titems.append( slot->itemID );\r\n\t\t}\r\n\t}\r\n\treturn items;\r\n}\r\n\r\nQVariantMap Equipment::serialize()\r\n{\r\n\tQVariantMap vEqui;\r\n\r\n\tvEqui.insert( \"Hair\", hair );\r\n\tvEqui.insert( \"FacialHair\", facialHair );\r\n\tvEqui.insert( \"HairColor\", hairColor );\r\n\tvEqui.insert( \"Shirt\", shirt );\r\n\tvEqui.insert( \"ShirtColor\", shirtColor );\r\n\r\n\tvEqui.insert( \"UniformID\", uniformID );\r\n\tvEqui.insert( \"RoomID\", roomID );\r\n\r\n\tQVariantMap items;\r\n\titems.insert( \"HeadArmor\", head.serialize() );\r\n\titems.insert( \"ChestArmor\", chest.serialize() );\r\n\titems.insert( \"ArmArmor\", arm.serialize() );\r\n\titems.insert( \"HandArmor\", hand.serialize() );\r\n\titems.insert( \"LegArmor\", leg.serialize() );\r\n\titems.insert( \"FootArmor\", foot.serialize() );\r\n\titems.insert( \"LeftHandHeld\", leftHandHeld.serialize() );\r\n\titems.insert( \"RightHandHeld\", rightHandHeld.serialize() );\r\n\titems.insert( \"Back\", back.serialize() );\r\n\tvEqui.insert( \"Items\", items );\r\n\r\n\treturn vEqui;\r\n}\r\n\r\nEquipment::Equipment( const QVariantMap& in )\r\n{\r\n\thair       = in.value( \"Hair\" ).toString();\r\n\tfacialHair = in.value( \"FacialHair\" ).toString();\r\n\thairColor  = in.value( \"HairColor\" ).toInt();\r\n\tshirt      = in.value( \"Shirt\" ).toString();\r\n\tshirtColor = in.value( \"ShirtColor\" ).toInt();\r\n\r\n\tuniformID = in.value( \"UniformID\" ).toUInt();\r\n\troomID    = in.value( \"RoomID\" ).toUInt();\r\n\r\n\tauto vmItems  = in.value( \"Items\" ).toMap();\r\n\thead          = EquipmentItem( vmItems.value( \"HeadArmor\" ).toMap() );\r\n\tchest         = EquipmentItem( vmItems.value( \"ChestArmor\" ).toMap() );\r\n\tarm           = EquipmentItem( vmItems.value( \"ArmArmor\" ).toMap() );\r\n\thand          = EquipmentItem( vmItems.value( \"HandArmor\" ).toMap() );\r\n\tleg           = EquipmentItem( vmItems.value( \"LegArmor\" ).toMap() );\r\n\tfoot          = EquipmentItem( vmItems.value( \"FootArmor\" ).toMap() );\r\n\tleftHandHeld  = EquipmentItem( vmItems.value( \"LeftHandHeld\" ).toMap() );\r\n\trightHandHeld = EquipmentItem( vmItems.value( \"RightHandHeld\" ).toMap() );\r\n\tback          = EquipmentItem( vmItems.value( \"Back\" ).toMap() );\r\n}\r\n\r\nvoid Equipment::clearAllItems()\r\n{\r\n\thead          = EquipmentItem();\r\n\tchest         = EquipmentItem();\r\n\tarm           = EquipmentItem();\r\n\thand          = EquipmentItem();\r\n\tleg           = EquipmentItem();\r\n\tfoot          = EquipmentItem();\r\n\tleftHandHeld  = EquipmentItem();\r\n\trightHandHeld = EquipmentItem();\r\n\tback          = EquipmentItem();\r\n}\r\n\r\nfloat Equipment::getDamageReduction( CreaturePart part )\r\n{\r\n\tunsigned int itemID = 0;\r\n\tQString itemSID;\r\n\tfloat reduction = 0.0;\r\n\tswitch ( part )\r\n\t{\r\n\t\tcase CP_HEAD:\r\n\t\t\titemID  = head.itemID;\r\n\t\t\titemSID = head.item;\r\n\t\t\tbreak;\r\n\t\tcase CP_TORSO:\r\n\t\t\titemID  = chest.itemID;\r\n\t\t\titemSID = chest.item;\r\n\t\t\tbreak;\r\n\t\tcase CP_LEFT_ARM:\r\n\t\tcase CP_RIGHT_ARM:\r\n\t\t\titemID  = arm.itemID;\r\n\t\t\titemSID = arm.item;\r\n\t\t\tbreak;\r\n\t\tcase CP_LEFT_HAND:\r\n\t\tcase CP_RIGHT_HAND:\r\n\t\t\titemID  = hand.itemID;\r\n\t\t\titemSID = hand.item;\r\n\t\t\tbreak;\r\n\t\tcase CP_LEFT_LEG:\r\n\t\tcase CP_RIGHT_LEG:\r\n\t\t\titemID  = leg.itemID;\r\n\t\t\titemSID = leg.item;\r\n\t\t\tbreak;\r\n\t\tcase CP_LEFT_FOOT:\r\n\t\tcase CP_RIGHT_FOOT:\r\n\t\t\titemID  = foot.itemID;\r\n\t\t\titemSID = foot.item;\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tif ( itemID )\r\n\t{ // TODO put these values on a dtabase table\r\n\t\tif ( itemSID.startsWith( \"Leather\" ) )\r\n\t\t{\r\n\t\t\treduction = 2.0;\r\n\t\t}\r\n\t\telse if ( itemSID.startsWith( \"Bone\" ) )\r\n\t\t{\r\n\t\t\treduction = 3.0;\r\n\t\t}\r\n\t\telse if ( itemSID.startsWith( \"Chain\" ) )\r\n\t\t{\r\n\t\t\treduction = 4.0;\r\n\t\t}\r\n\t\telse if ( itemSID.startsWith( \"Plate\" ) )\r\n\t\t{\r\n\t\t\treduction = 6.0;\r\n\t\t}\r\n\t\telse if ( itemSID.startsWith( \"Heavy\" ) )\r\n\t\t{\r\n\t\t\treduction = 8.0;\r\n\t\t}\r\n\t}\r\n\r\n\treturn reduction;\r\n}\r\n\r\nEquipmentItem& Equipment::getSlot( CreaturePart part )\r\n{\r\n\tswitch ( part )\r\n\t{\r\n\t\tcase CP_ARMOR_HEAD:\r\n\t\t\treturn head;\r\n\t\tcase CP_ARMOR_TORSO:\r\n\t\t\treturn chest;\r\n\t\tcase CP_ARMOR_ARM:\r\n\t\t\treturn arm;\r\n\t\tcase CP_ARMOR_HAND:\r\n\t\t\treturn hand;\r\n\t\tcase CP_ARMOR_LEG:\r\n\t\t\treturn leg;\r\n\t\tcase CP_ARMOR_FOOT:\r\n\t\t\treturn foot;\r\n\t\tcase CP_LEFT_HAND_HELD:\r\n\t\t\treturn leftHandHeld;\r\n\t\tcase CP_RIGHT_HAND_HELD:\r\n\t\t\treturn rightHandHeld;\r\n\t\tcase CP_BACK:\r\n\t\t\treturn back;\r\n\t\tdefault:\r\n\t\t\tqWarning() << \"Invalid equipment slot!\";\r\n\t\t\tabort();\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/game/creaturefactory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creaturefactory.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n\r\nCreatureFactory::CreatureFactory( Game* game ) :\r\n\tg( game )\r\n{\r\n}\r\nCreatureFactory::~CreatureFactory()\r\n{\r\n}\r\n\r\nAnimal* CreatureFactory::createRandomAnimal( QStringList allowedAnimals )\r\n{\r\n\tint dimx = Global::dimX;\r\n\tint dimy = Global::dimY;\r\n\tint dimZ = Global::dimZ;\r\n\r\n\tint numTypes = allowedAnimals.size();\r\n\r\n\tint randomType = rand() % ( numTypes );\r\n\tQString type   = allowedAnimals[randomType];\r\n\r\n\tint x = qMax( 2, ( rand() % dimx ) - 2 );\r\n\tint y = qMax( 2, ( rand() % dimy ) - 2 );\r\n\r\n\tPosition pos( x, y, dimZ - 2 );\r\n\tg->w()->getFloorLevelBelow( pos, false );\r\n\r\n\tAnimal* animal = new Animal( type, pos, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE, true, g );\r\n\r\n\tanimal->init();\r\n\treturn animal;\r\n}\r\n\r\nAnimal* CreatureFactory::createAnimal( QString type, Position pos, Gender gender, bool adult, bool tame )\r\n{\r\n\tAnimal* animal = new Animal( type, pos, gender, adult, g );\r\n\tanimal->init();\r\n\tanimal->setTame( tame );\r\n\treturn animal;\r\n}\r\n\r\nAnimal* CreatureFactory::createAnimal( QVariantMap values )\r\n{\r\n\tAnimal* animal = new Animal( values, g );\r\n\tanimal->init();\r\n\treturn animal;\r\n}\r\n\r\nMonster* CreatureFactory::createRandomMonster( QStringList allowedMonsters )\r\n{\r\n\t/*\r\n\tint dimx = Global::dimX\r\n\tint dimy = Global::dimY;\r\n\tint dimZ = Global::dimZ;\r\n\r\n\tTable& ta = Database::getInstance().getTable( \"Monsters\" );\r\n\r\n\tint numTypes = allowedMonsters.size();\r\n\r\n\tint randomType = rand() % ( numTypes );\r\n\tQString type = allowedMonsters[randomType];\r\n\r\n\tint x = qMax( 2, ( rand() % dimx ) - 2 );\r\n\tint y = qMax( 2, ( rand() % dimy ) - 2 );\r\n\r\n\tPosition pos( x, y, dimZ - 2 );\r\n\tm_world->getFloorLevelBelow( pos, false );\r\n\r\n\tMonster* monster = new Monster( type, 1, pos, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE );\r\n\t\r\n\tmonster->init();\r\n\treturn monster;\r\n\t*/\r\n\treturn nullptr;\r\n}\r\n\r\nMonster* CreatureFactory::createMonster( QString type, int level, Position pos, Gender gender )\r\n{\r\n\tMonster* monster = new Monster( type, level, pos, gender, g );\r\n\r\n\tmonster->init();\r\n\r\n\tauto attribs = DB::selectRows( \"Attributes\" );\r\n\r\n\tfor ( auto row : attribs )\r\n\t{\r\n\t\tQString attributeID = row.value( \"ID\" ).toString();\r\n\r\n\t\tmonster->addAttribute( attributeID, rand() % 10 + 1 );\r\n\t}\r\n\r\n\tauto skills = DB::selectRows( \"Skills\" );\r\n\r\n\tfor ( auto skill : skills )\r\n\t{\r\n\t\tQString skillID = skill.value( \"ID\" ).toString();\r\n\r\n\t\tauto group = skill.value( \"SkillGroup\" ).toString();\r\n\t\tif ( group == \"Combat\" || group == \"Defense\" )\r\n\t\t{\r\n\t\t\tmonster->addSkill( skillID, rand() % 500 );\r\n\t\t\t//monster->setSkillActive( skillID, true );\r\n\t\t}\r\n\t}\r\n\r\n\treturn monster;\r\n}\r\n\r\nMonster* CreatureFactory::createMonster( QVariantMap values )\r\n{\r\n\tMonster* monster = new Monster( values, g );\r\n\tmonster->init();\r\n\treturn monster;\r\n}"
  },
  {
    "path": "src/game/creaturefactory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"animal.h\"\r\n#include \"monster.h\"\r\n\r\n#include <QString>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\n\r\nclass CreatureFactory\r\n{\r\n\tQ_DISABLE_COPY_MOVE( CreatureFactory )\r\npublic:\r\n\tCreatureFactory( Game* game );\r\n\t~CreatureFactory();\r\n\r\n\tAnimal* createRandomAnimal( QStringList allowedAnimals );\r\n\tAnimal* createAnimal( QString type, Position pos, Gender gender, bool adult, bool tame );\r\n\tAnimal* createAnimal( QVariantMap values );\r\n\r\n\tMonster* createRandomMonster( QStringList allowedMonsters );\r\n\tMonster* createMonster( QString type, int level, Position pos, Gender gender );\r\n\tMonster* createMonster( QVariantMap values );\r\n\r\nprivate:\r\n    QPointer<Game> g;\r\n\r\n    int m_numWoodLice = 0;\r\n};\r\n"
  },
  {
    "path": "src/game/creaturemanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creaturemanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/regionmap.h\"\r\n#include \"../game/world.h\"\r\n#include \"../game/creaturefactory.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/newgamesettings.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n\r\nCreatureManager::CreatureManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nCreatureManager::~CreatureManager()\r\n{\r\n\tfor ( const auto& c : m_creatures )\r\n\t{\r\n\t\tdelete c;\r\n\t}\r\n}\r\n\r\nvoid CreatureManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\t//if ( m_startIndex >= m_creatures.size() )\r\n\t{\r\n\t\tm_startIndex = 0;\r\n\t}\r\n\tint oldStartIndex = m_startIndex;\r\n\tQList<unsigned int> toDestroy;\r\n\tfor ( int i = m_startIndex; i < m_creatures.size(); ++i )\r\n\t{\r\n\t\tCreature* creature = m_creatures[i];\r\n\r\n\t\tCreatureTickResult ctr = creature->onTick( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\r\n\t\tswitch ( ctr )\r\n\t\t{\r\n\t\t\tcase CreatureTickResult::TODESTROY:\r\n\t\t\t\ttoDestroy.append( creature->id() );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::DEAD:\r\n\t\t\t\tif( creature->type() == CreatureType::ANIMAL )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto a = dynamic_cast<Animal*>( creature );\r\n\t\t\t\t\tg->inv()->createItem( a->getPos(), \"AnimalCorpse\", { a->species() } );\r\n\t\t\t\t}\r\n\t\t\t\ttoDestroy.append( creature->id() );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tm_startIndex = i + 1;\r\n\t\t//if( jobChanged ) emit signalGnomeActivity( g.id(), g.getActivity() );\r\n\t\t//if ( timer.elapsed() > 2 )\r\n\t\t//\tbreak;\r\n\t}\r\n\r\n\tif ( toDestroy.size() )\r\n\t{\r\n\t\tfor ( auto aid : toDestroy )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < m_creatures.size(); ++i )\r\n\t\t\t{\r\n\t\t\t\tif ( aid == m_creatures[i]->id() )\r\n\t\t\t\t{\r\n\t\t\t\t\tremoveCreature( aid );\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\tif ( hourChanged )\r\n\t{\r\n\t\t\r\n\t}\r\n}\r\n\r\nQList<Creature*> CreatureManager::creaturesAtPosition( Position& pos )\r\n{\r\n\tQList<Creature*> out;\r\n\tfor ( int i = 0; i < m_creatures.size(); ++i )\r\n\t{\r\n\t\tif ( m_creatures[i]->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( m_creatures[i] );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<Animal*> CreatureManager::animalsAtPosition( Position& pos )\r\n{\r\n\tQList<Animal*> out;\r\n\tfor ( int i = 0; i < m_creatures.size(); ++i )\r\n\t{\r\n\t\tauto c = m_creatures[i];\r\n\r\n\t\tif ( c->isAnimal() && c->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( dynamic_cast<Animal*>( c ) );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\t\r\nQList<Monster*> CreatureManager::monstersAtPosition( Position& pos )\r\n{\r\n\tQList<Monster*> out;\r\n\tfor ( int i = 0; i < m_creatures.size(); ++i )\r\n\t{\r\n\t\tauto c = m_creatures[i];\r\n\r\n\t\tif ( c->isMonster() && c->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( dynamic_cast<Monster*>( c ) );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nint CreatureManager::countWildAnimals()\r\n{\r\n\treturn m_creatures.size();\r\n}\r\n\r\nunsigned int CreatureManager::addCreature( CreatureType ct, QString type, Position pos, Gender gender, bool adult, bool tame, int level )\r\n{\r\n\tCreature* creature = nullptr;\r\n\tCreatureFactory cf( g );\r\n\tswitch ( ct )\r\n\t{\r\n\t\tcase CreatureType::ANIMAL:\r\n\t\t\tcreature = cf.createAnimal( type, pos, gender, adult, tame );\r\n\t\t\tbreak;\r\n\t\tcase CreatureType::MONSTER:\r\n\t\t\tcreature = cf.createMonster( type, level, pos, gender );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif( creature )\r\n\t{\r\n\t\tm_creatures.append( creature );\r\n\t\tunsigned int id = m_creatures.last()->id();\r\n\t\tm_creaturesByID.insert( id, m_creatures.last() );\r\n\r\n\t\tint count = m_countPerType.value( type );\r\n\t\r\n\t\t++count;\r\n\t\tm_countPerType.insert( type, count );\r\n\r\n\t\tauto& list = m_creaturesPerType[type];\r\n\t\tlist.append( id );\r\n\r\n\t\tm_dirty = true;\r\n\r\n\t\tif( creature->hasTransparency() )\r\n\t\t{\r\n\t\t\tg->m_world->setTileFlag( creature->getPos(), TileFlag::TF_TRANSPARENT );\r\n\t\t}\r\n\r\n\t\treturn id;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int CreatureManager::addCreature( CreatureType ct, QVariantMap vals )\r\n{\r\n\tCreature* creature = nullptr;\r\n\tCreatureFactory cf( g );\r\n\tswitch ( ct )\r\n\t{\r\n\t\tcase CreatureType::ANIMAL:\r\n\t\t\tcreature = cf.createAnimal( vals );\r\n\t\t\tbreak;\r\n\t\tcase CreatureType::MONSTER:\r\n\t\t\tcreature = cf.createMonster( vals );\r\n\t\t\tbreak;\r\n\t}\r\n\tif( creature )\r\n\t{\r\n\t\tm_creatures.append( creature );\r\n\t\tunsigned int id = m_creatures.last()->id();\r\n\t\tm_creaturesByID.insert( id, m_creatures.last() );\r\n\r\n\t\tQString type = creature->species();\r\n\t\tint count    = m_countPerType.value( type );\r\n\t\t++count;\r\n\t\tm_countPerType.insert( type, count );\r\n\r\n\t\tauto& list = m_creaturesPerType[type];\r\n\t\tlist.append( id );\r\n\r\n\t\tm_dirty = true;\r\n\r\n\t\tif( creature->hasTransparency() )\r\n\t\t{\r\n\t\t\tg->m_world->setTileFlag( creature->getPos(), TileFlag::TF_TRANSPARENT );\r\n\t\t}\r\n\r\n\t\treturn id;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nCreature* CreatureManager::creature( unsigned int id )\r\n{\r\n\tif ( m_creaturesByID.contains( id ) )\r\n\t{\r\n\t\treturn m_creaturesByID[id];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nAnimal* CreatureManager::animal( unsigned int id )\r\n{\r\n\tif ( m_creaturesByID.contains( id ) )\r\n\t{\r\n\t\tauto c = m_creaturesByID[id];\r\n\t\tif( c->isAnimal() )\r\n\t\t{\r\n\t\t\treturn dynamic_cast<Animal*>( c );\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\t\r\nMonster* CreatureManager::monster( unsigned int id )\r\n{\r\n\tif ( m_creaturesByID.contains( id ) )\r\n\t{\r\n\t\tauto c = m_creaturesByID[id];\r\n\t\tif( c->isMonster() )\r\n\t\t{\r\n\t\t\treturn dynamic_cast<Monster*>( c );\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nint CreatureManager::count()\r\n{\r\n\treturn m_creatures.size();\r\n}\r\n\r\nint CreatureManager::count( QString type )\r\n{\r\n\treturn m_countPerType.value( type );\r\n}\r\n\r\nvoid CreatureManager::removeCreature( unsigned int id )\r\n{\r\n\tif( m_creaturesByID.contains( id ) )\r\n\t{\r\n\t\tauto creature = m_creaturesByID[id];\r\n\r\n\t\tswitch( creature->type() )\r\n\t\t{\r\n\t\t\tcase CreatureType::ANIMAL:\r\n\t\t\t{\r\n\t\t\t\tAnimal* a = dynamic_cast<Animal*>( creature );\r\n\t\t\t\tif ( a )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( a->pastureID() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tqDebug() << \"remove animal from pasture\";\r\n\t\t\t\t\t\tauto pasture = g->m_farmingManager->getPasture( a->pastureID() );\r\n\t\t\t\t\t\tif ( pasture )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpasture->removeAnimal( a->id() );\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\tbreak;\r\n\t\t}\r\n\r\n\t\tauto& perTypeList = m_creaturesPerType[creature->species()];\r\n\t\tperTypeList.removeAll( id );\r\n\r\n\t\tm_creaturesByID.remove( id );\r\n\t\tm_creatures.removeAll( creature );\r\n\r\n\t\tint count = m_countPerType.value( creature->species() );\r\n\t\t--count;\r\n\t\tm_countPerType.insert( creature->species(), count );\r\n\r\n\t\tdelete creature;\r\n\r\n\t\tm_dirty = true;\r\n\r\n\t\temit signalCreatureRemove( id );\r\n\t}\r\n}\r\n\r\nAnimal* CreatureManager::getClosestAnimal( Position pos, QString type )\r\n{\r\n\tauto distanceQueue = animalsByDistance( pos, type );\r\n\r\n\tif ( !distanceQueue.empty() )\r\n\t{\r\n\t\treturn distanceQueue.get();\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nPriorityQueue<Animal*, int> CreatureManager::animalsByDistance( Position pos, QString type )\r\n{\r\n\tauto distanceQueue = PriorityQueue<Animal*, int>();\r\n\tfor ( auto id : m_creaturesPerType[type] )\r\n\t{\r\n\t\tCreature* creature = m_creaturesByID[id];\r\n\t\tif( creature->isAnimal() )\r\n\t\t{\r\n\t\t\tAnimal* a = dynamic_cast<Animal*>( creature );\r\n\t\t\tif ( a && !a->inJob() && !a->isDead() && !a->toDestroy() )\r\n\t\t\t{\r\n\t\t\t\tPosition targetPos = a->getPos();\r\n\t\t\t\tif ( g->m_pf->checkConnectedRegions( pos, targetPos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tdistanceQueue.put( a, pos.distSquare( targetPos ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn distanceQueue;\r\n}\r\n\r\nQList<unsigned int> CreatureManager::animalsByType( QString type )\r\n{\r\n\treturn m_creaturesPerType.value( type );\r\n}\r\n\r\nvoid CreatureManager::forceMoveAnimals( const Position& from, const Position& to )\r\n{\r\n\tfor ( auto& a : m_creatures )\r\n\t{\r\n\t\t// check gnome position\r\n\t\tif ( a->getPos().toInt() == from.toInt() )\r\n\t\t{\r\n\t\t\t//qDebug() << \"force move gnome from \" << from.toString() << \" to \" << to.toString();\r\n\t\t\t// move gnome\r\n\t\t\ta->forceMove( to );\r\n\t\t\t// abort job if he has one\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQList<QString> CreatureManager::types()\r\n{\r\n\treturn m_countPerType.keys();\r\n}\r\n\r\n\t\r\nQList<Animal*>& CreatureManager::animals()\r\n{\r\n\tif( m_dirty )\r\n\t{\r\n\t\tupdateLists();\r\n\t}\r\n\r\n\treturn m_animals;\r\n}\r\n\r\nQList<Monster*>& CreatureManager::monsters()\r\n{\r\n\tif( m_dirty )\r\n\t{\r\n\t\tupdateLists();\r\n\t}\r\n\r\n\treturn m_monsters;\r\n}\r\n\r\nvoid CreatureManager::updateLists()\r\n{\r\n\tm_animals.clear();\r\n\tm_monsters.clear();\r\n\r\n\tfor( const auto& c : m_creatures )\r\n\t{\r\n\t\tif( c->isAnimal() )\r\n\t\t{\r\n\t\t\tm_animals.append( dynamic_cast<Animal*>( c ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_monsters.append( dynamic_cast<Monster*>( c ) );\r\n\t\t}\r\n\t}\r\n\tm_dirty = false;\r\n}\r\n\r\nbool CreatureManager::hasPathTo( const Position& pos, unsigned int creatureID )\r\n{\r\n\tif( m_creaturesByID.contains( creatureID ) )\r\n\t{\r\n\t\tauto creature = m_creaturesByID[creatureID];\r\n\t\tif( creature )\r\n\t\t{\r\n\t\t\treturn g->m_world->regionMap().checkConnectedRegions( pos, creature->getPos() );\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool CreatureManager::hasLineOfSightTo( const Position& pos, unsigned int creatureID )\r\n{\r\n\tif ( m_creaturesByID.contains( creatureID ) )\r\n\t{\r\n\t\tauto creature = m_creaturesByID[creatureID];\r\n\t\tif ( creature )\r\n\t\t{\r\n\t\t\treturn g->m_world->isLineOfSight( pos, creature->getPos() );\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n"
  },
  {
    "path": "src/game/creaturemanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/animal.h\"\r\n#include \"../game/monster.h\"\r\n\r\nclass Game;\r\n\r\nclass CreatureManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( CreatureManager )\r\npublic:\r\n\tCreatureManager( Game* parent );\r\n\t~CreatureManager();\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tint countWildAnimals();\r\n\r\n\tunsigned int addCreature( CreatureType ct, QString type, Position pos, Gender gender, bool adult, bool tame, int level = 1 );\r\n\tunsigned int addCreature( CreatureType ct, QVariantMap vals );\r\n\r\n\tvoid removeCreature( unsigned int id );\r\n\r\n\tQList<Creature*> creaturesAtPosition( Position& pos );\r\n\tQList<Animal*> animalsAtPosition( Position& pos );\r\n\tQList<Monster*> monstersAtPosition( Position& pos );\r\n\r\n\tCreature* creature( unsigned int id );\r\n\tAnimal* animal( unsigned int id );\r\n\tMonster* monster( unsigned int id );\r\n\r\n\tint count( QString type );\r\n\r\n\tint count();\r\n\r\n\tAnimal* getClosestAnimal( Position pos, QString type );\r\n\r\n\tQList<Creature*>& creatures()\r\n\t{\r\n\t\treturn m_creatures;\r\n\t}\r\n\r\n\tQList<Animal*>& animals();\r\n\tQList<Monster*>& monsters();\r\n\t\r\n\tPriorityQueue<Animal*, int> animalsByDistance( Position pos, QString type );\r\n\t\r\n\tvoid forceMoveAnimals( const Position& from, const Position& to );\r\n\r\n\tQList<QString> types();\r\n\tQList<unsigned int> animalsByType( QString type );\r\n\r\n\tbool hasPathTo( const Position& pos, unsigned int creatureID );\r\n\tbool hasLineOfSightTo( const Position& pos, unsigned int creatureID );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\tQList<Creature*> m_creatures;\r\n\tQList<Animal*> m_animals;\r\n\tQList<Monster*> m_monsters;\r\n\r\n\tQHash<unsigned int, Creature*> m_creaturesByID;\r\n\r\n\tQMap<QString, unsigned int> m_countPerType;\r\n\tQMap<QString, QList<unsigned int>> m_creaturesPerType;\r\n\r\n\tint m_startIndex = 0;\r\n\r\n\tbool m_dirty = true;\r\n\r\n\tvoid updateLists();\r\n\r\nsignals:\r\n\tvoid signalCreatureDeath( unsigned int id );\r\n\tvoid signalCreatureRemove( unsigned int id );\r\n\r\n\tvoid signalAddMonster( unsigned int monsterID );\r\n\tvoid signalRemoveMonster( unsigned int monsterID );\r\n};\r\n"
  },
  {
    "path": "src/game/eventmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"eventmanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/pathfinder.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/gnome.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/workshop.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include \"../gui/eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nQVariantMap Event::serialize()\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"ID\", id );\r\n\tout.insert( \"Tick\", tick );\r\n\tout.insert( \"Type\", (int)type );\r\n\tout.insert( \"Data\", data );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Event::deserialize( QVariantMap in )\r\n{\r\n\tid   = in.value( \"ID\" ).toUInt();\r\n\ttick = in.value( \"Tick\" ).value<quint64>();\r\n\ttype = (EventType)in.value( \"Type\" ).toInt();\r\n\tdata = in.value( \"Data\" );\r\n}\r\n\r\nQVariantMap Mission::serialize()\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"ID\", id );\r\n\tout.insert( \"Type\", (int)type );\r\n\tout.insert( \"Action\", (int)action );\r\n\tout.insert( \"Step\", (int)step );\r\n\tout.insert( \"Target\", target );\r\n\tout.insert( \"Distance\", distance );\r\n\tout.insert( \"Gnomes\", Global::util->uintList2Variant( gnomes ) );\r\n\tout.insert( \"StartTick\", startTick );\r\n\tout.insert( \"NextCheckTick\", nextCheckTick );\r\n\r\n\tout.insert( \"LeavePos\", leavePos.toString() );\r\n\tout.insert( \"Result\", result );\r\n\r\n\treturn out;\r\n}\r\n\r\nMission::Mission( QVariantMap in )\r\n{\r\n\tid            = in.value( \"ID\" ).toUInt();\r\n\ttype          = (MissionType)in.value( \"Type\" ).toInt();\r\n\taction        = (MissionAction)in.value( \"Action\" ).toInt();\r\n\tstep          = (MissionStep)in.value( \"Step\" ).toInt();\r\n\ttarget        = in.value( \"Target\" ).toUInt();\r\n\tdistance      = in.value( \"Distance\" ).toUInt();\r\n\tgnomes        = Global::util->variantList2UInt( in.value( \"Gnomes\" ).toList() );\r\n\tstartTick     = in.value( \"StartTick\" ).value<quint64>();\r\n\tnextCheckTick = in.value( \"NextCheckTick\" ).value<quint64>();\r\n\tleavePos      = Position( in.value( \"LeavePos\" ) );\r\n\tresult        = in.value( \"Result\" ).toMap();\r\n}\r\n\r\nEventManager::EventManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tm_string2type.insert( \"EventTrader\", (int)EventType::TRADER );\r\n\tm_string2type.insert( \"EventMigration\", (int)EventType::MIGRATION );\r\n\tm_string2type.insert( \"EventInvasion\", (int)EventType::INVASION );\r\n\r\n\tm_reqMap.insert( \"None\", (int)EventRequire::NOREQUIRE );\r\n\tm_reqMap.insert( \"Query\", (int)EventRequire::QUERY );\r\n\tm_reqMap.insert( \"FreeMarketStall\", (int)EventRequire::FREEMARKETSTALL );\r\n}\r\n\r\nEventManager::~EventManager()\r\n{\r\n}\r\n\r\nQVariantMap EventManager::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tQVariantList vel; // variant event list\r\n\tfor ( auto entry : m_eventList )\r\n\t{\r\n\t\tvel.append( entry.serialize() );\r\n\t}\r\n\tout.insert( \"EventList\", vel );\r\n\r\n\tQVariantList ml;\r\n\tfor ( auto mission : m_missions )\r\n\t{\r\n\t\tml.append( mission.serialize() );\r\n\t}\r\n\tout.insert( \"Missions\", ml );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid EventManager::deserialize( QVariantMap in )\r\n{\r\n\tm_eventList.clear();\r\n\tm_missions.clear();\r\n\tauto vel = in.value( \"EventList\" ).toList();\r\n\tfor ( auto ve : vel )\r\n\t{\r\n\t\tEvent event;\r\n\t\tevent.deserialize( ve.toMap() );\r\n\t\tm_eventList.append( event );\r\n\t}\r\n\r\n\tauto vml = in.value( \"Missions\" ).toList();\r\n\tfor ( auto vm : vml )\r\n\t{\r\n\t\tMission m( vm.toMap() );\r\n\t\tm_missions.append( m );\r\n\t}\r\n}\r\n\r\nvoid EventManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tif ( hourChanged )\r\n\t{\r\n\t\tfor ( auto mission : m_missions )\r\n\t\t{\r\n\t\t\temit signalUpdateMission( mission );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( seasonChanged )\r\n\t{\r\n\t\tauto ev = createEvent( \"EventMigration\" );\r\n\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\tev.tick = GameState::tick + Global::util->ticksPerDayRandomized( 50 );\r\n\t\tm_eventList.append( ev );\r\n\t}\r\n\r\n\tfor ( auto it = m_eventList.begin(); it != m_eventList.end(); )\r\n\t{\r\n\t\tauto& event = *it;\r\n\t\tif ( GameState::tick >= event.tick && checkRequirements( event ) )\r\n\t\t{\r\n\t\t\tauto em     = event.data.toMap();\r\n\t\t\tQString msg = em.value( \"OnSuccess\" ).toMap().value( \"Message\" ).toString();\r\n\t\t\tif ( !msg.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tint amount = em.value( \"Amount\" ).toInt();\r\n\t\t\t\tmsg.replace( \"$Num\", QString::number( amount ) );\r\n\t\t\t\tQString title = em.value( \"OnSuccess\" ).toMap().value( \"Title\" ).toString();\r\n\t\t\t\tGlobal::eventConnector->onEvent( 0, title, msg, true, false );\r\n\t\t\t}\r\n\t\t\texecuteEvent( event );\r\n\t\t\tit = m_eventList.erase( it );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t++it;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nEvent EventManager::createEvent( QString eventID )\r\n{\r\n\tEvent ev;\r\n\tev.id   = GameState::createID();\r\n\tev.tick = GameState::tick;\r\n\tev.type = (EventType)m_string2type.value( eventID );\r\n\r\n\tQVariantMap em = DB::selectRow( \"Events\", eventID );\r\n\r\n\tauto im = DB::selectRow( \"Events_Init\", eventID );\r\n\tem.insert( \"Init\", im );\r\n\r\n\tauto sm = DB::selectRow( \"Events_OnSuccess\", eventID );\r\n\tauto fm = DB::selectRow( \"Events_OnFailure\", eventID );\r\n\tem.insert( \"OnSuccess\", sm );\r\n\tem.insert( \"OnFailure\", fm );\r\n\r\n\tint min = im.value( \"Min\" ).toInt();\r\n\tint max = im.value( \"Max\" ).toInt();\r\n\tint num = min;\r\n\tif ( min != max )\r\n\t{\r\n\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\tnum = qMax( min, rand() % max + 1 );\r\n\t}\r\n\tem.insert( \"Amount\", num );\r\n\r\n\tev.data = em;\r\n\r\n\treturn ev;\r\n}\r\n\r\nbool EventManager::checkRequirements( Event& event )\r\n{\r\n\tauto data = event.data.toMap();\r\n\tint num   = data.value( \"Amount\" ).toInt();\r\n\r\n\tauto im = data.value( \"Init\" ).toMap();\r\n\tswitch ( (EventRequire)m_reqMap.value( im.value( \"Require\" ).toString() ) )\r\n\t{\r\n\t\tcase EventRequire::NOREQUIRE:\r\n\t\t\treturn true;\r\n\t\tcase EventRequire::QUERY:\r\n\t\t{\r\n\t\t\tQString msg = im.value( \"Message\" ).toString();\r\n\r\n\t\t\tif ( !msg.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tmsg.replace( \"$Num\", QString::number( num ) );\r\n\r\n\t\t\t\tGlobal::eventConnector->onEvent( event.id, im.value( \"Title\" ).toString(), msg, im.value( \"Pause\" ).toBool(), true );\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.contains( \"Expires\" ) )\r\n\t\t\t{\r\n\t\t\t\tauto expireMap = data.value( \"Expires\" ).toMap();\r\n\t\t\t\tauto val       = expireMap.value( \"After\" ).toInt();\r\n\t\t\t\tQString unit   = expireMap.value( \"Unit\" ).toString();\r\n\t\t\t\tif ( unit == \"Day\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tdata.insert( \"ExpireTick\", GameState::tick + val * Global::util->ticksPerDay );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( unit == \"Ticks\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tdata.insert( \"ExpireTick\", GameState::tick + val );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tcase EventRequire::FREEMARKETSTALL:\r\n\t\t{\r\n\t\t\tunsigned int marketStall = 0;\r\n\t\t\tfor ( auto ws : g->m_workshopManager->workshops() )\r\n\t\t\t{\r\n\t\t\t\tif ( ws->type() == \"MarketStall\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( ws->assignedGnome() == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmarketStall = ws->id();\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 ( marketStall )\r\n\t\t\t{\r\n\t\t\t\tdata.insert( \"MarketStall\", marketStall );\r\n\t\t\t\tevent.data = data;\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid EventManager::executeEvent( Event& event )\r\n{\r\n\t//qDebug() << \"execute event\";\r\n\tauto data = event.data.toMap();\r\n\t/*\r\n\tfor( auto key : data.keys() )\r\n\t{\r\n\t\tqDebug() << key << data[key];\r\n\t}\r\n\t*/\r\n\tPosition location = getEventLocation( data );\r\n\tint amount        = data.value( \"Amount\" ).toInt();\r\n\r\n\tswitch ( event.type )\r\n\t{\r\n\t\tcase EventType::MIGRATION:\r\n\t\t{\r\n\t\t\tspawnGnome( location, amount );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase EventType::TRADER:\r\n\t\t{\r\n\t\t\tauto marketStall = data.value( \"MarketStall\" ).toUInt();\r\n\t\t\tif ( marketStall )\r\n\t\t\t{\r\n\t\t\t\tspawnTrader( location, marketStall, data );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"Spawn trader failed, marketStall = 0\";\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase EventType::INVASION:\r\n\t\t{\r\n\t\t\tspawnInvasion( location, amount, data );\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\temit signalCenterCamera( location );\r\n}\r\n\r\nvoid EventManager::spawnGnome( Position location, int amount )\r\n{\r\n\tfor ( int i = 0; i < amount; ++i )\r\n\t{\r\n\t\tg->m_gnomeManager->addGnome( location );\r\n\t}\r\n}\r\n\r\nvoid EventManager::spawnInvasion( Position location, int amount, QVariantMap data )\r\n{\r\n\tQString type = data.value( \"Species\" ).toString();\r\n\tfor ( int i = 0; i < amount; ++i )\r\n\t{\r\n\t\tg->m_creatureManager->addCreature( CreatureType::MONSTER, type, location, Gender::MALE, true, false, 1 );\r\n\t}\r\n}\r\n\r\nvoid EventManager::spawnTrader( Position location, unsigned int marketStall, QVariantMap data )\r\n{\r\n\tauto ws = g->m_workshopManager->workshop( marketStall );\r\n\t// spawn trader\"\r\n\tQString type;\r\n\tKingdomEconomy econ = (KingdomEconomy)data.value( \"KingdomEconomy\" ).toInt();\r\n\r\n\tswitch ( econ )\r\n\t{\r\n\t\tcase KingdomEconomy::FARMING:\r\n\t\t\ttype = \"SeedTrader\";\r\n\t\t\tbreak;\r\n\t\tcase KingdomEconomy::ANIMALBREEDING:\r\n\t\t\ttype = \"AnimalTrader\";\r\n\t\t\tbreak;\r\n\t\tcase KingdomEconomy::MINING:\r\n\t\t\ttype = \"OreTrader\";\r\n\t\t\tbreak;\r\n\t\tcase KingdomEconomy::LOGGING:\r\n\t\t\ttype = \"WoodTrader\";\r\n\t\t\tbreak;\r\n\t\tcase KingdomEconomy::TRADING:\r\n\t\tdefault:\r\n\t\t{\r\n\t\t\tauto types = DB::ids( \"Traders\" );\r\n\t\t\tif ( types.size() )\r\n\t\t\t{\r\n\t\t\t\ttype = types[rand() % types.size()];\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tunsigned int id = g->m_gnomeManager->addTrader( location, ws->id(), type );\r\n\tws->assignGnome( id );\r\n}\r\n\r\nvoid EventManager::onAnswer( unsigned int id, bool answer )\r\n{\r\n\tfor ( int i = 0; i < m_eventList.size(); ++i )\r\n\t{\r\n\t\tEvent e = m_eventList[i];\r\n\t\tif ( e.id == id )\r\n\t\t{\r\n\t\t\tif ( answer )\r\n\t\t\t{\r\n\t\t\t\tauto eventMap = e.data.toMap();\r\n\t\t\t\tif ( eventMap.contains( \"ExpireTick\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tquint64 expireTick = eventMap.value( \"ExpireTick\" ).value<quint64>();\r\n\t\t\t\t\tif ( GameState::tick > expireTick )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQString msg   = eventMap.value( \"Expires\" ).toMap().value( \"Message\" ).toString();\r\n\t\t\t\t\t\tQString title = eventMap.value( \"Expires\" ).toMap().value( \"Title\" ).toString();\r\n\t\t\t\t\t\tGlobal::eventConnector->onEvent( 0, title, msg, false, false );\r\n\t\t\t\t\t\tm_eventList.removeAt( i );\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\te.data = eventMap;\r\n\t\t\t\tm_eventList.removeAt( i );\r\n\t\t\t\texecuteEvent( e );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_eventList.removeAt( i );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nPosition EventManager::getEventLocation( QVariantMap& eventMap )\r\n{\r\n\tauto im = eventMap.value( \"Init\" ).toMap();\r\n\r\n\tQString locationString = im.value( \"Location\" ).toString();\r\n\r\n\tPosition location;\r\n\r\n\tif ( locationString == \"RandomBorderTile\")\r\n\t{\r\n\t\tbool found = false;\r\n\t\tlocation = Global::util->borderPos( found );\r\n\t\tif (!found)\r\n\t\t{\r\n\t\t\t//TODO Use a different spawn location if no edge position was valid\r\n\t\t\tlocation = Position();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tlocation = Position(locationString);\r\n\t}\r\n\tif ( !g->w()->isWalkableGnome(location))\r\n\t{\r\n\t\tbool found = false;\r\n\t\tlocation = Global::util->borderPos( found );\r\n\t\tif (!found)\r\n\t\t{\r\n\t\t\t//TODO Use a different spawn location if no edge position was valid\r\n\t\t\tlocation = Position();\r\n\t\t}\r\n\t}\r\n\treturn location;\r\n}\r\n\r\nvoid EventManager::onDebugEvent( EventType type, QVariantMap args )\r\n{\r\n\tQString eventID;\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase EventType::MIGRATION:\r\n\t\t{\r\n\t\t\teventID = \"EventMigration\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase EventType::TRADER:\r\n\t\t{\r\n\t\t\t{\r\n\t\t\t\r\n\t\t\t\tNeighborKingdom k;\r\n\t\t\t\tk.distance = 0;\r\n\t\t\t\tk.economy = KingdomEconomy::ANIMALBREEDING;\r\n\t\t\t\tk.nextTrader = GameState::tick;\r\n\t\t\t\tk.wealth = KingdomWealth::VERYRICH;\r\n\t\t\t\tk.type = KingdomType::GNOME;\r\n\r\n\t\t\t\teventID = \"EventTrader\";\r\n\r\n\t\t\t\taddTraderEvent( k );\r\n\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase EventType::INVASION:\r\n\t\t{\r\n\t\t\teventID = \"EventInvasion\";\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tEvent e = createEvent( eventID );\r\n\tauto em    = e.data.toMap();\r\n\tint amount = args.value( \"Amount\" ).toInt();\r\n\tif ( amount > 0 )\r\n\t{\r\n\t\tem.insert( \"Amount\", amount );\r\n\t}\r\n\tem.insert( \"Species\", args.value( \"Type\" ).toString() );\r\n\te.data        = em;\r\n\tm_eventList.append( e );\r\n}\r\n\r\nQList<Mission>& EventManager::missions()\r\n{\r\n\tfor( auto& mission : m_missions )\r\n\t{\r\n\t\tmission.time = ( GameState::tick - mission.startTick ) / ( Global::util->ticksPerMinute * 60 );\r\n\t}\r\n\r\n\treturn m_missions;\r\n}\r\n\r\nvoid EventManager::addMission( Mission mission )\r\n{\r\n\tm_missions.append( mission );\r\n}\r\n\r\nMission* EventManager::getMission( unsigned int id )\r\n{\r\n\tfor ( auto& mission : m_missions )\r\n\t{\r\n\t\tif ( mission.id == id )\r\n\t\t{\r\n\t\t\tmission.time = ( GameState::tick - mission.startTick ) / ( Global::util->ticksPerMinute * 60 );\r\n\t\t\treturn &mission;\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid EventManager::finishMission( unsigned int id )\r\n{\r\n\tfor ( int i = 0; i < m_missions.size(); ++i )\r\n\t{\r\n\t\tif ( m_missions[i].id == id )\r\n\t\t{\r\n\t\t\tm_missions.removeAt( i );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid EventManager::addTraderEvent( NeighborKingdom kingdom )\r\n{\r\n\tquint64 leaveTick = kingdom.nextTrader;\r\n\tquint64 tick      = leaveTick + kingdom.distance * Global::util->ticksPerMinute * Global::util->minutesPerHour;\r\n\r\n\tauto e = createEvent( \"EventTrader\" );\r\n\te.tick = tick;\r\n\r\n\tauto data = e.data.toMap();\r\n\tdata.insert( \"KingdomType\", (int)kingdom.type );\r\n\tdata.insert( \"KingdomWealth\", (int)kingdom.wealth );\r\n\tdata.insert( \"KingdomEconomy\", (int)kingdom.economy );\r\n\r\n\te.data = data;\r\n\r\n\tm_eventList.append( e );\r\n}\r\n\r\nvoid EventManager::addRaidEvent( NeighborKingdom kingdom )\r\n{\r\n\tif ( GameState::peaceful )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tquint64 leaveTick = GameState::tick;\r\n\tquint64 tick      = leaveTick + kingdom.distance * Global::util->ticksPerMinute * Global::util->minutesPerHour;\r\n\r\n\tauto e = createEvent( \"EventInvasion\" );\r\n\te.tick = tick;\r\n\r\n\tauto data = e.data.toMap();\r\n\tdata.insert( \"KingdomType\", (int)kingdom.type );\r\n\tdata.insert( \"KingdomWealth\", (int)kingdom.wealth );\r\n\tdata.insert( \"KingdomMilitary\", (int)kingdom.military );\r\n\tdata.insert( \"Amount\", GameState::year + 1 ); //TODO amount depending on factors\r\n\tdata.insert( \"Species\", \"Goblin\" );\r\n\te.data = data;\r\n\r\n\tm_eventList.append( e );\r\n}\r\n\r\nvoid EventManager::startMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID )\r\n{\r\n\tMission mission;\r\n\r\n\tmission.id = GameState::createID();\r\n\r\n\tmission.type = type;\r\n\tmission.step = MissionStep::LEAVE_MAP;\r\n\tmission.target = targetKingdom;\r\n\tmission.action = action;\r\n\tmission.distance = g->m_neighborManager->distance( mission.target );\r\n\tmission.gnomes = { gnomeID };\r\n\tmission.startTick = GameState::tick;\r\n\tmission.nextCheckTick = GameState::tick + Global::util->ticksPerDay;\r\n\r\n\taddMission( mission );\r\n\r\n\tg->m_gnomeManager->setInMission( gnomeID, mission.id );\r\n}\r\n"
  },
  {
    "path": "src/game/eventmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/position.h\"\r\n#include \"../base/priorityqueue.h\"\r\n#include \"../game/neighbormanager.h\"\r\n\r\n#include <QMap>\r\n#include <QObject>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\n\r\nenum class EventRequire\r\n{\r\n\tNOREQUIRE,\r\n\tQUERY,\r\n\tFREEMARKETSTALL\r\n};\r\n\r\nenum class EventType\r\n{\r\n\tTRADER,\r\n\tMIGRATION,\r\n\tINVASION,\r\n};\r\n\r\nstruct Event\r\n{\r\n\tunsigned int id = 0;\r\n\tquint64 tick    = 0;\r\n\r\n\tEventType type;\r\n\r\n\tQVariant data;\r\n\r\n\tbool operator==( const Event& other )\r\n\t{\r\n\t\treturn tick == other.tick;\r\n\t}\r\n\tbool operator!=( const Event& other )\r\n\t{\r\n\t\treturn tick != other.tick;\r\n\t};\r\n\tbool operator<( const Event& other )\r\n\t{\r\n\t\treturn tick < other.tick;\r\n\t};\r\n\r\n\tQVariantMap serialize();\r\n\tvoid deserialize( QVariantMap in );\r\n};\r\n\r\nenum class MissionType\r\n{\r\n\tNOMISSION,\r\n\tEXPLORE,\r\n\tSPY,\r\n\tEMISSARY,\r\n\tRAID,\r\n\tSABOTAGE\r\n};\r\nQ_DECLARE_METATYPE( MissionType )\r\n\r\nenum class MissionStep\r\n{\r\n\tNONE,\r\n\tLEAVE_MAP,\r\n\tTRAVEL,\r\n\tACTION,\r\n\tRETURN,\r\n\tRETURNED\r\n};\r\nQ_DECLARE_METATYPE( MissionStep )\r\n\r\nenum class MissionAction\r\n{\r\n\tNONE,\r\n\tIMPROVE,\r\n\tINSULT,\r\n\tINVITE_TRADER,\r\n\tINVITE_AMBASSADOR\r\n};\r\nQ_DECLARE_METATYPE( MissionAction )\r\n\r\nstruct Mission\r\n{\r\n\tunsigned int id = 0;\r\n\tMissionType type;\r\n\tMissionAction action;\r\n\tMissionStep step;\r\n\tunsigned int target = 0;\r\n\tint distance        = 0;\r\n\tQList<unsigned int> gnomes;\r\n\tquint64 startTick     = 0;\r\n\tquint64 nextCheckTick = 0;\r\n\tint time = 0;\r\n\r\n\tPosition leavePos;\r\n\tQVariantMap result;\r\n\r\n\tMission() {};\r\n\tMission( QVariantMap in );\r\n\r\n\tQVariantMap serialize();\r\n};\r\nQ_DECLARE_METATYPE( Mission )\r\n\r\n\r\nclass EventManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( EventManager )\r\npublic:\r\n\tEventManager( Game* parent );\r\n\t~EventManager();\r\n\r\n\tQVariantMap serialize();\r\n\tvoid deserialize( QVariantMap in );\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid addTraderEvent( NeighborKingdom kingdom );\r\n\tvoid addRaidEvent( NeighborKingdom kingdom );\r\n\r\n\tQList<Mission>& missions();\r\n\tvoid addMission( Mission mission );\r\n\tMission* getMission( unsigned int id );\r\n\tvoid finishMission( unsigned int id );\r\n\r\n\tvoid startMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQMap<QString, int> m_string2type;\r\n\tQMap<QString, int> m_reqMap;\r\n\r\n\tQList<Event> m_eventList;\r\n\r\n\tEvent createEvent( QString eventID );\r\n\r\n\tbool checkRequirements( Event& event );\r\n\r\n\tvoid executeEvent( Event& event );\r\n\r\n\tvoid spawnGnome( Position location, int amount );\r\n\tvoid spawnInvasion( Position location, int amount, QVariantMap data );\r\n\tvoid spawnTrader( Position location, unsigned int marketStall, QVariantMap data );\r\n\r\n\tPosition getEventLocation( QVariantMap& eventMap );\r\n\r\n\tQList<Mission> m_missions;\r\n\r\nsignals:\r\n\tvoid signalCenterCamera( const Position& location );\r\n\tvoid signalUpdateMission( const Mission& mission );\r\n\r\npublic slots:\r\n\tvoid onAnswer( unsigned int id, bool answer );\r\n\r\n\tvoid onDebugEvent( EventType type, QVariantMap args );\r\n};\r\n"
  },
  {
    "path": "src/game/farm.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"farm.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nFarmProperties::FarmProperties( QVariantMap& in )\r\n{\r\n\tplantType = in.value( \"PlantType\" ).toString();\r\n\tseedItem  = in.value( \"SeedItemID\" ).toString();\r\n\tonlySeed  = in.value( \"OnlySeed\" ).toBool();\r\n\tharvest   = in.value( \"Harvest\" ).toBool();\r\n\tauto vjpl = in.value( \"JobPriorities\" ).toList();\r\n\tfor ( auto vjp : vjpl )\r\n\t{\r\n\t\tjobPriorities.append( vjp.value<quint8>() );\r\n\t}\r\n\r\n\tautoHarvestSeed  = in.value( \"AutoHarvestSeed\" ).toBool();\r\n\tautoHarvestItem1 = in.value( \"AutoHarvestItem1\" ).toBool();\r\n\tautoHarvestItem2 = in.value( \"AutoHarvestItem2\" ).toBool();\r\n\r\n\tautoHarvestSeedMin  = in.value( \"AutoHarvestSeedMin\" ).toUInt();\r\n\tautoHarvestSeedMax  = in.value( \"AutoHarvestSeedMax\" ).toUInt();\r\n\tautoHarvestItem1Min = in.value( \"AutoHarvestItem1Min\" ).toUInt();\r\n\tautoHarvestItem1Max = in.value( \"AutoHarvestItem1Max\" ).toUInt();\r\n\tautoHarvestItem2Min = in.value( \"AutoHarvestItem2Min\" ).toUInt();\r\n\tautoHarvestItem2Max = in.value( \"AutoHarvestItem2Max\" ).toUInt();\r\n}\r\n\r\nvoid FarmProperties::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"Type\", \"farm\" );\r\n\tout.insert( \"PlantType\", plantType );\r\n\tout.insert( \"SeedItemID\", seedItem );\r\n\tout.insert( \"OnlySeed\", onlySeed );\r\n\tout.insert( \"Harvest\", harvest );\r\n\tQVariantList jpl;\r\n\tfor ( auto jp : jobPriorities )\r\n\t{\r\n\t\tjpl.append( jp );\r\n\t}\r\n\tout.insert( \"JobPriorities\", jpl );\r\n\r\n\tout.insert( \"AutoHarvestSeed\", autoHarvestSeed );\r\n\tout.insert( \"AutoHarvestItem1\", autoHarvestItem1 );\r\n\tout.insert( \"AutoHarvestItem2\", autoHarvestItem2 );\r\n\r\n\tout.insert( \"AutoHarvestSeedMin\", autoHarvestSeedMin );\r\n\tout.insert( \"AutoHarvestSeedMax\", autoHarvestSeedMax );\r\n\tout.insert( \"AutoHarvestItem1Min\", autoHarvestItem1Min );\r\n\tout.insert( \"AutoHarvestItem1Max\", autoHarvestItem1Max );\r\n\tout.insert( \"AutoHarvestItem2Min\", autoHarvestItem2Min );\r\n\tout.insert( \"AutoHarvestItem2Max\", autoHarvestItem2Max );\r\n}\r\n\r\nFarm::Farm( QList<QPair<Position, bool>> tiles, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_name = \"Farm\";\r\n\r\n\tm_properties.jobPriorities.clear();\r\n\tm_properties.jobPriorities.push_back( FarmJobs::Harvest );\r\n\tm_properties.jobPriorities.push_back( FarmJobs::PlantPlant );\r\n\tm_properties.jobPriorities.push_back( FarmJobs::Till );\r\n\r\n\tfor ( auto p : tiles )\r\n\t{\r\n\t\tif ( p.second )\r\n\t\t{\r\n\t\t\tm_fields.insert( p.first.toInt(), FarmField(p.first, nullptr));\r\n\t\t}\r\n\t}\r\n\r\n\tif (!m_fields.empty())\r\n\t{\r\n\t\tm_properties.firstPos = m_fields.first().pos;\r\n\t}\r\n}\r\n\r\nFarm::Farm( QVariantMap vals, Game* game ) :\r\n\tWorldObject( vals, game ),\r\n\tm_properties( vals )\r\n{\r\n\tQVariantList vfl = vals.value( \"Fields\" ).toList();\r\n\tfor ( auto vf : vfl )\r\n\t{\r\n\t\tFarmField grofi;\r\n\t\tauto gfm = vf.toMap();\r\n\t\tgrofi.pos       = Position( gfm.value( \"Pos\" ).toString() );\r\n\t\tif( gfm.contains( \"Job\" ) )\r\n\t\t{\r\n\t\t\tgrofi.job = g->jm()->getJob( gfm.value( \"Job\" ).toUInt() );\r\n\t\t}\r\n\t\tm_fields.insert( grofi.pos.toInt(), std::move(grofi));\r\n\t}\r\n\r\n\tif (!m_fields.empty())\r\n\t{\r\n\t\tm_properties.firstPos = m_fields.first().pos;\r\n\t}\r\n\r\n\tQVariantList vjl = vals.value( \"Jobs\" ).toList();\r\n\tfor ( auto vj : vjl )\r\n\t{\r\n\t\tQSharedPointer<Job> job( new Job( vj.toMap() ) );\r\n\t}\r\n}\r\n\r\nQVariant Farm::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tWorldObject::serialize( out );\r\n\tm_properties.serialize( out );\r\n\r\n\tQVariantList tiles;\r\n\tfor ( const auto& field : m_fields )\r\n\t{\r\n\t\tQVariantMap entry;\r\n\t\tentry.insert( \"Pos\", field.pos.toString() );\r\n\t\tif( field.job )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> spJob = field.job.toStrongRef();\r\n\t\t\tentry.insert( \"Job\", spJob->id() );\r\n\t\t}\r\n\t\ttiles.append( entry );\r\n\t}\r\n\tout.insert( \"Fields\", tiles );\r\n\treturn out;\r\n}\r\n\r\nFarm::~Farm()\r\n{\r\n\r\n}\r\n\r\nvoid Farm::addTile( const Position & pos )\r\n{\r\n\tm_fields.insert( pos.toInt(), FarmField(pos, nullptr) );\r\n\tg->w()->setTileFlag( pos, TileFlag::TF_FARM );\r\n}\r\n\r\nvoid Farm::onTick( quint64 tick )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn;\r\n\r\n\tfor( auto& gf : m_fields )\r\n\t{\r\n\t\tif( !gf.job )\r\n\t\t{\r\n\t\t\tTile& tile = g->w()->getTile( gf.pos );\r\n\r\n\t\t\tif ( g->w()->plants().contains( gf.pos.toInt() ) )\r\n\t\t\t{\r\n\t\t\t\tPlant& plant = g->w()->plants()[gf.pos.toInt()];\r\n\t\t\t\tif ( !plant.isPlant() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif ( plant.harvestable() )\r\n\t\t\t\t{\r\n\t\t\t\t\t//harvest\r\n\t\t\t\t\tunsigned int jobID = g->jm()->addJob( \"Harvest\", gf.pos, 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//job->setPrio();\r\n\t\t\t\t\t\tgf.job = job;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( !( tile.flags & TileFlag::TF_TILLED ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t//till\r\n\t\t\t\t\tunsigned int jobID = g->jm()->addJob( \"Till\", gf.pos, 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//job->setPrio();\r\n\t\t\t\t\t\tgf.job = job;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif ( tile.flags & TileFlag::TF_TILLED )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto item = g->inv()->getClosestItem( m_fields.first().pos, true, m_properties.seedItem, m_properties.plantType );\r\n\t\t\t\t\tif ( item == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tunsigned int jobID = g->jm()->addJob( \"PlantFarm\", gf.pos, \"Plant\", { m_properties.plantType}, 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob->addRequiredItem( 1, m_properties.seedItem, m_properties.plantType, QStringList() );\r\n\t\t\t\t\t\t//job->setPrio();\r\n\t\t\t\t\t\tgf.job = job;\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\t//updateAutoFarmer();\r\n}\r\n\r\nvoid Farm::updateAutoFarmer()\r\n{\r\n\tQString seedMaterialID = DB::select( \"Material\", \"Plants\", m_properties.plantType ).toString();\r\n\r\n\tunsigned int countSeed = g->inv()->itemCount( m_properties.seedItem, seedMaterialID );\r\n\r\n\tauto hl = DB::selectRows( \"Plants_OnHarvest_HarvestedItem\", m_properties.plantType );\r\n\r\n\tQString item1ID;\r\n\tQString material1ID;\r\n\tQString item2ID;\r\n\tQString material2ID;\r\n\tfor ( auto hi : hl )\r\n\t{\r\n\t\titem1ID = hi.value( \"ItemID\" ).toString();\r\n\t\tif ( item1ID != m_properties.seedItem )\r\n\t\t{\r\n\t\t\tmaterial1ID = hi.value( \"MaterialID\" ).toString();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tunsigned int countItem1 = 0;\r\n\tunsigned int countItem2 = 0;\r\n\tif ( !item1ID.isEmpty() )\r\n\t{\r\n\t\tcountItem1 = g->inv()->itemCount( item1ID, material1ID );\r\n\t}\r\n\r\n\tfor ( auto hi : hl )\r\n\t{\r\n\t\titem2ID = hi.value( \"ItemID\" ).toString();\r\n\t\tif ( item2ID != m_properties.seedItem && item2ID != item1ID )\r\n\t\t{\r\n\t\t\tmaterial2ID = hi.value( \"MaterialID\" ).toString();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !item2ID.isEmpty() )\r\n\t{\r\n\t\tcountItem2 = g->inv()->itemCount( item2ID, material2ID );\r\n\t}\r\n\tbool harvestOn  = false;\r\n\tbool harvestOff = false;\r\n\r\n\tif ( m_properties.autoHarvestSeed )\r\n\t{\r\n\t\tunsigned int count = g->inv()->itemCount( m_properties.seedItem, seedMaterialID );\r\n\t\tunsigned int min   = m_properties.autoHarvestSeedMin;\r\n\t\tunsigned int max   = m_properties.autoHarvestSeedMax;\r\n\t\tif ( count < min )\r\n\t\t{\r\n\t\t\tharvestOn = true;\r\n\t\t}\r\n\t\tif ( count > max )\r\n\t\t{\r\n\t\t\tharvestOff = true;\r\n\t\t}\r\n\t}\r\n\tif ( m_properties.autoHarvestItem1 && !item1ID.isEmpty() )\r\n\t{\r\n\t\tunsigned int count = g->inv()->itemCount( item1ID, material1ID );\r\n\t\tunsigned int min   = m_properties.autoHarvestItem1Min;\r\n\t\tunsigned int max   = m_properties.autoHarvestItem1Max;\r\n\t\tif ( count < min )\r\n\t\t{\r\n\t\t\tharvestOn = true;\r\n\t\t}\r\n\t\tif ( count > max )\r\n\t\t{\r\n\t\t\tharvestOff = true;\r\n\t\t}\r\n\t}\r\n\tif ( m_properties.autoHarvestItem2 && !item2ID.isEmpty() )\r\n\t{\r\n\t\tunsigned int count = g->inv()->itemCount( item2ID, material2ID );\r\n\t\tunsigned int min   = m_properties.autoHarvestItem2Min;\r\n\t\tunsigned int max   = m_properties.autoHarvestItem2Max;\r\n\t\tif ( count < min )\r\n\t\t{\r\n\t\t\tharvestOn = true;\r\n\t\t}\r\n\t\tif ( count > max )\r\n\t\t{\r\n\t\t\tharvestOff = true;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( harvestOn )\r\n\t{\r\n\t\tm_properties.harvest = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( harvestOff )\r\n\t\t{\r\n\t\t\tm_properties.harvest = false;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Farm::canDelete()\r\n{\r\n\treturn true; //m_jobsOut.isEmpty();\r\n}\r\n\r\nbool Farm::removeTile( const Position & pos )\r\n{\r\n\tauto id = pos.toInt();\r\n\tif( m_fields.contains( id ) )\r\n\t{\r\n\t\tauto gf = m_fields.value( id );\r\n\t\tif( gf.job )\r\n\t\t{\r\n\t\t\t//qDebug() << \"farm field still has a job\";\r\n\t\t\tg->jm()->deleteJobAt( pos );\r\n\t\t}\r\n\t}\r\n\tm_fields.remove( id );\r\n\tg->w()->clearTileFlag( pos, TileFlag::TF_FARM );\r\n\r\n\tif (!m_fields.empty())\r\n\t{\r\n\t\tm_properties.firstPos = m_fields.first().pos;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_properties.firstPos = Position();\r\n\t}\r\n\r\n\t// if last tile deleted return true\r\n\treturn m_fields.empty();\r\n}\r\n\r\nvoid Farm::getInfo( int& numPlots, int& tilled, int& planted, int& cropReady )\r\n{\r\n\tnumPlots  = m_fields.size();\r\n\ttilled    = 0;\r\n\tplanted   = 0;\r\n\tcropReady = 0;\r\n\tfor ( const auto& gf : m_fields )\r\n\t{\r\n\r\n\t\tTile& tile = g->w()->getTile( gf.pos );\r\n\t\tif ( tile.flags & TileFlag::TF_TILLED )\r\n\t\t{\r\n\t\t\t++tilled;\r\n\t\t}\r\n\t\tif ( g->w()->plants().contains( gf.pos.toInt() ) )\r\n\t\t{\r\n\t\t\tPlant& plant = g->w()->plants()[gf.pos.toInt()];\r\n\r\n\t\t\tif ( plant.isPlant() )\r\n\t\t\t{\r\n\t\t\t\t++planted;\r\n\t\t\t\tif ( plant.harvestable() )\r\n\t\t\t\t{\r\n\t\t\t\t\t++cropReady;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint Farm::countTiles()\r\n{\r\n\treturn m_fields.size();\r\n}\r\n\r\nvoid Farm::setPlantType( QString plantID )\r\n{\r\n\tm_properties.plantType = plantID;\r\n\r\n\tQString seedItemID    = DB::select( \"SeedItemID\", \"Plants\", plantID ).toString();\r\n\tm_properties.seedItem = seedItemID;\r\n}\r\n\r\nvoid Farm::setHarvest( bool harvest )\r\n{\r\n\tm_properties.harvest = harvest;\r\n}"
  },
  {
    "path": "src/game/farm.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/worldobject.h\"\r\n#include \"../game/job.h\"\r\n\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QPair>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\n\r\nstruct FarmField\r\n{\r\n\tFarmField() = default;\r\n\tFarmField(const Position& pos, const QSharedPointer<Job>& job) : pos(pos), job(job) {}\r\n\r\n\tPosition pos;\r\n\tQWeakPointer<Job> job;\r\n};\r\n\r\nenum FarmJobs : quint8\r\n{\r\n\tTill,\r\n\tPlantPlant,\r\n\tHarvest\r\n};\r\n\r\nstruct FarmProperties\r\n{\r\n\tQString plantType = \"\";\r\n\tQString seedItem  = \"\";\r\n\r\n\tPosition firstPos;\r\n\r\n\tbool onlySeed = true;\r\n\tbool harvest  = true;\r\n\r\n\tQList<qint8> jobPriorities;\r\n\r\n\tbool autoHarvestSeed  = false;\r\n\tbool autoHarvestItem1 = false;\r\n\tbool autoHarvestItem2 = false;\r\n\r\n\tunsigned int autoHarvestSeedMin  = 0;\r\n\tunsigned int autoHarvestSeedMax  = 0;\r\n\tunsigned int autoHarvestItem1Min = 0;\r\n\tunsigned int autoHarvestItem1Max = 0;\r\n\tunsigned int autoHarvestItem2Min = 0;\r\n\tunsigned int autoHarvestItem2Max = 0;\r\n\r\n\tvoid serialize( QVariantMap& out ) const;\r\n\tFarmProperties() {};\r\n\tFarmProperties( QVariantMap& in );\r\n};\r\n\r\nclass Farm : public WorldObject\r\n{\r\n\tfriend class AggregatorAgri;\r\n\tQ_DISABLE_COPY_MOVE( Farm )\r\npublic:\r\n\tFarm() = delete;\r\n\tFarm( QList<QPair<Position, bool>> tiles, Game* game );\r\n\tFarm( QVariantMap vals, Game* game );\r\n\t~Farm();\r\n\r\n\tQVariant serialize() const;\r\n\r\n\tQString plantType() const\r\n\t{\r\n\t\treturn m_properties.plantType;\r\n\t}\r\n\r\n\tbool harvest() const\r\n\t{\r\n\t\treturn m_properties.harvest;\r\n\t}\r\n\r\n\tvoid onTick( quint64 tick );\r\n\r\n\tbool removeTile( const Position & pos );\r\n\tvoid addTile( const Position & pos );\r\n\r\n\tvoid getInfo( int& numPlots, int& tilled, int& planted, int& ready );\r\n\r\n\tvoid setPlantType( QString plantID );\r\n\tvoid setHarvest( bool harvest );\r\n\r\n\tbool canDelete();\r\n\tint countTiles();\r\n\r\nprivate:\r\n\tFarmProperties m_properties;\r\n\r\n\tQMap<unsigned int, FarmField> m_fields;\r\n\r\n\tvoid updateAutoFarmer();\r\n\r\n\tFarmProperties& properties()\r\n\t{\r\n\t\treturn m_properties;\r\n\t}\r\n};\r\n"
  },
  {
    "path": "src/game/farmingmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"farmingmanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/global.h\"\r\n#include \"../base/position.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QVariantMap>\r\n\r\nvoid Beehive::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"Type\", \"beehive\" );\r\n\tout.insert( \"ID\", id );\r\n\tout.insert( \"Pos\", pos.toString() );\r\n\tout.insert( \"Honey\", honey );\r\n\tout.insert( \"Harvest\", harvest );\r\n}\r\n\r\nBeehive::Beehive()\r\n{\r\n}\r\n\r\nBeehive::~Beehive()\r\n{\r\n}\r\n\r\nBeehive::Beehive( QVariantMap& in )\r\n{\r\n\tid      = in.value( \"ID\" ).toUInt();\r\n\tpos     = Position( in.value( \"Pos\" ) );\r\n\thoney   = in.value( \"Honey\" ).toFloat();\r\n\tharvest = in.value( \"Harvest\" ).toBool();\r\n}\r\n\r\nFarmingManager::FarmingManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject(parent)\r\n{\r\n}\r\n\r\nFarmingManager::~FarmingManager()\r\n{\r\n\tfor (const auto& pa : m_pastures)\r\n\t{\r\n\t\tdelete pa;\r\n\t}\r\n\tm_pastures.clear();\r\n\tfor (const auto& fa : m_farms)\r\n\t{\r\n\t\tdelete fa;\r\n\t}\r\n\tm_farms.clear();\r\n\tfor (const auto& gr : m_groves)\r\n\t{\r\n\t\tdelete gr;\r\n\t}\r\n\tm_groves.clear();\r\n\tfor ( const auto& bh : m_beehives )\r\n\t{\r\n\t\tdelete bh;\r\n\t}\r\n\tm_beehives.clear();\r\n}\r\n\r\nbool FarmingManager::load( QVariantMap vm )\r\n{\r\n\tQString type = vm.value( \"Type\" ).toString();\r\n\tif ( type == \"farm\" )\r\n\t{\r\n\t\tauto fa = new Farm( vm, g );\r\n\t\tm_farms.insert( fa->id(), fa );\r\n\t\tfor ( const auto& f : vm.value( \"Fields\" ).toList() )\r\n\t\t{\r\n\t\t\tQVariantMap fm = f.toMap();\r\n\t\t\tm_allFarmTiles.insert( Position( fm.value( \"Pos\" ).toString() ), fa->id() );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\tif ( type == \"grove\" )\r\n\t{\r\n\t\tauto gr = new Grove( vm, g );\r\n\t\tm_groves.insert( gr->id(), gr );\r\n\t\tfor ( const auto& f : vm.value( \"Fields\" ).toList() )\r\n\t\t{\r\n\t\t\tQVariantMap fm = f.toMap();\r\n\t\t\tm_allGroveTiles.insert( Position( fm.value( \"Pos\" ).toString() ), gr->id() );\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\tif ( type == \"pasture\" )\r\n\t{\r\n\t\tauto pa = new Pasture( vm, g );\r\n\t\tm_pastures.insert( pa->id(), pa );\r\n\t\tfor ( const auto& f : vm.value( \"Fields\" ).toList() )\r\n\t\t{\r\n\t\t\tQVariantMap fm = f.toMap();\r\n\t\t\tm_allPastureTiles.insert( Position( fm.value( \"Pos\" ).toString() ), pa->id() );\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tif ( type == \"beehive\" )\r\n\t{\r\n\t\tauto bh = new Beehive( vm );\r\n\t\tm_beehives.insert( bh->id, bh );\r\n\t\tm_allBeehiveTiles.insert( bh->pos, bh->id );\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid FarmingManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tonTickFarm( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\tonTickPasture( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\tonTickGrove( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\tif ( hourChanged )\r\n\t{\r\n\t\tonTickBeeHive( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::onTickBeeHive( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tfor ( auto& bh : m_beehives )\r\n\t{\r\n\t\tbh->honey += (float)( 1.0 / 200. );\r\n\r\n\t\tif ( bh->honey >= 1.0 && !bh->hasJob )\r\n\t\t{\r\n\t\t\tg->m_jobManager->addJob( \"Harvest\", bh->pos, 0, true );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::onTickGrove( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tfor ( auto&& gr : m_groves )\r\n\t{\r\n\t\tgr->onTick( tickNumber );\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::onTickFarm( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tif ( hourChanged )\r\n\t{\r\n\t\tfor ( auto&& fa : m_farms )\r\n\t\t{\r\n\t\t\tif ( fa->countTiles() == 0 && fa->canDelete() )\r\n\t\t\t{\r\n\t\t\t\tremoveFarm( fa->id() );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto& fa : m_farms )\r\n\t{\r\n\t\tfa->onTick( tickNumber );\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::onTickPasture( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tif ( hourChanged )\r\n\t{\r\n\t\tfor ( auto& pa : m_pastures )\r\n\t\t{\r\n\t\t\tif ( pa->countTiles() == 0 && pa->canDelete() )\r\n\t\t\t{\r\n\t\t\t\tremovePasture( pa->id() );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( minuteChanged )\r\n\t{\r\n\t\tm_totalCountAnimals = 0;\r\n\t\tint count = 0;\r\n\t\tfor ( auto& pa : m_pastures )\r\n\t\t{\r\n\t\t\tpa->onTick( tickNumber, count );\r\n\t\t\tm_totalCountAnimals += count;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::addGrove( Position firstClick, QList<QPair<Position, bool>> fields )\r\n{\r\n\tif ( m_allGroveTiles.contains( firstClick ) )\r\n\t{\r\n\t\tunsigned int grID = m_allGroveTiles.value( firstClick );\r\n\r\n\t\tGrove* gr = getGroveAtPos( firstClick );\r\n\t\tif ( gr )\r\n\t\t{\r\n\t\t\tfor ( const auto& p : fields )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second && !m_allGroveTiles.contains( p.first ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_allGroveTiles.insert( p.first, grID );\r\n\t\t\t\t\tgr->addTile( p.first );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tauto gr = new Grove( fields, g );\r\n\t\tfor ( const auto& p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second && !m_allGroveTiles.contains(p.first) )\r\n\t\t\t{\r\n\t\t\t\tm_allGroveTiles.insert( p.first, gr->id() );\r\n\t\t\t\tgr->addTile( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_groves.insert( gr->id(), gr );\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::removeGrove( unsigned int id )\r\n{\r\n\tauto it = m_groves.find( id );\r\n\tif ( it != m_groves.end() )\r\n\t{\r\n\t\tfor ( auto field = m_allGroveTiles.begin(); field != m_allGroveTiles.end(); )\r\n\t\t{\r\n\t\t\tif ( field.value() == id )\r\n\t\t\t{\r\n\t\t\t\tit.value()->removeTile( field.key() );\r\n\t\t\t\tfield = m_allGroveTiles.erase( field );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++field;\r\n\t\t\t}\r\n\t\t}\r\n\t\tdelete it.value();\r\n\t\tm_groves.erase( it );\r\n\t}\r\n}\r\n\r\nGrove* FarmingManager::getGroveAtPos( Position pos )\r\n{\r\n\tauto it = m_allGroveTiles.find( pos );\r\n\tif (it != m_allGroveTiles.end())\r\n\t{\r\n\t\treturn getGrove( it.value() );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nGrove* FarmingManager::getGrove( unsigned int id )\r\n{\r\n\tauto it = m_groves.find( id );\r\n\tif (it != m_groves.end())\r\n\t{\r\n\t\treturn it.value();\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nbool FarmingManager::isGrove( Position pos ) const\r\n{\r\n\treturn m_allGroveTiles.contains( pos );\r\n}\r\n\r\nvoid FarmingManager::addFarm( Position firstClick, QList<QPair<Position, bool>> fields )\r\n{\r\n\tif ( m_allFarmTiles.contains( firstClick) )\r\n\t{\r\n\t\tunsigned int faID = m_allFarmTiles.value( firstClick );\r\n\r\n\t\tFarm* fa = getFarmAtPos( firstClick );\r\n\t\tif ( fa )\r\n\t\t{\r\n\t\t\tfor ( const auto& p : fields )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second && !m_allFarmTiles.contains( p.first ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_allFarmTiles.insert( p.first, faID );\r\n\t\t\t\t\tfa->addTile( p.first );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\temit signalFarmChanged( faID );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tauto fa = new Farm( fields, g );\r\n\t\tfor ( const auto& p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second && !m_allFarmTiles.contains( p.first ) )\r\n\t\t\t{\r\n\t\t\t\tm_allFarmTiles.insert( p.first, fa->id() );\r\n\t\t\t\tfa->addTile( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_farms.insert( fa->id(), fa );\r\n\t\temit signalFarmChanged( fa->id() );\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::removeFarm( unsigned int id )\r\n{\r\n\tauto it = m_farms.find( id );\r\n\tif ( it != m_farms.end() )\r\n\t{\r\n\t\tfor ( auto field = m_allFarmTiles.begin(); field != m_allFarmTiles.end(); )\r\n\t\t{\r\n\t\t\tif ( field.value() == id )\r\n\t\t\t{\r\n\t\t\t\tit.value()->removeTile( field.key() );\r\n\t\t\t\tfield = m_allFarmTiles.erase( field );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++field;\r\n\t\t\t}\r\n\t\t}\r\n\t\tdelete it.value();\r\n\t\tm_farms.erase( it );\r\n\t}\r\n}\r\n\r\nFarm* FarmingManager::getFarmAtPos( Position pos )\r\n{\r\n\tauto it = m_allFarmTiles.find( pos );\r\n\tif ( it != m_allFarmTiles.end() )\r\n\t{\r\n\t\treturn getFarm( it.value() );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nFarm* FarmingManager::getFarm( unsigned int id )\r\n{\r\n\tauto it = m_farms.find( id );\r\n\tif ( it != m_farms.end() )\r\n\t{\r\n\t\treturn it.value();\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nbool FarmingManager::isFarm( Position pos ) const\r\n{\r\n\treturn m_allFarmTiles.contains( pos );\r\n}\r\n\r\nvoid FarmingManager::addPasture( Position firstClick, QList<QPair<Position, bool>> fields )\r\n{\r\n\tif ( m_allPastureTiles.contains( firstClick ) )\r\n\t{\r\n\t\tunsigned int paID = m_allPastureTiles.value( firstClick );\r\n\r\n\t\tPasture* pa = getPastureAtPos( firstClick );\r\n\t\tif ( pa )\r\n\t\t{\r\n\t\t\tfor ( const auto& p : fields )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second && !m_allPastureTiles.contains( p.first ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_allPastureTiles.insert( p.first, paID );\r\n\t\t\t\t\tpa->addTile( p.first );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tauto pa = new Pasture( fields, g );\r\n\t\tfor ( const auto& p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second && !m_allPastureTiles.contains( p.first ) )\r\n\t\t\t{\r\n\t\t\t\tm_allPastureTiles.insert( p.first, pa->id() );\r\n\t\t\t\tpa->addTile( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_pastures.insert( pa->id(), pa );\r\n\t}\r\n}\r\n\r\nvoid FarmingManager::removePasture( unsigned int id )\r\n{\r\n\tauto it = m_pastures.find( id );\r\n\tif ( it != m_pastures.end() )\r\n\t{\r\n\t\tfor ( auto field = m_allFarmTiles.begin(); field != m_allFarmTiles.end(); )\r\n\t\t{\r\n\t\t\tif ( field.value() == id )\r\n\t\t\t{\r\n\t\t\t\tit.value()->removeTile( field.key() );\r\n\t\t\t\tfield = m_allFarmTiles.erase( field );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++field;\r\n\t\t\t}\r\n\t\t}\r\n\t\tit.value()->removeAllAnimals();\r\n\t\tdelete it.value();\r\n\t\tm_pastures.erase( it );\r\n\t}\r\n}\r\n\r\nPasture* FarmingManager::getPastureAtPos( Position pos )\r\n{\r\n\tauto it = m_allPastureTiles.find( pos );\r\n\tif ( it != m_allPastureTiles.end() )\r\n\t{\r\n\t\treturn getPasture( it.value() );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nPasture* FarmingManager::getPasture( unsigned int id )\r\n{\r\n\tauto it = m_pastures.find( id );\r\n\tif ( it != m_pastures.end() )\r\n\t{\r\n\t\treturn it.value();\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nbool FarmingManager::isPasture( Position pos ) const\r\n{\r\n\treturn m_allPastureTiles.contains( pos );\r\n}\r\n\r\nconst QHash<unsigned int, Grove*>& FarmingManager::allGroves()\r\n{\r\n\treturn m_groves;\r\n}\r\n\r\nconst QHash<unsigned int, Farm*>& FarmingManager::allFarms()\r\n{\r\n\treturn m_farms;\r\n}\r\n\r\nconst QHash<unsigned int, Pasture*>& FarmingManager::allPastures()\r\n{\r\n\treturn m_pastures;\r\n}\r\n\r\nconst QHash<unsigned int, Beehive*>& FarmingManager::allBeeHives()\r\n{\r\n\treturn m_beehives;\r\n}\r\n\r\nvoid FarmingManager::removeTile( Position pos, bool includeFarm, bool includePasture, bool includeGrove )\r\n{\r\n\tif ( includeFarm && isFarm( pos ) )\r\n\t{\r\n\t\tFarm* farm = getFarmAtPos( pos );\r\n\t\tif ( farm )\r\n\t\t{\r\n\t\t\tunsigned int id = farm->id();\r\n\t\t\tm_allFarmTiles.remove( pos );\r\n\t\t\tif ( farm->removeTile( pos ) && farm->canDelete() )\r\n\t\t\t{\r\n\t\t\t\tremoveFarm( id );\r\n\t\t\t}\r\n\t\t\temit signalFarmChanged( id );\r\n\t\t}\r\n\t}\r\n\telse if ( includeGrove && isGrove( pos ) )\r\n\t{\r\n\t\tGrove* grove = getGroveAtPos( pos );\r\n\t\tif ( grove )\r\n\t\t{\r\n\t\t\tm_allGroveTiles.remove( pos );\r\n\t\t\tif ( grove->removeTile( pos ) && grove->canDelete() )\r\n\t\t\t{\r\n\t\t\t\tremoveGrove( grove->id() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( includePasture && isPasture( pos ) )\r\n\t{\r\n\t\tPasture* pasture = getPastureAtPos( pos );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tm_allPastureTiles.remove( pos );\r\n\t\t\tif ( pasture->removeTile( pos ) && pasture->canDelete() )\r\n\t\t\t{\r\n\t\t\t\tremovePasture( pasture->id() );\r\n\t\t\t}\r\n\t\t\temit signalPastureChanged( pasture->id() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool FarmingManager::addUtil( Position pos, unsigned int itemID )\r\n{\r\n\tQString itemSID = g->m_inv->itemSID( itemID );\r\n\r\n\tif ( itemSID == \"Shed\" )\r\n\t{\r\n\t\treturn addUtilToPasture( pos, itemID );\r\n\t}\r\n\telse if ( itemSID == \"Trough\" )\r\n\t{\r\n\t\treturn addUtilToPasture( pos, itemID );\r\n\t}\r\n\telse if ( itemSID == \"BeeHive\" )\r\n\t{\r\n\t\tif ( !m_allBeehiveTiles.contains( pos ) )\r\n\t\t{\r\n\t\t\tauto bh = new Beehive;\r\n\t\t\tbh->id  = itemID;\r\n\t\t\tbh->pos = pos;\r\n\r\n\t\t\tm_beehives.insert( bh->id, bh );\r\n\t\t\tm_allBeehiveTiles.insert( bh->pos, bh->id );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool FarmingManager::removeUtil( Position pos )\r\n{\r\n\tif ( auto bh = getBeehiveAtPos(pos) )\r\n\t{\r\n\t\tm_beehives.remove( bh->id );\r\n\t\tm_allBeehiveTiles.remove( bh->pos );\r\n\t\tdelete bh;\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tauto pasture = getPastureAtPos( pos );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tpasture->removeUtil( pos );\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool FarmingManager::addUtilToPasture( Position pos, unsigned int itemID )\r\n{\r\n\tPasture* pasture = getPastureAtPos( pos );\r\n\tif ( pasture )\r\n\t{\r\n\t\treturn pasture->addUtil( pos, itemID );\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nbool FarmingManager::removeUtilFromPasture( Position pos, unsigned int itemID )\r\n{\r\n\tPasture* pasture = getPastureAtPos( pos );\r\n\tif ( pasture )\r\n\t{\r\n\t\treturn pasture->removeUtil( pos );\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nunsigned int FarmingManager::util( Position pos )\r\n{\r\n\tPasture* pasture = getPastureAtPos( pos );\r\n\tif ( pasture )\r\n\t{\r\n\t\treturn pasture->util( pos );\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nint FarmingManager::farmPriority( unsigned int id )\r\n{\r\n\t//TODO\r\n\treturn -1;\r\n}\r\n\r\nint FarmingManager::countFarms()\r\n{\r\n\treturn m_farms.size();\r\n}\r\n\r\nvoid FarmingManager::setFarmPriority( unsigned int id, int prio )\r\n{\r\n\t//TODO\r\n}\r\n\r\nint FarmingManager::grovePriority( unsigned int id )\r\n{\r\n\t//TODO\r\n\treturn -1;\r\n}\r\n\r\nint FarmingManager::countGroves()\r\n{\r\n\treturn m_groves.size();\r\n}\r\n\r\nvoid FarmingManager::setGrovePriority( unsigned int id, int prio )\r\n{\r\n\t//TODO\r\n}\r\n\r\nint FarmingManager::pasturePriority( unsigned int id )\r\n{\r\n\t//TODO\r\n\treturn -1;\r\n}\r\n\r\nint FarmingManager::countPastures()\r\n{\r\n\treturn m_pastures.size();\r\n}\r\n\r\nvoid FarmingManager::setPasturePriority( unsigned int id, int prio )\r\n{\r\n\t//TODO\r\n}\r\n\r\nbool FarmingManager::isBeehive( Position pos )\r\n{\r\n\treturn m_allBeehiveTiles.contains( pos.toInt() );\r\n}\r\n\r\nBeehive* FarmingManager::getBeehiveAtPos( Position pos )\r\n{\r\n\tauto it = m_allBeehiveTiles.find( pos );\r\n\tif ( it != m_allBeehiveTiles.end() )\r\n\t{\r\n\t\treturn getBeehive( it.value() );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nBeehive* FarmingManager::getBeehive( unsigned int id )\r\n{\r\n\tauto it = m_beehives.find( id );\r\n\tif ( it != m_beehives.end() )\r\n\t{\r\n\t\treturn it.value();\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid FarmingManager::setBeehiveHarvest( unsigned int id, bool harvest )\r\n{\r\n\tauto bh = getBeehive( id );\r\n\tif (bh)\r\n\t{\r\n\t\tbh->harvest = harvest;\r\n\t}\r\n}\r\n\r\nbool FarmingManager::harvestBeehive( Position pos )\r\n{\r\n\tauto bh = getBeehiveAtPos( pos );\r\n\tif (bh)\r\n\t{\r\n\t\tbh->hasJob = false;\r\n\t\tbh->honey  = 0.0;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\t\r\nvoid FarmingManager::emitUpdateSignalFarm( unsigned int id )\r\n{\r\n\temit signalFarmChanged( id );\r\n}\r\n\r\nvoid FarmingManager::emitUpdateSignalPasture( unsigned int id )\r\n{\r\n\temit signalPastureChanged( id );\r\n}\r\n\r\nvoid FarmingManager::emitUpdateSignalGrove( unsigned int id )\r\n{\r\n\temit signalGroveChanged( id );\r\n}"
  },
  {
    "path": "src/game/farmingmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"farm.h\"\r\n#include \"grove.h\"\r\n#include \"pasture.h\"\r\n\r\n#include <QHash>\r\n\r\nclass Game;\r\nclass Inventory;\r\nclass Job;\r\nclass JobManager;\r\nclass World;\r\n\r\nstruct Beehive\r\n{\r\n\tunsigned int id = 0;\r\n\tPosition pos;\r\n\tfloat honey  = 0;\r\n\tbool harvest = true;\r\n\tbool hasJob  = false;\r\n\r\n\tvoid serialize( QVariantMap& out ) const;\r\n\tBeehive();\r\n\tBeehive( QVariantMap& in );\r\n\t~Beehive();\r\nprivate:\r\n\tQ_DISABLE_COPY_MOVE( Beehive )\r\n};\r\n\r\nclass FarmingManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( FarmingManager )\r\npublic:\r\n\tFarmingManager( Game* parent );\r\n\t~FarmingManager();\r\n\r\n\tbool load( QVariantMap vm );\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid addGrove( Position firstClick, QList<QPair<Position, bool>> fields );\r\n\tvoid removeGrove( unsigned int id );\r\n\tGrove* getGroveAtPos( Position pos );\r\n\tGrove* getGrove( unsigned int id );\r\n\tbool isGrove( Position pos ) const;\r\n\tint grovePriority( unsigned int id );\r\n\tint countGroves();\r\n\tvoid setGrovePriority( unsigned int id, int prio );\r\n\r\n\tvoid addFarm( Position firstClick, QList<QPair<Position, bool>> fields );\r\n\tvoid removeFarm( unsigned int id );\r\n\tFarm* getFarmAtPos( Position pos );\r\n\tFarm* getFarm( unsigned int id );\r\n\tbool isFarm( Position pos ) const;\r\n\tint farmPriority( unsigned int id );\r\n\tint countFarms();\r\n\tvoid setFarmPriority( unsigned int id, int prio );\r\n\r\n\tvoid addPasture( Position firstClick, QList<QPair<Position, bool>> fields );\r\n\tvoid removePasture( unsigned int id );\r\n\tPasture* getPastureAtPos( Position pos );\r\n\tPasture* getPasture( unsigned int id );\r\n\tbool isPasture( Position pos ) const;\r\n\tint pasturePriority( unsigned int id );\r\n\tint countPastures();\r\n\tvoid setPasturePriority( unsigned int id, int prio );\r\n\r\n\tconst QHash<unsigned int, Grove*>& allGroves();\r\n\tconst QHash<unsigned int, Farm*>& allFarms();\r\n\tconst QHash<unsigned int, Pasture*>& allPastures();\r\n\tconst QHash<unsigned int, Beehive*>& allBeeHives();\r\n\r\n\tvoid removeTile( Position pos, bool includeFarm, bool includePasture, bool includeGrove );\r\n\r\n\tbool addUtil( Position pos, unsigned int itemID );\r\n\tbool removeUtil( Position pos );\r\n\r\n\tbool addUtilToPasture( Position pos, unsigned int itemID );\r\n\tbool removeUtilFromPasture( Position pos, unsigned int itemID );\r\n\tunsigned int util( Position pos );\r\n\r\n\tbool isBeehive( Position pos );\r\n\tBeehive* getBeehiveAtPos( Position pos );\r\n\tBeehive* getBeehive( unsigned int id );\r\n\tvoid setBeehiveHarvest( unsigned int id, bool harvest );\r\n\tbool harvestBeehive( Position pos );\r\n\r\n\tvoid emitUpdateSignalFarm( unsigned int id );\r\n\tvoid emitUpdateSignalPasture( unsigned int id );\r\n\tvoid emitUpdateSignalGrove( unsigned int id );\r\n\r\n\tint countAnimals() { return m_totalCountAnimals; }\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tvoid onTickGrove( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\tvoid onTickFarm( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\tvoid onTickPasture( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\tvoid onTickBeeHive( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tQHash<unsigned int, Grove*> m_groves;\r\n\tQHash<Position, unsigned int> m_allGroveTiles;\r\n\r\n\tQHash<unsigned int, Farm*> m_farms;\r\n\tQHash<Position, unsigned int> m_allFarmTiles;\r\n\r\n\tQHash<unsigned int, Pasture*> m_pastures;\r\n\tQHash<Position, unsigned int> m_allPastureTiles;\r\n\r\n\tQHash<unsigned int, Beehive*> m_beehives;\r\n\tQHash<Position, unsigned int> m_allBeehiveTiles;\r\n\r\n\tint m_totalCountAnimals = 0;\r\n\r\nsignals:\r\n\tvoid signalFarmChanged( unsigned int id );\r\n\tvoid signalPastureChanged( unsigned int id );\r\n\tvoid signalGroveChanged( unsigned int id );\r\n};\r\n"
  },
  {
    "path": "src/game/fluidmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"fluidmanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QQueue>\r\n\r\nQVariantMap NetworkPipe::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"ItemID\", itemUID );\r\n\tout.insert( \"Pos\", pos.toString() );\r\n\tout.insert( \"Type\", type );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid NetworkPipe::deserialize( QVariantMap in )\r\n{\r\n\titemUID = in.value( \"ItemID\" ).toUInt();\r\n\tpos     = Position( in.value( \"Pos\" ) );\r\n\ttype    = (PipeType)in.value( \"Type\" ).value<unsigned char>();\r\n}\r\n\r\nFluidManager::FluidManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nFluidManager::~FluidManager()\r\n{\r\n}\r\n\r\nvoid FluidManager::loadPipes( QVariantList data )\r\n{\r\n\tfor ( auto vdata : data )\r\n\t{\r\n\t\tNetworkPipe np;\r\n\t\tauto vnp = vdata.toMap();\r\n\r\n\t\tnp.deserialize( vnp );\r\n\r\n\t\tm_allPipes.insert( np.pos.toInt(), np );\r\n\t\tswitch ( np.type )\r\n\t\t{\r\n\t\t\tcase PT_PIPE:\r\n\t\t\t\tbreak;\r\n\t\t\tcase PT_INPUT:\r\n\t\t\t\tm_inputs.append( np.pos );\r\n\t\t\t\tbreak;\r\n\t\t\tcase PT_OUTPUT:\r\n\t\t\t\tm_outputs.append( np.pos );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t/*\r\n\t\tif( md.jobID )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> job = new Job( vmd.value( \"Job\" ).toMap() );\r\n\t\t\tm_jobs.insert( md.jobID, job );\r\n\t\t}\r\n\t\t*/\r\n\t}\r\n\tupdateNetwork();\r\n}\r\n\r\nvoid FluidManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tint tickDiff = tickNumber - m_lastTick;\r\n\r\n\tif ( tickDiff < 20 )\r\n\t\treturn;\r\n\tm_lastTick = tickNumber;\r\n\r\n\tbool needUpdate = false;\r\n\r\n\tQQueue<Position> workQueue;\r\n\r\n\t// for all outputs\r\n\t// empty outputs if possible\r\n\t// cue all incoming connections in next order\r\n\tfor ( auto outPos : m_outputs )\r\n\t{\r\n\t\tif ( m_allPipes.contains( outPos.toInt() ) )\r\n\t\t{\r\n\t\t\tNetworkPipe& nw = m_allPipes[outPos.toInt()];\r\n\r\n\t\t\tunsigned char fl = g->m_world->fluidLevel( nw.pos );\r\n\r\n\t\t\tif ( nw.level > 0 && fl < 10 )\r\n\t\t\t{\r\n\t\t\t\tnw.level -= 1;\r\n\t\t\t\tg->m_world->changeFluidLevel( nw.pos, +1 );\r\n\t\t\t}\r\n\t\t\tif ( nw.ins.size() )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto inPos : nw.ins )\r\n\t\t\t\t{\r\n\t\t\t\t\tworkQueue.enqueue( inPos );\r\n\t\t\t\t}\r\n\t\t\t\tauto pos = nw.ins.takeFirst();\r\n\t\t\t\tnw.ins.push_back( pos );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_allPipes.remove( outPos.toInt() );\r\n\t\t}\r\n\t}\r\n\twhile ( !workQueue.isEmpty() )\r\n\t{\r\n\t\tPosition pos = workQueue.dequeue();\r\n\t\tif ( m_allPipes.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tNetworkPipe& nw = m_allPipes[pos.toInt()];\r\n\r\n\t\t\tauto tempList = nw.outs;\r\n\r\n\t\t\tfor ( auto outPos : tempList )\r\n\t\t\t{\r\n\t\t\t\tauto pos2 = nw.outs.takeFirst();\r\n\t\t\t\tnw.outs.push_back( pos2 );\r\n\r\n\t\t\t\tNetworkPipe& outPipe = m_allPipes[outPos.toInt()];\r\n\t\t\t\tif ( nw.level > 0 && outPipe.level < outPipe.capacity )\r\n\t\t\t\t{\r\n\t\t\t\t\toutPipe.level += 1;\r\n\t\t\t\t\tnw.level -= 1;\r\n\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( nw.ins.size() )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto inPos : nw.ins )\r\n\t\t\t\t{\r\n\t\t\t\t\tworkQueue.enqueue( inPos );\r\n\t\t\t\t}\r\n\t\t\t\tauto pos2 = nw.ins.takeFirst();\r\n\t\t\t\tnw.ins.push_back( pos2 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_allPipes.remove( pos.toInt() );\r\n\t\t}\r\n\t}\r\n\tfor ( auto inPos : m_inputs )\r\n\t{\r\n\t\tif ( m_allPipes.contains( inPos.toInt() ) )\r\n\t\t{\r\n\t\t\tNetworkPipe& nw = m_allPipes[inPos.toInt()];\r\n\r\n\t\t\tif ( nw.level < nw.capacity )\r\n\t\t\t{\r\n\t\t\t\tif ( g->m_mechanismManager->hasPower( inPos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned char bfl = g->m_world->fluidLevel( inPos.belowOf() );\r\n\t\t\t\t\tif ( bfl > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnw.level += 1;\r\n\t\t\t\t\t\tg->m_world->changeFluidLevel( inPos.belowOf(), -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}\r\n\r\nvoid FluidManager::addInput( Position pos, unsigned int itemUID )\r\n{\r\n\tNetworkPipe pipe;\r\n\tpipe.pos     = pos;\r\n\tpipe.itemUID = itemUID;\r\n\tpipe.type    = PT_INPUT;\r\n\tm_allPipes.insert( pos.toInt(), pipe );\r\n\tm_inputs.append( pos );\r\n\tupdateNetwork();\r\n}\r\n\r\nvoid FluidManager::addPipe( Position pos, unsigned int itemUID )\r\n{\r\n\tNetworkPipe pipe;\r\n\tpipe.pos     = pos;\r\n\tpipe.itemUID = itemUID;\r\n\tpipe.type    = PT_PIPE;\r\n\tm_allPipes.insert( pos.toInt(), pipe );\r\n\tupdateNetwork();\r\n}\r\n\r\nvoid FluidManager::addOutput( Position pos, unsigned int itemUID )\r\n{\r\n\tNetworkPipe pipe;\r\n\tpipe.pos     = pos;\r\n\tpipe.itemUID = itemUID;\r\n\tpipe.type    = PT_OUTPUT;\r\n\tm_allPipes.insert( pos.toInt(), pipe );\r\n\tm_outputs.append( pos );\r\n\tupdateNetwork();\r\n}\r\n\r\nvoid FluidManager::removeAt( Position pos )\r\n{\r\n\tm_allPipes.remove( pos.toInt() );\r\n\tm_inputs.removeAll( pos );\r\n\tm_outputs.removeAll( pos );\r\n\tupdateNetwork();\r\n}\r\n\r\nvoid FluidManager::updateNetwork()\r\n{\r\n\tfor ( auto& nw : m_allPipes )\r\n\t{\r\n\t\tnw.ins.clear();\r\n\t\tnw.outs.clear();\r\n\t}\r\n\tQQueue<Position> workQueue;\r\n\tfor ( auto pos : m_outputs )\r\n\t{\r\n\t\tPosition n = pos.northOf();\r\n\t\tPosition e = pos.eastOf();\r\n\t\tPosition s = pos.southOf();\r\n\t\tPosition w = pos.westOf();\r\n\r\n\t\tNetworkPipe& nw = m_allPipes[pos.toInt()];\r\n\r\n\t\tif ( m_allPipes.contains( n.toInt() ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( n );\r\n\t\t\tworkQueue.enqueue( n );\r\n\r\n\t\t\tNetworkPipe& nwn = m_allPipes[n.toInt()];\r\n\t\t\tnwn.outs.append( pos );\r\n\t\t}\r\n\t\tif ( m_allPipes.contains( e.toInt() ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( e );\r\n\t\t\tworkQueue.enqueue( e );\r\n\t\t\tNetworkPipe& nwe = m_allPipes[e.toInt()];\r\n\t\t\tnwe.outs.append( pos );\r\n\t\t}\r\n\t\tif ( m_allPipes.contains( s.toInt() ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( s );\r\n\t\t\tworkQueue.enqueue( s );\r\n\t\t\tNetworkPipe& nws = m_allPipes[s.toInt()];\r\n\t\t\tnws.outs.append( pos );\r\n\t\t}\r\n\t\tif ( m_allPipes.contains( w.toInt() ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( w );\r\n\t\t\tworkQueue.enqueue( w );\r\n\t\t\tNetworkPipe& nww = m_allPipes[w.toInt()];\r\n\t\t\tnww.outs.append( pos );\r\n\t\t}\r\n\t}\r\n\twhile ( !workQueue.isEmpty() )\r\n\t{\r\n\t\tPosition pos    = workQueue.dequeue();\r\n\t\tNetworkPipe& nw = m_allPipes[pos.toInt()];\r\n\r\n\t\tPosition n = pos.northOf();\r\n\t\tPosition e = pos.eastOf();\r\n\t\tPosition s = pos.southOf();\r\n\t\tPosition w = pos.westOf();\r\n\r\n\t\tif ( m_allPipes.contains( n.toInt() ) && !nw.outs.contains( n ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( n );\r\n\t\t\tworkQueue.enqueue( n );\r\n\r\n\t\t\tNetworkPipe& nwn = m_allPipes[n.toInt()];\r\n\t\t\tnwn.outs.append( pos );\r\n\t\t}\r\n\t\tif ( m_allPipes.contains( e.toInt() ) && !nw.outs.contains( e ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( e );\r\n\t\t\tworkQueue.enqueue( e );\r\n\t\t\tNetworkPipe& nwe = m_allPipes[e.toInt()];\r\n\t\t\tnwe.outs.append( pos );\r\n\t\t}\r\n\t\tif ( m_allPipes.contains( s.toInt() ) && !nw.outs.contains( s ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( s );\r\n\t\t\tworkQueue.enqueue( s );\r\n\t\t\tNetworkPipe& nws = m_allPipes[s.toInt()];\r\n\t\t\tnws.outs.append( pos );\r\n\t\t}\r\n\t\tif ( m_allPipes.contains( w.toInt() ) && !nw.outs.contains( w ) )\r\n\t\t{\r\n\t\t\tnw.ins.append( w );\r\n\t\t\tworkQueue.enqueue( w );\r\n\t\t\tNetworkPipe& nww = m_allPipes[w.toInt()];\r\n\t\t\tnww.outs.append( pos );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int FluidManager::getJob( unsigned int gnomeID, QString skillID )\r\n{\r\n\r\n\treturn 0;\r\n}\r\n\r\nbool FluidManager::finishJob( unsigned int jobID )\r\n{\r\n\treturn false;\r\n}\r\n\r\nbool FluidManager::giveBackJob( unsigned int jobID )\r\n{\r\n\treturn finishJob( jobID );\r\n}\r\n\r\nQSharedPointer<Job> FluidManager::getJob( unsigned int jobID )\r\n{\r\n\treturn nullptr;\r\n}\r\n\r\nbool FluidManager::hasJobID( unsigned int jobID ) const\r\n{\r\n\treturn false;\r\n}\r\n"
  },
  {
    "path": "src/game/fluidmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/job.h\"\r\n\r\n#include <QSet>\r\n\r\nclass Game;\r\n\r\nenum PipeType : unsigned char\r\n{\r\n\tPT_NONE,\r\n\tPT_INPUT,\r\n\tPT_OUTPUT,\r\n\tPT_PIPE\r\n};\r\n\r\nstruct NetworkPipe\r\n{\r\n\tPosition pos;\r\n\r\n\tunsigned int itemUID = 0;\r\n\r\n\tPipeType type = PT_NONE;\r\n\r\n\tunsigned char capacity = 1;\r\n\tunsigned char level    = 0;\r\n\r\n\tQList<Position> ins;\r\n\tQList<Position> outs;\r\n\r\n\tQVariantMap serialize() const;\r\n\tvoid deserialize( QVariantMap in );\r\n};\r\n\r\nclass FluidManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( FluidManager )\r\npublic:\r\n\tFluidManager( Game* parent );\r\n\t~FluidManager();\r\n\r\n\tQHash<unsigned int, NetworkPipe>& pipes()\r\n\t{\r\n\t\treturn m_allPipes;\r\n\t};\r\n\tvoid loadPipes( QVariantList data );\r\n\r\n\tvoid addInput( Position pos, unsigned int itemUID );\r\n\tvoid addPipe( Position pos, unsigned int itemUID );\r\n\tvoid addOutput( Position pos, unsigned int itemUID );\r\n\tvoid removeAt( Position pos );\r\n\tvoid updateNetwork();\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tunsigned int getJob( unsigned int gnomeID, QString skillID );\r\n\r\n\tbool finishJob( unsigned int jobID );\r\n\tbool giveBackJob( unsigned int jobID );\r\n\tQSharedPointer<Job> getJob( unsigned int jobID );\r\n\tbool hasJobID( unsigned int jobID ) const;\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tquint64 m_lastTick = 0;\r\n\r\n\tQList<Position> m_inputs;\r\n\tQList<Position> m_outputs;\r\n\r\n\tQHash<unsigned int, NetworkPipe> m_allPipes;\r\n};\r\n"
  },
  {
    "path": "src/game/game.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"game.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/io.h\"\r\n#include \"../base/pathfinder.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/animal.h\"\r\n\r\n#include \"../game/inventory.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/eventmanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/fluidmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/newgamesettings.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/soundmanager.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include \"../game/gamemanager.h\"\r\n#include \"../game/gnome.h\"\r\n\r\n#include \"../game/itemhistory.h\"\r\n#include \"../game/object.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/techtree.h\"\r\n#include \"../game/world.h\"\r\n#include \"../game/worldgenerator.h\"\r\n\r\n#include \"../gui/eventconnector.h\"\r\n#include \"../gui/strings.h\"\r\n#include \"../gui/aggregatorcreatureinfo.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QTimer>\r\n\r\n#include <time.h>\r\n\r\nGame::Game( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tqDebug() << \"init game...\";\r\n\t\r\n\tm_upsTimer.start();\r\n\r\n\tm_sf.reset( new SpriteFactory() );\r\n\t\r\n\t#pragma region initStuff\r\n\tDB::select( \"Value_\", \"Time\", \"MillisecondsSlow\" );\r\n\r\n\tm_millisecondsSlow = DB::select( \"Value_\", \"Time\", \"MillisecondsSlow\" ).toInt();\r\n\tm_millisecondsFast = DB::select( \"Value_\", \"Time\", \"MillisecondsFast\" ).toInt();\r\n\r\n\tGameState::tick = 1;\r\n\tGameState::hour = 9;\r\n\tGameState::minute = 0;\r\n\tGameState::day    = 1;\r\n\tGameState::season = 0; // zero based, 0-numSeasons, typically 4 can be modded\r\n\tGameState::year   = 1;\r\n\r\n\tQString dt = QString( \"Day %1, %2:%3\" ).arg( GameState::day, 2, 10, QChar( ' ' ) ).arg( GameState::hour, 2, 10, QChar( '0' ) ).arg( GameState::minute, 2, 10, QChar( '0' ) );\r\n\tGameState::currentDayTime = dt;\r\n\tGameState::seasonString = \"Spring\";\r\n\tGameState::currentYearAndSeason = \"Year \" + QString::number( GameState::year ) + \", \" + S::s( \"$SeasonName_\" + GameState::seasonString );\r\n\r\n\tcalcDaylight();\r\n\tGameState::daylight = true;\r\n\r\n\tfor( auto t : DB::ids( \"Tech\" ) )\r\n\t{\r\n\t\tGameState::techs.insert( t, 1 );\r\n\t}\r\n#pragma endregion\r\n\tm_inv   \t\t\t= new Inventory( this );\r\n\t\r\n\tm_spm\t\t\t\t= new StockpileManager( this );\r\n\tm_farmingManager\t= new FarmingManager( this );\r\n\tm_workshopManager\t= new WorkshopManager( this );\r\n\tm_roomManager\t\t= new RoomManager( this );\r\n\r\n\tm_jobManager\t\t= new JobManager( this );\r\n\t\r\n\tm_creatureManager\t= new CreatureManager( this );\r\n\tm_gnomeManager\t\t= new GnomeManager( this );\r\n\tm_militaryManager\t= new MilitaryManager( this );\r\n\r\n\tm_mechanismManager\t= new MechanismManager( this );\r\n\tm_fluidManager\t\t= new FluidManager( this );\r\n\t\r\n\tm_neighborManager\t= new NeighborManager( this );\r\n\tm_eventManager\t\t= new EventManager( this );\r\n\t\r\n\tm_soundManager\t= new SoundManager( this );\r\n\r\n\tqDebug() << \"init game done\";\r\n}\r\n\r\n\r\nGame::~Game()\r\n{\r\n}\r\n\r\nvoid Game::generateWorld( NewGameSettings* ngs )\r\n{\r\n\tm_inv->loadFilter();\r\n\r\n\tWorldGenerator wg( ngs, this );\r\n\tconnect( &wg, &WorldGenerator::signalStatus, dynamic_cast<GameManager*>( parent() ), &GameManager::onGeneratorMessage );\r\n\tm_world.reset( wg.generateTopology() );\t\r\n\twg.addLife();\r\n\r\n\tm_pf.reset( new PathFinder( m_world.get(), this ) );\r\n}\r\n\r\nvoid Game::setWorld( int dimX, int dimY, int dimZ )\r\n{\r\n\tm_world.reset( new World( dimX, dimY, dimZ, this ) );\r\n\tm_pf.reset( new PathFinder( m_world.get(), this ) );\r\n}\r\n\r\nvoid Game::start()\r\n{\r\n\tqDebug() << \"Starting game\";\r\n\r\n\tif ( GameState::tick == 0 && !GameState::initialSave )\r\n\t{\r\n\t\tGlobal::cfg->set( \"DaysToNextAutoSave\", 0 );\r\n\t\tautoSave();\r\n\t\tGlobal::cfg->set( \"Pause\", true );\r\n\t\temit signalPause( true );\r\n\t}\r\n\r\n\tif ( m_timer )\r\n\t{\r\n\t\tstop();\r\n\t}\r\n\tm_timer = new QTimer( this );\r\n\tconnect( m_timer, &QTimer::timeout, this, &Game::loop );\r\n\tm_timer->start( m_millisecondsSlow );\r\n}\r\n\r\nvoid Game::stop()\r\n{\r\n\tqDebug() << \"Stop game\";\r\n\tif ( m_timer )\r\n\t{\r\n\t\tm_timer->stop();\r\n\t\tdelete m_timer;\r\n\t}\r\n}\r\n\r\nvoid Game::loop()\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tif (m_guiHeartbeat <= m_guiHeartbeatResponse+20)\r\n\t{\r\n\t\tm_upsCounter1++;\r\n\t\tif ( m_upsTimer.elapsed() > 1000 ) \r\n\t\t{\r\n\t\t\tm_upsTimer.restart();\r\n\t\t\t//printf(\" gameloop ups %d avg ms %d\\n\", m_upsCounter1, m_avgLoopTime/m_upsCounter1);\r\n\t\t\tm_upsCounter = m_upsCounter1;\r\n\t\t\tm_upsCounter1 = 0;\r\n\t\t\tm_avgLoopTime = 0;\r\n\t\t}\r\n\t\tint ms2 = 0;\r\n\t\t\r\n\t\tif ( !m_paused )\r\n\t\t{\r\n\t\t\t\r\n\t\t\t\r\n\t\t\temit sendOverlayMessage( 6, \"tick \" + QString::number( GameState::tick ) );\r\n\t\t\t//printf(\"   game tick %d\\n\",GameState::tick );\r\n\t\t\t\r\n\t\t\tsendClock();\r\n\r\n\t\t\t// process grass\r\n\t\t\tm_world->processGrass();\r\n\t\t\t// process plants\r\n\t\t\tprocessPlants();\r\n\r\n\t\t\t// process animals\r\n\r\n\t\t\tm_creatureManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\r\n\t\t\t// process gnomes\r\n\t\t\tQElapsedTimer timer2;\r\n\t\t\ttimer2.start();\r\n\t\t\tm_gnomeManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\t\t\tms2 = timer2.elapsed();\r\n\t\t\t// process jobs\r\n\t\t\tm_jobManager->onTick();\r\n\t\t\t// process stockpiles\r\n\t\t\tm_spm->onTick( GameState::tick );\r\n\t\t\tm_farmingManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\t\t\tm_workshopManager->onTick( GameState::tick );\r\n\t\t\tm_roomManager->onTick( GameState::tick );\r\n\t\t\tm_inv->itemHistory()->onTick( GameState::dayChanged );\r\n\t\t\tm_eventManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\t\t\tm_mechanismManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\t\t\tm_fluidManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\t\t\tm_neighborManager->onTick( GameState::tick, GameState::seasonChanged, GameState::dayChanged, GameState::hourChanged, GameState::minuteChanged );\r\n\r\n\t\t\tm_soundManager->onTick( GameState::tick );\r\n\t\t\t\r\n\t\t\tm_world->processWater();\r\n\r\n\t\t\tm_pf->findPaths();\r\n\r\n\t\t\t++GameState::tick;\r\n\t\t}\r\n\r\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\t\t//\r\n\t\t// update gui\r\n\t\t//\r\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\t\r\n\t\tauto updates = m_world->updatedTiles();\r\n\t\tif ( !updates.empty() )\r\n\t\t{\r\n\t\t\tsignalUpdateTileInfo( std::move( updates ) );\r\n\t\t}\r\n\t\temit signalUpdateStockpile();\r\n\t\r\n\t\tGlobal::eventConnector->aggregatorCreatureInfo()->update();\r\n\t\r\n\t\tint ms        = timer.elapsed();\r\n\t\tm_maxLoopTime = qMax( ms2, m_maxLoopTime );\r\n\t\r\n\t\tauto numString = QString::number( ms );\r\n\t\twhile ( numString.size() < 5 )\r\n\t\t\tnumString.prepend( '0' );\r\n\t\r\n\t\tQString msg = \"game loop time: \" + numString;\r\n\t\tif ( Global::debugMode )\r\n\t\t\tmsg += \" ms (max gnome time:\" + QString::number( m_maxLoopTime ) + \"ms)\";\r\n\t\temit sendOverlayMessage( 3, msg );\r\n\t\r\n\t\t\r\n\t\temit signalKingdomInfo( GameState::kingdomName, \r\n\t\t\t\"Gnomes: \" + QString::number( gm()->numGnomes() ), \r\n\t\t\t\"Animals: \" + QString::number( fm()->countAnimals() ),\r\n\t\t\t\"Items: \"  + QString::number( inv()->numItems() ) );\r\n\r\n\t\tm_guiHeartbeat = m_guiHeartbeat + 1;\r\n\t\temit signalHeartbeat(m_guiHeartbeat);\r\n\t}\r\n\r\n\t\r\n\tm_avgLoopTime += timer.elapsed();\r\n\t\r\n}\r\n\r\nvoid Game::sendClock()\r\n{\r\n\tGameState::minuteChanged = false;\r\n\tGameState::hourChanged   = false;\r\n\tGameState::dayChanged    = false;\r\n\tGameState::seasonChanged = false;\r\n\r\n\tif ( GameState::tick % Global::util->ticksPerMinute == 0 )\r\n\t{\r\n\t\t++GameState::minute;\r\n\t\tGameState::minuteChanged = true;\r\n\t}\r\n\tif ( GameState::minute == Global::util->minutesPerHour )\r\n\t{\r\n\t\tGameState::minute = 0;\r\n\t\t++GameState::hour;\r\n\t\tGameState::hourChanged = true;\r\n\t}\r\n\tif ( GameState::hour == Global::util->hoursPerDay )\r\n\t{\r\n\t\tGameState::hour = 0;\r\n\t\t++GameState::day;\r\n\t\tGameState::dayChanged = true;\r\n\t}\r\n\r\n\tif ( GameState::dayChanged )\r\n\t{\r\n\t\tint daysThisSeason = DB::select( \"NumDays\", \"Seasons\", GameState::seasonString ).toInt();\r\n\t\tif ( GameState::day > daysThisSeason )\r\n\t\t{\r\n\t\t\tGameState::day = 1;\r\n\t\t\t++GameState::season;\r\n\t\t\tGameState::seasonChanged    = true;\r\n\t\t\tQString nextSeason = DB::select( \"NextSeason\", \"Seasons\", GameState::seasonString ).toString();\r\n\t\t\t//qDebug() << \"Now it's \" << nextSeason;\r\n\t\t\tGameState::seasonString = nextSeason;\r\n\r\n\t\t\tGlobal::util->daysPerSeason = DB::select( \"NumDays\", \"Seasons\", nextSeason ).toInt();\r\n\r\n\t\t\tint numSeasonsPerYear = DB::numRows( \"Seasons\" );\r\n\t\t\tif ( GameState::season == numSeasonsPerYear )\r\n\t\t\t{\r\n\t\t\t\tGameState::season = 0;\r\n\t\t\t\t++GameState::year;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcalcDaylight();\r\n\r\n\t\tautoSave();\r\n\t}\r\n\tif ( GameState::seasonChanged )\r\n\t{\r\n\t\tauto gm = dynamic_cast<GameManager*>( parent() );\r\n\t\tm_sf->forceUpdate();\r\n\t}\r\n\r\n\tQString sunStatus;\r\n\tint currentTimeInt = GameState::hour * Global::util->minutesPerHour + GameState::minute;\r\n\tif ( currentTimeInt < GameState::sunrise )\r\n\t{\r\n\t\t//time between midnight and sunrise\r\n\t\tsunStatus        = \"Sunrise: \" + intToTime( GameState::sunrise );\r\n\t\tGameState::daylight = false;\r\n\t}\r\n\telse if ( currentTimeInt < GameState::sunset )\r\n\t{\r\n\t\t// day time\r\n\t\tsunStatus        = \"Sunset: \" + intToTime( GameState::sunset );\r\n\t\tGameState::daylight = true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// time after sunset\r\n\t\tsunStatus        = \"Sunrise: \" + intToTime( GameState::nextSunrise );\r\n\t\tGameState::daylight = false;\r\n\t}\r\n\tQString dt = QString( \"Day %1, %2:%3\" ).arg( GameState::day, 2, 10, QChar( ' ' ) ).arg( GameState::hour, 2, 10, QChar( '0' ) ).arg( GameState::minute, 2, 10, QChar( '0' ) );\r\n\tGameState::currentDayTime = dt;\r\n\tGameState::currentYearAndSeason = \"Year \" + QString::number( GameState::year ) + \", \" + S::s( \"$SeasonName_\" + GameState::seasonString );\r\n\temit signalTimeAndDate( GameState::minute, GameState::hour, GameState::day, S::s( \"$SeasonName_\" + GameState::seasonString ), GameState::year, sunStatus );\r\n}\r\n\r\nvoid Game::sendTime()\r\n{\r\n\temit signalTimeAndDate( GameState::minute, GameState::hour, GameState::day, S::s( \"$SeasonName_\" + GameState::seasonString ), GameState::year, \"\" );\r\n}\r\n\r\nvoid Game::calcDaylight()\r\n{\r\n\tQString currentSeason = GameState::seasonString;\r\n\tQString sunrise       = DB::select( \"SunRiseFirst\", \"Seasons\", currentSeason ).toString();\r\n\tQString sunset        = DB::select( \"SunSetFirst\", \"Seasons\", currentSeason ).toString();\r\n\tQString nextSeason    = DB::select( \"NextSeason\", \"Seasons\", currentSeason ).toString();\r\n\r\n\tQString nextSunrise = DB::select( \"SunRiseFirst\", \"Seasons\", nextSeason ).toString();\r\n\tQString nextSunset  = DB::select( \"SunSetFirst\", \"Seasons\", nextSeason ).toString();\r\n\r\n\tint numDays = DB::select( \"NumDays\", \"Seasons\", currentSeason ).toInt();\r\n\r\n\tint sr1 = timeToInt( sunrise );\r\n\tint sr2 = timeToInt( nextSunrise );\r\n\tint ss1 = timeToInt( sunset );\r\n\tint ss2 = timeToInt( nextSunset );\r\n\r\n\tGameState::sunrise     = sr1 + ( ( sr2 - sr1 ) / numDays ) * ( GameState::day - 1 );\r\n\tGameState::nextSunrise = sr1 + ( ( sr2 - sr1 ) / numDays ) * ( GameState::day );\r\n\tGameState::sunset      = ss1 + ( ( ss2 - ss1 ) / numDays ) * ( GameState::day - 1 );\r\n\r\n\t//qDebug() << \"sunrise: \" << intToTime( m_sunrise ) << \" sunset:\" << intToTime( m_sunset );\r\n}\r\n\r\nint Game::timeToInt( QString time )\r\n{\r\n\tQStringList tl = time.split( \":\" );\r\n\treturn tl[0].toInt() * Global::util->minutesPerHour + tl[1].toInt();\r\n}\r\n\r\nQString Game::intToTime( int time )\r\n{\r\n\tint hour    = time / Global::util->minutesPerHour;\r\n\tint minute  = time - ( hour * Global::util->minutesPerHour );\r\n\tQString out = \"\";\r\n\tif ( hour < 10 )\r\n\t\tout += \"0\";\r\n\tout += QString::number( hour );\r\n\tout += \":\";\r\n\tif ( minute < 10 )\r\n\t\tout += \"0\";\r\n\tout += QString::number( minute );\r\n\treturn out;\r\n}\r\n\r\nvoid Game::processPlants()\r\n{\r\n\tQList<Position> toRemove;\r\n\tfor ( auto& p : m_world->plants() )\r\n\t{\r\n\t\tswitch ( p.onTick( GameState::tick, GameState::dayChanged, GameState::seasonChanged ) )\r\n\t\t{\r\n\t\t\tcase OnTickReturn::DESTROY:\r\n\t\t\t\ttoRemove.push_back( p.getPos() );\r\n\t\t\t\tbreak;\r\n\t\t\tcase OnTickReturn::UPDATE:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tfor ( auto p : toRemove )\r\n\t{\r\n\t\tm_world->removePlant( p );\r\n\t}\r\n}\r\n\r\nvoid Game::autoSave()\r\n{\r\n\tint daysToNext = Global::cfg->get( \"DaysToNextAutoSave\" ).toInt();\r\n\r\n\tif ( daysToNext == 0 )\r\n\t{\r\n\t\tGlobal::cfg->set( \"Pause\", true );\r\n\t\temit signalStartAutoSave();\r\n\t\temit signalPause( true );\r\n\t\tIO io( this, this );\r\n\t\tio.save( true );\r\n\t\temit signalEndAutoSave();\r\n\r\n\t\tif ( Global::cfg->get( \"AutoSaveContinue\" ).toBool() )\r\n\t\t{\r\n\t\t\temit signalPause( false );\r\n\t\t\tGlobal::cfg->set( \"Pause\", false );\r\n\t\t}\r\n\r\n\t\tGlobal::cfg->set( \"DaysToNextAutoSave\", Global::cfg->get( \"AutoSaveInterval\" ).toInt() - 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t--daysToNext;\r\n\t\tGlobal::cfg->set( \"DaysToNextAutoSave\", daysToNext );\r\n\t}\r\n}\r\n\r\nvoid Game::save()\r\n{\r\n\tGlobal::cfg->set( \"Pause\", true );\r\n\temit signalStartAutoSave();\r\n\temit signalPause( true );\r\n\tIO io( this, this );\r\n\tio.save( true );\r\n\temit signalEndAutoSave();\r\n\r\n\tif ( Global::cfg->get( \"AutoSaveContinue\" ).toBool() )\r\n\t{\r\n\t\temit signalPause( false );\r\n\t\tGlobal::cfg->set( \"Pause\", false );\r\n\t}\r\n}\r\n\r\n\t\r\nGameSpeed Game::gameSpeed()\r\n{\r\n\treturn m_gameSpeed;\r\n}\r\n\r\nvoid Game::setGameSpeed( GameSpeed speed )\r\n{\r\n\tm_gameSpeed = speed;\r\n\tswitch( m_gameSpeed )\r\n\t{\r\n\t\tcase GameSpeed::Normal:\r\n\t\t\tm_timer->setInterval( m_millisecondsSlow );\r\n\t\t\tbreak;\r\n\t\tcase GameSpeed::Fast:\r\n\t\t\tm_timer->setInterval( m_millisecondsFast );\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nbool Game::paused()\r\n{\r\n\treturn m_paused;\r\n}\r\n\r\nvoid Game::setPaused( bool value )\r\n{\r\n\tm_paused = value;\r\n\tif (m_paused) \r\n\t{\r\n\t\tm_timer->setInterval( m_millisecondsSlow*2 );\r\n\t}\r\n\telse {\r\n\t\tswitch( m_gameSpeed )\r\n\t\t{\r\n\t\t\tcase GameSpeed::Normal:\r\n\t\t\t\tm_timer->setInterval( m_millisecondsSlow );\r\n\t\t\t\tbreak;\r\n\t\t\tcase GameSpeed::Fast:\r\n\t\t\t\tm_timer->setInterval( m_millisecondsFast );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n}\r\nvoid Game::setHeartbeatResponse( int value )\r\n{\r\n\t//printf(\"heartbeatresponse %d\", value);\r\n\tm_guiHeartbeatResponse = value;\r\n}\r\n\r\nInventory*\t\t\tGame::inv(){ return m_inv; }\r\nItemHistory*\t\tGame::ih(){ return m_inv->itemHistory(); }\r\nJobManager*\t\t\tGame::jm(){ return m_jobManager; }\r\nStockpileManager*\tGame::spm(){ return m_spm; }\r\nFarmingManager*\t\tGame::fm(){ return m_farmingManager; }\r\nWorkshopManager*\tGame::wsm(){ return m_workshopManager; }\r\nWorld*\t\t\t\tGame::w(){ return m_world.get(); }\r\nSpriteFactory*\t\tGame::sf(){ return m_sf.get(); }\r\nRoomManager*\t\tGame::rm(){ return m_roomManager; }\r\nGnomeManager*\t\tGame::gm(){ return m_gnomeManager; }\r\nCreatureManager*\tGame::cm(){ return m_creatureManager; }\r\nEventManager*\t\tGame::em(){ return m_eventManager; }\r\nMechanismManager*\tGame::mcm(){ return m_mechanismManager; }\r\nFluidManager*\t\tGame::flm(){ return m_fluidManager; }\r\nNeighborManager*\tGame::nm(){ return m_neighborManager; }\r\nMilitaryManager*\tGame::mil(){ return m_militaryManager; }\r\nSoundManager*\t\tGame::sm(){ return m_soundManager; }\r\nPathFinder*\t\t\tGame::pf(){ return m_pf.get(); }\r\nWorld*\t\t\t\tGame::world() { return m_world.get(); }\r\n"
  },
  {
    "path": "src/game/game.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef GAME_H_\r\n#define GAME_H_\r\n\r\n#include \"../base/enums.h\"\r\n\r\n#include <QObject>\r\n\r\nclass Config;\r\nclass NewGameSettings;\r\n\r\nclass QTimer;\r\n\r\nclass Inventory;\r\nclass ItemHistory;\r\nclass JobManager;\r\nclass StockpileManager;\r\nclass FarmingManager;\r\nclass WorkshopManager;\r\nclass RoomManager;\r\nclass GnomeManager;\r\nclass CreatureManager;\r\nclass EventManager;\r\nclass MechanismManager;\r\nclass FluidManager;\r\nclass NeighborManager;\r\nclass MilitaryManager;\r\nclass SoundManager;\r\n\r\nclass PathFinder;\r\nclass SpriteFactory;\r\nclass World;\r\n\r\nclass Game : public QObject\r\n{\r\n\tfriend class Inventory;\r\n\tfriend class SpriteFactory;\r\n\tfriend class World;\r\n\r\n\tfriend class JobManager;\r\n\tfriend class StockpileManager;\r\n\tfriend class FarmingManager;\r\n\tfriend class WorkshopManager;\r\n\tfriend class RoomManager;\r\n\tfriend class GnomeManager;\r\n\tfriend class CreatureManager;\r\n\tfriend class EventManager;\r\n\tfriend class MechanismManager;\r\n\tfriend class FluidManager;\r\n\tfriend class NeighborManager;\r\n\tfriend class MilitaryManager;\r\n\tfriend class SoundManager;\r\n\r\n\tfriend class Gnome;\r\n\tfriend class GnomeTrader;\r\n\tfriend class Automaton;\r\n\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( Game )\r\npublic:\r\n\tGame( QObject* parent );\r\n\tGame() = delete;\r\n\tvirtual ~Game();\r\n\r\n\tvoid save();\r\n\r\n\tGameSpeed gameSpeed();\r\n\tvoid setGameSpeed( GameSpeed speed );\r\n\r\n\tbool paused();\r\n\tvoid setPaused( bool value );\r\n\tvoid setHeartbeatResponse( int value );\r\n\r\n\tvoid generateWorld( NewGameSettings* ngs );\r\n\tvoid setWorld( int dimX, int dimY, int dimZ );\r\n\tWorld* world();\r\n\r\n\tInventory* inv();\r\n\tItemHistory* ih();\r\n\tJobManager* jm();\r\n\tStockpileManager* spm();\r\n\tFarmingManager* fm();\r\n\tWorkshopManager* wsm();\r\n\tWorld* w();\r\n\tSpriteFactory* sf();\r\n\tRoomManager* rm();\r\n\tGnomeManager* gm();\r\n\tCreatureManager* cm();\r\n\tEventManager* em();\r\n\tMechanismManager* mcm();\r\n\tFluidManager* flm();\r\n\tNeighborManager* nm();\r\n\tMilitaryManager* mil();\r\n\tPathFinder* pf();\r\n\tSoundManager* sm();\r\n\r\nprivate:\r\n\tQScopedPointer<World> m_world;\r\n\tQScopedPointer<SpriteFactory> m_sf;\r\n\tQScopedPointer<PathFinder> m_pf;\r\n\r\n\tQPointer<QTimer> m_timer;\r\n\t\r\n\tQElapsedTimer m_upsTimer;\r\n\tint m_upsCounter;\r\n\tint m_upsCounter1;\r\n\tint m_avgLoopTime;\r\n\r\n\tint m_millisecondsSlow = 50;\r\n\tint m_millisecondsFast = 5;\r\n\r\n\tint m_maxLoopTime = 0;\r\n\tint m_guiHeartbeat = 0;\r\n\tint m_guiHeartbeatResponse = 0;\r\n\r\n\tvoid processPlants();\r\n\r\n\tvoid sendClock();\r\n\tvoid calcDaylight();\r\n\tint timeToInt( QString time );\r\n\tQString intToTime( int time );\r\n\r\n\tvoid autoSave();\r\n\r\n\tbool m_paused         = true;\r\n\tGameSpeed m_gameSpeed = GameSpeed::Normal;\r\n\r\n\tQPointer<Inventory> m_inv;\r\n\r\n\tQPointer<JobManager> m_jobManager;\r\n\tQPointer<StockpileManager> m_spm;\r\n\tQPointer<FarmingManager> m_farmingManager;\r\n\tQPointer<WorkshopManager> m_workshopManager;\r\n\tQPointer<RoomManager> m_roomManager;\r\n\tQPointer<GnomeManager> m_gnomeManager;\r\n\tQPointer<CreatureManager> m_creatureManager;\r\n\tQPointer<EventManager> m_eventManager;\r\n\tQPointer<MechanismManager> m_mechanismManager;\r\n\tQPointer<FluidManager> m_fluidManager;\r\n\tQPointer<NeighborManager> m_neighborManager;\r\n\tQPointer<MilitaryManager> m_militaryManager;\r\n\tQPointer<SoundManager> m_soundManager;\r\n\r\npublic slots:\r\n\tvoid loop();\r\n\tvoid start();\r\n\tvoid stop();\r\n\tvoid sendTime();\r\n\r\nsignals:\r\n\tvoid sendOverlayMessage( int id, QString text );\r\n\tvoid signalTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus );\r\n\tvoid signalKingdomInfo( QString name, QString info1, QString info2, QString info3 );\r\n\tvoid signalHeartbeat( int value );\r\n\tvoid signalPause( bool pause );\r\n\tvoid signalEvent( unsigned int id, QString title, QString msg, bool pause, bool yesno );\r\n\tvoid signalStartAutoSave();\r\n\tvoid signalEndAutoSave();\r\n\tvoid signalUpdateTileInfo( QSet<unsigned int> changeSet );\r\n\tvoid signalUpdateStockpile();\r\n};\r\n\r\n#endif /* GAME_H_ */\r\n"
  },
  {
    "path": "src/game/gamemanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"gamemanager.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/io.h\"\r\n#include \"../base/pathfinder.h\"\r\n#include \"../base/util.h\"\r\n#include \"../base/selection.h\"\r\n\r\n#include \"../game/game.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/newgamesettings.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/eventconnector.h\"\r\n#include \"../gui/mainwindow.h\"\r\n#include \"../gui/mainwindowrenderer.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include \"../game/inventory.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/eventmanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/fluidmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/soundmanager.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n\r\n\r\n#include \"../gui/aggregatoragri.h\"\r\n#include \"../gui/aggregatorcreatureinfo.h\"\r\n#include \"../gui/aggregatordebug.h\"\r\n#include \"../gui/aggregatorinventory.h\"\r\n#include \"../gui/aggregatorpopulation.h\"\r\n#include \"../gui/aggregatorrenderer.h\"\r\n#include \"../gui/aggregatorstockpile.h\"\r\n#include \"../gui/aggregatortileinfo.h\"\r\n#include \"../gui/aggregatorworkshop.h\"\r\n#include \"../gui/aggregatorneighbors.h\"\r\n#include \"../gui/aggregatormilitary.h\"\r\n#include \"../gui/aggregatorsettings.h\"\r\n#include \"../gui/aggregatorloadgame.h\"\r\n#include \"../gui/aggregatorselection.h\"\r\n#include \"../gui/aggregatorsound.h\"\r\n\r\n#include <QDateTime>\r\n#include <QDebug>\r\n#include <QDir>\r\n#include <QJsonDocument>\r\n#include <QStandardPaths>\r\n\r\nGameManager::GameManager( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tqRegisterMetaType<GameSpeed>();\r\n\r\n\tm_eventConnector = new EventConnector( this );\r\n\tGlobal::eventConnector = m_eventConnector;\r\n\tGlobal::util = new Util( nullptr );\r\n\r\n\tGlobal::newGameSettings = new NewGameSettings( this );\r\n\r\n\tGameState::init();\r\n\r\n}\r\n\r\nGameManager::~GameManager()\r\n{\r\n\tif ( m_game )\r\n\t{\r\n\t\tdelete m_game;\r\n\t}\r\n}\r\n\r\nEventConnector* GameManager::eventConnector()\r\n{\r\n\treturn m_eventConnector;\r\n}\r\n\r\nvoid GameManager::setShowMainMenu( bool value )\r\n{\r\n\tm_eventConnector->emitPause( true );\r\n\tm_eventConnector->emitInMenu( value );\r\n\t\r\n\tif( m_game )\r\n\t{\r\n\t\tm_game->setPaused( true );\r\n\t}\r\n}\r\n\r\nvoid GameManager::endCurrentGame()\r\n{\r\n\tm_eventConnector->emitStopGame();\r\n\r\n\tif ( m_game )\r\n\t{\r\n\t\tdelete m_game;\r\n\t\tGlobal::sel = nullptr;\r\n\t\tGlobal::util = new Util( nullptr );\r\n\t}\r\n}\r\n\r\nvoid GameManager::startNewGame()\r\n{\r\n\tqDebug() << \"GameManger: New game\";\r\n\r\n\t// create new random kingdom name\r\n\r\n\t// save current settings for fast create new game\r\n\tGlobal::newGameSettings->save();\r\n\t\r\n\t// check if folder exists, set new save folder name if yes\r\n\tcreateNewGame();\r\n\t\r\n\tm_eventConnector->sendResume();\r\n}\r\n\r\nvoid GameManager::setUpNewGame()\r\n{\r\n\t// check if folder exists, set new save folder name if yes\r\n}\r\n\r\nvoid GameManager::continueLastGame()\r\n{\r\n\t//get last save\r\n\tQString folder = IO::getDataFolder() + \"/save/\";\r\n\r\n\tQDir dir( folder );\r\n\tdir.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );\r\n\tdir.setSorting( QDir::Time );\r\n\tif ( !dir.entryList().isEmpty() )\r\n\t{\r\n\t\tauto kingdomDir = dir.entryList().first();\r\n\r\n\t\tfolder = IO::getDataFolder() + \"/save/\" + kingdomDir + \"/\";\r\n\t\tQDir dir2( folder );\r\n\t\tdir2.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );\r\n\t\tdir2.setSorting( QDir::Time );\r\n\t\tif ( !dir2.entryList().isEmpty() )\r\n\t\t{\r\n\t\t\tauto gameDir = dir2.entryList().first();\r\n\r\n\t\t\tif ( IO::saveCompatible( folder + gameDir + \"/\" ) )\r\n\t\t\t{\r\n\t\t\t\tloadGame( folder + gameDir + \"/\" );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_eventConnector->sendLoadGameDone( false );\r\n}\r\n\r\nvoid GameManager::init()\r\n{\r\n\tm_eventConnector->emitStopGame();\r\n\r\n\tif ( m_game )\r\n\t{\r\n\t\tdelete m_game;\r\n\t}\r\n\t// reset everything and initialize components;\r\n\tGlobal::reset();\r\n\t\r\n\tGameState::init();\r\n\r\n\tif ( !S::gi().init() )\r\n\t{\r\n\t\tqDebug() << \"Failed to init translation.\";\r\n\t\tabort();\r\n\t}\r\n}\r\n\r\nvoid GameManager::loadGame( QString folder )\r\n{\r\n\tinit();\r\n\t\r\n\tm_game = new Game( this );\r\n\tm_eventConnector->setGamePtr( m_game );\r\n\r\n\tIO io( m_game, this) ;\r\n\tconnect( &io, &IO::signalStatus, this, &GameManager::onGeneratorMessage );\r\n\tif ( io.load( folder ) )\r\n\t{\r\n\t\tGlobal::util = new Util( m_game );\r\n\t\tGlobal::sel = new Selection( m_game );\r\n\r\n\t\tpostCreationInit();\r\n\t\tm_eventConnector->sendLoadGameDone( true );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"failed to load\";\r\n\t\tm_eventConnector->sendLoadGameDone( false );\r\n\t}\r\n}\r\n\r\nvoid GameManager::createNewGame()\r\n{\r\n\tinit();\r\n\tm_game = new Game( this );\r\n\tm_eventConnector->setGamePtr( m_game );\r\n\tm_game->generateWorld( Global::newGameSettings );\r\n\t\r\n\tGlobal::util = new Util( m_game );\r\n\tGlobal::sel = new Selection( m_game );\r\n\r\n\tGameState::peaceful = Global::newGameSettings->isPeaceful();\r\n\r\n\tpostCreationInit();\r\n}\r\n\r\n\r\nvoid GameManager::postCreationInit()\r\n{\r\n\tm_game->mil()->init();\r\n\r\n\tm_eventConnector->aggregatorAgri()->init( m_game );\r\n\tm_eventConnector->aggregatorCreatureInfo()->init( m_game );\r\n\tm_eventConnector->aggregatorInventory()->init( m_game );\r\n\tm_eventConnector->aggregatorMilitary()->init( m_game );\r\n\tm_eventConnector->aggregatorNeighbors()->init( m_game );\r\n\tm_eventConnector->aggregatorPopulation()->init( m_game );\r\n\tm_eventConnector->aggregatorRenderer()->init( m_game );\r\n\tm_eventConnector->aggregatorStockpile()->init( m_game );\r\n\tm_eventConnector->aggregatorTileInfo()->init( m_game );\r\n\tm_eventConnector->aggregatorWorkshop()->init( m_game );\r\n\tm_eventConnector->aggregatorSound()->init( m_game );\r\n\r\n\tconnect( m_game->fm(), &FarmingManager::signalFarmChanged, m_eventConnector->aggregatorAgri(), &AggregatorAgri::onUpdateFarm, Qt::QueuedConnection );\r\n\tconnect( m_game->fm(), &FarmingManager::signalPastureChanged, m_eventConnector->aggregatorAgri(), &AggregatorAgri::onUpdatePasture, Qt::QueuedConnection );\r\n\tconnect( m_eventConnector->aggregatorDebug(), &AggregatorDebug::signalTriggerEvent, m_game->em(), &EventManager::onDebugEvent );\r\n\tconnect( m_game->spm(), &StockpileManager::signalStockpileAdded, m_eventConnector->aggregatorStockpile(), &AggregatorStockpile::onOpenStockpileInfo, Qt::QueuedConnection );\r\n\tconnect( m_game->spm(), &StockpileManager::signalStockpileContentChanged, m_eventConnector->aggregatorStockpile(), &AggregatorStockpile::onUpdateStockpileContent, Qt::QueuedConnection );\r\n\tconnect( m_game->wsm(), &WorkshopManager::signalJobListChanged, m_eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onCraftListChanged, Qt::QueuedConnection );\r\n\r\n\tconnect( m_game->sm(), &SoundManager::signalPlayEffect, m_eventConnector->aggregatorSound(), &AggregatorSound::onPlayEffect, Qt::QueuedConnection );\r\n\r\n\tconnect( m_game->em(), &EventManager::signalUpdateMission, m_eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::onUpdateMission, Qt::QueuedConnection );\r\n\tconnect( m_game->em(), &EventManager::signalCenterCamera, m_eventConnector->aggregatorRenderer(), &AggregatorRenderer::onCenterCamera, Qt::QueuedConnection );\r\n\r\n\tconnect( m_game->inv(), &Inventory::signalAddItem, m_eventConnector->aggregatorInventory(), &AggregatorInventory::onAddItem, Qt::QueuedConnection );\r\n\tconnect( m_game->inv(), &Inventory::signalRemoveItem, m_eventConnector->aggregatorInventory(), &AggregatorInventory::onRemoveItem, Qt::QueuedConnection );\r\n\r\n\tconnect( m_game, &Game::signalTimeAndDate, m_eventConnector, &EventConnector::onTimeAndDate );\r\n\tconnect( m_game, &Game::signalKingdomInfo, m_eventConnector, &EventConnector::onKingdomInfo );\r\n\tconnect( m_game, &Game::signalHeartbeat, m_eventConnector, &EventConnector::onHeartbeat );\r\n\r\n\t\r\n\tGlobal::util->initAllowedInContainer();\r\n\tm_eventConnector->onViewLevel( GameState::viewLevel );\r\n\tm_eventConnector->emitInMenu( false );\r\n\r\n\tconnect( m_eventConnector, &EventConnector::stopGame, m_eventConnector->aggregatorRenderer(), &AggregatorRenderer::onWorldParametersChanged );\r\n\tconnect( m_eventConnector, &EventConnector::startGame, m_game, &Game::start );\r\n\t\r\n\tconnect( m_eventConnector, &EventConnector::signalCameraPosition, m_eventConnector->aggregatorSound(), &AggregatorSound::onCameraPosition, Qt::QueuedConnection );\r\n\r\n\r\n\tqRegisterMetaType<QSet<unsigned int>>();\r\n\tconnect( m_game, &Game::signalUpdateTileInfo,  m_eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onUpdateAnyTileInfo );\r\n\tconnect( m_game, &Game::signalUpdateStockpile, m_eventConnector->aggregatorStockpile(), &AggregatorStockpile::onUpdateAfterTick );\r\n\tconnect( m_game, &Game::signalUpdateTileInfo,  m_eventConnector->aggregatorRenderer(), &AggregatorRenderer::onUpdateAnyTileInfo );\r\n\tconnect( m_game, &Game::signalTimeAndDate,     m_eventConnector, &EventConnector::onTimeAndDate );\r\n\tm_game->sendTime();\r\n\r\n\tconnect( Global::sel, &Selection::signalActionChanged, m_eventConnector->aggregatorSelection(), &AggregatorSelection::onActionChanged, Qt::QueuedConnection );\r\n\tconnect( Global::sel, &Selection::signalFirstClick, m_eventConnector->aggregatorSelection(), &AggregatorSelection::onUpdateFirstClick, Qt::QueuedConnection );\r\n\tconnect( Global::sel, &Selection::signalSize, m_eventConnector->aggregatorSelection(), &AggregatorSelection::onUpdateSize, Qt::QueuedConnection );\r\n\tGlobal::sel->updateGui();\r\n\r\n\tm_eventConnector->aggregatorInventory()->update();\r\n\r\n\tm_eventConnector->emitPause( m_game->paused() );\r\n\tm_eventConnector->emitStartGame();\r\n}\r\n\r\nvoid GameManager::onGeneratorMessage( QString message )\r\n{\r\n\tqDebug() << message;\r\n}\r\n\r\nvoid GameManager::saveGame()\r\n{\r\n\tif( m_game )\r\n\t{\r\n\t\tbool paused = m_game->paused();\r\n\t\tm_game->setPaused( true );\r\n\t\tIO io( m_game, this );\r\n\t\tio.save();\r\n\t\tm_game->setPaused( paused );\r\n\r\n\t\tm_eventConnector->sendResume();\r\n\t}\r\n}\r\n\r\nGameSpeed GameManager::gameSpeed()\r\n{\r\n\tif( m_game )\r\n\t{\r\n\t\treturn m_game->gameSpeed();\r\n\t}\r\n\treturn GameSpeed::Normal;\r\n}\r\nvoid GameManager::setGameSpeed( GameSpeed speed )\r\n{\r\n\tif( m_game )\r\n\t{\r\n\t\tif( m_game->gameSpeed() != speed )\r\n\t\t{\r\n\t\t\tm_game->setGameSpeed( speed );\r\n\t\t\tm_eventConnector->emitGameSpeed( m_game->gameSpeed() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool GameManager::paused()\r\n{\r\n\tif( m_game )\r\n\t{\r\n\t\treturn m_game->paused();\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid GameManager::setPaused( bool value )\r\n{\r\n\tif( m_game )\r\n\t{\r\n\t\tif( m_game->paused() != value )\r\n\t\t{\r\n\t\t\tm_game->setPaused( value );\r\n\t\t\tm_eventConnector->emitPause( value );\r\n\t\t}\r\n\t}\r\n}\r\nvoid GameManager::setHeartbeatResponse( int value )\r\n{\r\n\tif( m_game )\r\n\t{\r\n\t\tm_game->setHeartbeatResponse( value );\r\n\t}\r\n}\r\n\r\nGame* GameManager::game()\r\n{ \r\n\treturn m_game; \r\n}"
  },
  {
    "path": "src/game/gamemanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/enums.h\"\r\n\r\n#include <QObject>\r\n#include <QString>\r\n#include <QThread>\r\n\r\nclass Game;\r\nclass EventConnector;\r\nclass NewGameSettings;\r\nclass SpriteFactory;\r\n\r\nclass GameManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( GameManager )\r\npublic:\r\n\tGameManager( QObject* parent = nullptr );\r\n\t~GameManager();\r\n\r\n\tvoid startNewGame();\r\n\tvoid setUpNewGame();\r\n\tvoid continueLastGame();\r\n\tvoid loadGame( QString folder );\r\n\tvoid saveGame();\r\n\r\n\tvoid setShowMainMenu( bool value );\r\n\tvoid endCurrentGame();\r\n\r\n\tGameSpeed gameSpeed();\r\n\tvoid setGameSpeed( GameSpeed speed );\r\n\r\n\tbool paused();\r\n\tvoid setPaused( bool value );\r\n\t\r\n\tvoid setHeartbeatResponse( int value );\r\n\r\n\tEventConnector* eventConnector();\r\n\r\n\tGame* game();\r\n\t\r\nprivate:\r\n\tQPointer<EventConnector> m_eventConnector;\r\n\t//SpriteFactory* m_sf = nullptr;\r\n\r\n\tQPointer<Game> m_game;\r\n\t\r\n\tvoid init();\r\n\tvoid createNewGame();\r\n\r\n\tvoid postCreationInit();\r\n\t\r\nsignals:\r\n\r\npublic slots:\r\n\tvoid onGeneratorMessage( QString message );\r\n};\r\n"
  },
  {
    "path": "src/game/gnome.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"gnome.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/game.h\"\r\n\r\n#include \"../base/behaviortree/bt_tree.h\"\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../game/workshop.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QDomDocument>\r\n#include <QElapsedTimer>\r\n#include <QFile>\r\n#include <QPainter>\r\n#include <QThreadPool>\r\n\r\nGnome::Gnome( Position& pos, QString name, Gender gender, Game* game ) :\r\n\tCanWork( pos, name, gender, \"Gnome\", game )\r\n{\r\n\tm_ignoreNoPass = false;\r\n\r\n\tint shirt         = rand() % 14 + 1;\r\n\tm_equipment.shirt = \"GnomeShirt\" + QString::number( shirt );\r\n\tint hair          = rand() % 14 + 1;\r\n\tm_equipment.hair  = \"GnomeHair\" + QString::number( hair );\r\n\r\n\tauto numHairColors = DB::ids( \"HairColors\" ).size();\r\n\r\n\tm_equipment.hairColor  = rand() % numHairColors;\r\n\tm_equipment.shirtColor = rand() % 6;\r\n\r\n\tint fhair = rand() % 15;\r\n\tif ( m_gender == Gender::MALE )\r\n\t{\r\n\t\tm_equipment.facialHair = \"GnomeFacialHair\" + QString::number( fhair );\r\n\t}\r\n\r\n\tm_type = CreatureType::GNOME;\r\n\r\n\tm_anatomy.init( \"Humanoid\", false );\r\n\r\n\tfor ( int i = 0; i < 24; ++i )\r\n\t{\r\n\t\tm_schedule.append( ScheduleActivity::None );\r\n\t}\r\n\r\n\tlog( GameState::currentYearAndSeason );\r\n}\r\n\r\nGnome::Gnome( QVariantMap& in, Game* game ) :\r\n\tCanWork( in, game )\r\n{\r\n\tm_skillActive     = in.value( \"SkillActive\" ).toMap();\r\n\tm_skillPriorities = in.value( \"SkillPriorities\" ).toStringList();\r\n\r\n\tm_needs = in.value( \"Needs\" ).toMap();\r\n\r\n\tif ( in.contains( \"Profession\" ) )\r\n\t{\r\n\t\tm_profession = in.value( \"Profession\" ).toString();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_profession = \"Gnomad\";\r\n\t}\r\n\r\n\tm_equipment = in.value( \"Equipment\" ).toMap();\r\n\r\n\tif ( in.contains( \"Schedule\" ) )\r\n\t{\r\n\t\tauto list = in.value( \"Schedule\" ).toList();\r\n\t\tm_schedule.clear();\r\n\t\tfor( auto vs : list )\r\n\t\t{\r\n\t\t\tauto ss = vs.toString();\r\n\t\t\tScheduleActivity sa = ScheduleActivity::None;\r\n\t\t\tif ( ss == \"eat\" ) sa = ScheduleActivity::Eat;\r\n\t\t\telse if ( ss == \"sleep\" ) sa = ScheduleActivity::Sleep;\r\n\t\t\telse if ( ss == \"train\" ) sa = ScheduleActivity::Training;\r\n\r\n\t\t\tm_schedule.append( sa );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor ( int i = 0; i < 24; ++i )\r\n\t\t{\r\n\t\t\tm_schedule.append( ScheduleActivity::None );\r\n\t\t}\r\n\t}\r\n\r\n\tm_carryBandages = in.value( \"CarryBandages\" ).toBool();\r\n\tm_carryFood     = in.value( \"CarryFood\" ).toBool();\r\n\tm_carryDrinks   = in.value( \"CarryDrinks\" ).toBool();\r\n\r\n\t// TODO update carried counts from inventory\r\n\tfor ( auto item : m_inventoryItems )\r\n\t{\r\n\t\tif ( g->inv()->itemSID( item ) == \"Bandage\" )\r\n\t\t{\r\n\t\t\t++m_carriedBandages;\r\n\t\t}\r\n\t\telse if ( g->inv()->nutritionalValue( item ) > 0 )\r\n\t\t{\r\n\t\t\t++m_carriedFood;\r\n\t\t}\r\n\t\telse if ( g->inv()->drinkValue( item ) > 0 )\r\n\t\t{\r\n\t\t\t++m_carriedDrinks;\r\n\t\t}\r\n\t}\r\n\r\n\tm_leftHandAttackSkill  = getSkillLevel( \"Unarmed\" );\r\n\tm_leftHandAttackValue  = m_leftHandAttackSkill;\r\n\tm_rightHandAttackSkill = getSkillLevel( \"Unarmed\" );\r\n\tm_rightHandAttackValue = m_rightHandAttackSkill;\r\n\r\n\tlog( GameState::currentYearAndSeason );\r\n}\r\n\r\nvoid Gnome::serialize( QVariantMap& out )\r\n{\r\n\tCanWork::serialize( out );\r\n\t////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\t////////////////////////////////////////////////////////////////////////////////////\r\n\r\n\tout.insert( \"SkillActive\", m_skillActive );\r\n\tout.insert( \"SkillPriorities\", m_skillPriorities );\r\n\t//basic needs\r\n\tout.insert( \"Needs\", m_needs );\r\n\tout.insert( \"Equipment\", m_equipment.serialize() );\r\n\r\n\tout.insert( \"Profession\", m_profession );\r\n\r\n\t\r\n\r\n\tQVariantList vSchedule;\r\n\tfor( const auto& sa : m_schedule )\r\n\t{\r\n\t\tswitch ( sa )\r\n\t\t{\r\n\t\t\tcase ScheduleActivity::Eat:\r\n\t\t\t\tvSchedule.append( \"eat\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase ScheduleActivity::Sleep:\r\n\t\t\t\tvSchedule.append( \"sleep\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase ScheduleActivity::Training:\r\n\t\t\t\tvSchedule.append( \"train\" );\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tvSchedule.append( \"none\" );\r\n\t\t}\r\n\t}\r\n\tout.insert( \"Schedule\", vSchedule );\r\n\r\n\tout.insert( \"CarryBandages\", m_carryBandages );\r\n\tout.insert( \"CarryFood\", m_carryFood );\r\n\tout.insert( \"CarryDrinks\", m_carryDrinks );\r\n}\r\n\r\nGnome::~Gnome()\r\n{\r\n}\r\n\r\nvoid Gnome::init()\r\n{\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\r\n\tupdateSprite();\r\n\tinitTaskMap();\r\n\tloadBehaviorTree( \"Gnome\" );\r\n\r\n\tif ( m_btBlackBoard.contains( \"State\" ) )\r\n\t{\r\n\t\tQVariantMap btm = m_btBlackBoard.value( \"State\" ).toMap();\r\n\t\tif ( m_behaviorTree )\r\n\t\t{\r\n\t\t\tm_behaviorTree->deserialize( btm );\r\n\t\t\tm_btBlackBoard.remove( \"State\" );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Gnome::setConcealed( QString part, bool concealed )\r\n{\r\n\tfor ( int k = 0; k < m_spriteDef.size(); ++k )\r\n\t{\r\n\t\tauto cm = m_spriteDef[k].toMap();\r\n\t\tif ( cm.value( \"Part\" ).toString() == part )\r\n\t\t{\r\n\t\t\tcm.insert( \"Hidden\", concealed );\r\n\t\t\tm_spriteDef.replace( k, cm );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( int k = 0; k < m_spriteDefBack.size(); ++k )\r\n\t{\r\n\t\tauto cm = m_spriteDefBack[k].toMap();\r\n\t\tif ( cm.value( \"Part\" ).toString() == part )\r\n\t\t{\r\n\t\t\tcm.insert( \"Hidden\", concealed );\r\n\t\t\tm_spriteDefBack.replace( k, cm );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Gnome::updateSprite()\r\n{\r\n\tm_spriteDef     = createSpriteDef( \"Gnome\", false );\r\n\tm_spriteDefBack = createSpriteDef( \"GnomeBack\", true );\r\n\r\n\tg->sf()->setCreatureSprite( m_id, m_spriteDef, m_spriteDefBack, isDead() );\r\n\tm_equipmentChanged = true;\r\n\tm_renderParamsChanged = true;\r\n}\r\n\r\nQVariantList Gnome::createSpriteDef( QString type, bool isBack )\r\n{\r\n\tauto parts = DB::selectRows( \"Creature_Parts\", type );\r\n\r\n\tQVariantMap ordered;\r\n\tfor ( auto pm : parts )\r\n\t{\r\n\t\tordered.insert( pm.value( \"Order\" ).toString(), pm );\r\n\t}\r\n\r\n\tUniform* uniform = nullptr;\r\n\tif ( m_roleID )\r\n\t{\r\n\t\tuniform = g->mil()->uniform( m_roleID );\r\n\t}\r\n\r\n\tQVariantList def;\r\n\tfor ( auto vpm : ordered )\r\n\t{\r\n\t\tauto pm = vpm.toMap();\r\n\r\n\t\tCreaturePart part = Global::creaturePartLookUp.value( pm.value( \"Part\" ).toString() );\r\n\r\n\t\tQString tint = pm.value( \"Tint\" ).toString();\r\n\r\n\t\tQString bs = pm.value( \"BaseSprite\" ).toString();\r\n\r\n\t\tbool hairConcealed = false;\r\n\t\tif ( m_equipment.head.itemID )\r\n\t\t{\r\n\t\t\thairConcealed = true;\r\n\t\t}\r\n\r\n\t\tunsigned int item = 0;\r\n\r\n\t\tswitch ( part )\r\n\t\t{\r\n\t\t\tcase CP_HEAD:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_TORSO:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_LEFT_ARM:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_RIGHT_ARM:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_LEFT_HAND:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_RIGHT_HAND:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_LEFT_LEG:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_RIGHT_LEG:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_LEFT_FOOT:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_RIGHT_FOOT:\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase CP_HAIR:\r\n\t\t\t\tpm.insert( \"Tint\", m_equipment.hairColor );\r\n\t\t\t\tbs = m_equipment.hair;\r\n\t\t\t\tpm.insert( \"IsHair\", true );\r\n\t\t\t\tpm.insert( \"Hidden\", hairConcealed );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_FACIAL_HAIR:\r\n\t\t\t\tpm.insert( \"Tint\", m_equipment.hairColor );\r\n\t\t\t\tbs = m_equipment.facialHair;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_CLOTHING:\r\n\t\t\t\tpm.insert( \"Tint\", m_equipment.shirtColor );\r\n\t\t\t\tbs = m_equipment.shirt;\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_BOOTS:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_HAT:\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase CP_ARMOR_HEAD:\r\n\t\t\t\tif ( m_equipment.head.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.head.itemID );\r\n\t\t\t\t\tbs += \"HeadArmor\";\r\n\t\t\t\t\thairConcealed = true;\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.head.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_TORSO:\r\n\t\t\t\tif ( m_equipment.chest.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.chest.itemID );\r\n\t\t\t\t\tbs += \"ChestArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.chest.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_LEFT_ARM:\r\n\t\t\t\tif ( m_equipment.arm.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.arm.itemID );\r\n\t\t\t\t\tbs += \"LeftArmArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.arm.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_RIGHT_ARM:\r\n\t\t\t\tif ( m_equipment.arm.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.arm.itemID );\r\n\t\t\t\t\tbs += \"RightArmArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.arm.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_LEFT_HAND:\r\n\t\t\t\tif ( m_equipment.hand.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.hand.itemID );\r\n\t\t\t\t\tbs += \"LeftHandArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.hand.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_RIGHT_HAND:\r\n\t\t\t\tif ( m_equipment.hand.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.hand.itemID );\r\n\t\t\t\t\tbs += \"RightHandArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.hand.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_LEFT_FOOT:\r\n\t\t\t\tif ( m_equipment.foot.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.foot.itemID );\r\n\t\t\t\t\tbs += \"LeftFootArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.foot.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_ARMOR_RIGHT_FOOT:\r\n\t\t\t\tif ( m_equipment.foot.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += g->inv()->itemGroup( m_equipment.foot.itemID );\r\n\t\t\t\t\tbs += \"RightFootArmor\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.foot.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_LEFT_HAND_HELD:\r\n\t\t\t\tif ( m_equipment.leftHandHeld.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += m_equipment.leftHandHeld.item;\r\n\t\t\t\t\tbs += \"Left\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.leftHandHeld.material );\r\n\t\t\t\t\tpm.insert( \"HasBase\", true );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_RIGHT_HAND_HELD:\r\n\t\t\t\tif ( m_equipment.rightHandHeld.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += m_equipment.rightHandHeld.item;\r\n\t\t\t\t\tbs += \"Right\";\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.leftHandHeld.material );\r\n\t\t\t\t\tpm.insert( \"HasBase\", true );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase CP_BACK:\r\n\t\t\t\tif ( isBack && m_equipment.back.itemID )\r\n\t\t\t\t{\r\n\t\t\t\t\tbs = \"Gnome\";\r\n\t\t\t\t\tbs += m_equipment.back.item;\r\n\t\t\t\t\tpm.insert( \"Material\", m_equipment.leftHandHeld.material );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t\r\n\r\n\t\tif ( isBack && !bs.endsWith( \"Back\" ) )\r\n\t\t{\r\n\t\t\tbs += \"Back\";\r\n\t\t}\r\n\r\n\t\tpm.insert( \"BaseSprite\", bs );\r\n\r\n\t\tdef.append( pm );\r\n\t}\r\n\treturn def;\r\n}\r\n\r\nvoid Gnome::initTaskMap()\r\n{\r\n\tusing namespace std::placeholders;\r\n\r\n\tm_behaviors.insert( \"IsSleepy\", std::bind( &Gnome::conditionIsSleepy, this, _1 ) );\r\n\tm_behaviors.insert( \"IsHungry\", std::bind( &Gnome::conditionIsHungry, this, _1 ) );\r\n\tm_behaviors.insert( \"IsVeryHungry\", std::bind( &Gnome::conditionIsVeryHungry, this, _1 ) );\r\n\tm_behaviors.insert( \"IsThirsty\", std::bind( &Gnome::conditionIsThirsty, this, _1 ) );\r\n\tm_behaviors.insert( \"IsVeryThirsty\", std::bind( &Gnome::conditionIsVeryThirsty, this, _1 ) );\r\n\tm_behaviors.insert( \"AllItemsInPlaceForJob\", std::bind( &Gnome::conditionAllItemsInPlaceForJob, this, _1 ) );\r\n\tm_behaviors.insert( \"IsButcherJobJob\", std::bind( &Gnome::conditionIsButcherJob, this, _1 ) );\r\n\tm_behaviors.insert( \"AllPickedUp\", std::bind( &Gnome::conditionAllPickedUp, this, _1 ) );\r\n\tm_behaviors.insert( \"IsFull\", std::bind( &Gnome::conditionIsFull, this, _1 ) );\r\n\tm_behaviors.insert( \"IsDrinkFull\", std::bind( &Gnome::conditionIsDrinkFull, this, _1 ) );\r\n\tm_behaviors.insert( \"IsCivilian\", std::bind( &Gnome::conditionIsCivilian, this, _1 ) );\r\n\tm_behaviors.insert( \"Alarm\", std::bind( &Gnome::conditionAlarm, this, _1 ) );\r\n\tm_behaviors.insert( \"IsInSafeRoom\", std::bind( &Gnome::conditionIsInSafeRoom, this, _1 ) );\r\n\r\n\t// combat conditions\r\n\tm_behaviors.insert( \"TargetAdjacent\", std::bind( &Gnome::conditionTargetAdjacent, this, _1 ) );\r\n\tm_behaviors.insert( \"IsInCombat\", std::bind( &Gnome::conditionIsInCombat, this, _1 ) );\r\n\tm_behaviors.insert( \"IsTrainingTime\", std::bind( &Gnome::conditionIsTrainingTime, this, _1 ) );\r\n\tm_behaviors.insert( \"IsTrainer\", std::bind( &Gnome::conditionIsTrainer, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"HasHuntTarget\", std::bind( &Gnome::conditionHasHuntTarget, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"IsOnMission\", std::bind( &Gnome::conditionIsOnMission, this, _1 ) );\r\n\r\n\t//m_behaviors.insert( \"\", std::bind( &Gnome::condition, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"Sleep\", std::bind( &Gnome::actionSleep, this, _1 ) );\r\n\tm_behaviors.insert( \"FindBed\", std::bind( &Gnome::actionFindBed, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"FindFood\", std::bind( &Gnome::actionFindFood, this, _1 ) );\r\n\tm_behaviors.insert( \"FindDining\", std::bind( &Gnome::actionFindDining, this, _1 ) );\r\n\tm_behaviors.insert( \"Eat\", std::bind( &Gnome::actionEat, this, _1 ) );\r\n\tm_behaviors.insert( \"FindDrink\", std::bind( &Gnome::actionFindDrink, this, _1 ) );\r\n\tm_behaviors.insert( \"Drink\", std::bind( &Gnome::actionDrink, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"Move\", std::bind( &Gnome::actionMove, this, _1 ) );\r\n\tm_behaviors.insert( \"RandomMove\", std::bind( &Gnome::actionRandomMove, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"PickUpItem\", std::bind( &Gnome::actionPickUpItem, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"ClaimItems\", std::bind( &Gnome::actionClaimItems, this, _1 ) );\r\n\tm_behaviors.insert( \"DropItem\", std::bind( &Gnome::actionDropItem, this, _1 ) );\r\n\tm_behaviors.insert( \"EquipTool\", std::bind( &Gnome::actionEquipTool, this, _1 ) );\r\n\tm_behaviors.insert( \"FindTool\", std::bind( &Gnome::actionFindTool, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"CheckUniform\", std::bind( &Gnome::actionCheckUniform, this, _1 ) );\r\n\tm_behaviors.insert( \"CheckBandages\", std::bind( &Gnome::actionCheckBandages, this, _1 ) );\r\n\tm_behaviors.insert( \"UniformCleanUp\", std::bind( &Gnome::actionUniformCleanUp, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"GetItemDropPosition\", std::bind( &Gnome::actionGetItemDropPosition, this, _1 ) );\r\n\tm_behaviors.insert( \"GetWorkPosition\", std::bind( &Gnome::actionGetWorkPosition, this, _1 ) );\r\n\tm_behaviors.insert( \"GetSafeRoomPosition\", std::bind( &Gnome::actionGetSafeRoomPosition, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"GetJob\", std::bind( &Gnome::actionGetJob, this, _1 ) );\r\n\tm_behaviors.insert( \"InitJob\", std::bind( &Gnome::actionInitJob, this, _1 ) );\r\n\tm_behaviors.insert( \"FinishJob\", std::bind( &Gnome::actionFinishJob, this, _1 ) );\r\n\tm_behaviors.insert( \"AbortJob\", std::bind( &Gnome::actionAbortJob, this, _1 ) );\r\n\tm_behaviors.insert( \"Work\", std::bind( &Gnome::actionWork, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"InitAnimalJob\", std::bind( &Gnome::actionInitAnimalJob, this, _1 ) );\r\n\tm_behaviors.insert( \"GrabAnimal\", std::bind( &Gnome::actionGrabAnimal, this, _1 ) );\r\n\tm_behaviors.insert( \"ReleaseAnimal\", std::bind( &Gnome::actionReleaseAnimal, this, _1 ) );\r\n\tm_behaviors.insert( \"ButcherAnimal\", std::bind( &Gnome::actionButcherAnimal, this, _1 ) );\r\n\tm_behaviors.insert( \"DyeAnimal\", std::bind( &Gnome::actionDyeAnimal, this, _1 ) );\r\n\tm_behaviors.insert( \"HarvestAnimal\", std::bind( &Gnome::actionHarvestAnimal, this, _1 ) );\r\n\tm_behaviors.insert( \"TameAnimal\", std::bind( &Gnome::actionTameAnimal, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"FinalMoveAnimal\", std::bind( &Gnome::actionFinalMoveAnimal, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"DropAllItems\", std::bind( &Gnome::actionDropAllItems, this, _1 ) );\r\n\tm_behaviors.insert( \"ReturnAlwaysRunning\", std::bind( &Gnome::actionAlwaysRunning, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"GetTarget\", std::bind( &Gnome::actionGetTarget, this, _1 ) );\r\n\tm_behaviors.insert( \"AttackTarget\", std::bind( &Gnome::actionAttackTarget, this, _1 ) );\r\n\tm_behaviors.insert( \"FindTrainingGround\", std::bind( &Gnome::actionFindTrainingGround, this, _1 ) );\r\n\tm_behaviors.insert( \"Train\", std::bind( &Gnome::actionTrain, this, _1 ) );\r\n\tm_behaviors.insert( \"FindTrainerPosition\", std::bind( &Gnome::actionFindTrainerPosition, this, _1 ) );\r\n\tm_behaviors.insert( \"SuperviseTraining\", std::bind( &Gnome::actionSuperviseTraining, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"GetExitPosition\", std::bind( &Gnome::actionGetExitPosition, this, _1 ) );\r\n\tm_behaviors.insert( \"LeaveMap\", std::bind( &Gnome::actionLeaveMap, this, _1 ) );\r\n\tm_behaviors.insert( \"EnterMap\", std::bind( &Gnome::actionEnterMap, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"DoMission\", std::bind( &Gnome::actionDoMission, this, _1 ) );\r\n\tm_behaviors.insert( \"LeaveForMission\", std::bind( &Gnome::actionLeaveForMission, this, _1 ) );\r\n\tm_behaviors.insert( \"ReturnFromMission\", std::bind( &Gnome::actionReturnFromMission, this, _1 ) );\r\n\r\n\t//m_behaviors.insert( \"\", std::bind( &Gnome::action, this, _1 ) );\r\n\r\n\tm_taskFunctions.insert( \"Deconstruct\", std::bind( &Gnome::deconstruct, this ) );\r\n\r\n\tm_taskFunctions.insert( \"MineWall\", std::bind( &Gnome::mineWall, this ) );\r\n\tm_taskFunctions.insert( \"MineFloor\", std::bind( &Gnome::mineFloor, this ) );\r\n\tm_taskFunctions.insert( \"DigHole\", std::bind( &Gnome::digHole, this ) );\r\n\tm_taskFunctions.insert( \"ExplorativeMineWall\", std::bind( &Gnome::explorativeMineWall, this ) );\r\n\tm_taskFunctions.insert( \"RemoveWall\", std::bind( &Gnome::removeWall, this ) );\r\n\tm_taskFunctions.insert( \"RemoveRamp\", std::bind( &Gnome::removeRamp, this ) );\r\n\tm_taskFunctions.insert( \"RemoveFloor\", std::bind( &Gnome::removeFloor, this ) );\r\n\r\n\tm_taskFunctions.insert( \"Construct\", std::bind( &Gnome::construct, this ) );\r\n\tm_taskFunctions.insert( \"ConstructAnimate\", std::bind( &Gnome::constructAnimate, this ) );\r\n\tm_taskFunctions.insert( \"ConstructDugStairs\", std::bind( &Gnome::constructDugStairs, this ) );\r\n\tm_taskFunctions.insert( \"ConstructDugRamp\", std::bind( &Gnome::constructDugRamp, this ) );\r\n\r\n\tm_taskFunctions.insert( \"CreateItem\", std::bind( &Gnome::createItem, this ) );\r\n\tm_taskFunctions.insert( \"PlantTree\", std::bind( &Gnome::plantTree, this ) );\r\n\tm_taskFunctions.insert( \"FellTree\", std::bind( &Gnome::fellTree, this ) );\r\n\tm_taskFunctions.insert( \"Harvest\", std::bind( &Gnome::harvest, this ) );\r\n\tm_taskFunctions.insert( \"HarvestHay\", std::bind( &Gnome::harvestHay, this ) );\r\n\tm_taskFunctions.insert( \"Plant\", std::bind( &Gnome::plant, this ) );\r\n\tm_taskFunctions.insert( \"RemovePlant\", std::bind( &Gnome::removePlant, this ) );\r\n\tm_taskFunctions.insert( \"Till\", std::bind( &Gnome::till, this ) );\r\n\tm_taskFunctions.insert( \"Craft\", std::bind( &Gnome::craft, this ) );\r\n\r\n\tm_taskFunctions.insert( \"Fish\", std::bind( &Gnome::fish, this ) );\r\n\tm_taskFunctions.insert( \"ButcherFish\", std::bind( &Gnome::butcherFish, this ) );\r\n\tm_taskFunctions.insert( \"ButcherCorpse\", std::bind( &Gnome::butcherCorpse, this ) );\r\n\tm_taskFunctions.insert( \"FillTrough\", std::bind( &Gnome::fillTrough, this ) );\r\n\r\n\tm_taskFunctions.insert( \"PrepareSpell\", std::bind( &Gnome::prepareSpell, this ) );\r\n\tm_taskFunctions.insert( \"CastSpell\", std::bind( &Gnome::castSpell, this ) );\r\n\tm_taskFunctions.insert( \"CastSpellAnimate\", std::bind( &Gnome::castSpellAnimate, this ) );\r\n\tm_taskFunctions.insert( \"FinishSpell\", std::bind( &Gnome::finishSpell, this ) );\r\n\r\n\tm_taskFunctions.insert( \"SwitchMechanism\", std::bind( &Gnome::switchMechanism, this ) );\r\n\tm_taskFunctions.insert( \"InvertMechanism\", std::bind( &Gnome::invertMechanism, this ) );\r\n\tm_taskFunctions.insert( \"Refuel\", std::bind( &Gnome::refuel, this ) );\r\n\tm_taskFunctions.insert( \"Install\", std::bind( &Gnome::install, this ) );\r\n\tm_taskFunctions.insert( \"Uninstall\", std::bind( &Gnome::uninstall, this ) );\r\n\tm_taskFunctions.insert( \"SoundAlarm\", std::bind( &Gnome::soundAlarm, this ) );\r\n\tm_taskFunctions.insert( \"EquipItem\", std::bind( &Gnome::equipItem, this ) );\r\n}\r\n\r\nvoid Gnome::addNeed( QString id, int level )\r\n{\r\n\tm_needs.insert( id, level );\r\n}\r\n\r\nint Gnome::need( QString id )\r\n{\r\n\tif ( m_needs.contains( id ) )\r\n\t{\r\n\t\treturn m_needs[id].toInt();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Gnome::selectProfession( QString profession )\r\n{\r\n\tif ( m_profession != profession )\r\n\t{\r\n\t\tm_profession = profession;\r\n\r\n\t\tclearAllSkills();\r\n\r\n\t\tm_skillPriorities = g->gm()->professionSkills( profession );\r\n\r\n\t\tfor ( auto skill : m_skillPriorities )\r\n\t\t{\r\n\t\t\tsetSkillActive( skill, true );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// returns job changed, used to signal for activiti indicator\r\nCreatureTickResult Gnome::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tprocessCooldowns( tickNumber );\r\n\r\n\tif ( !m_isOnMission )\r\n\t{\r\n\t\tevalNeeds( seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\t}\r\n\r\n\tm_jobChanged    = false;\r\n\tPosition oldPos = m_position;\r\n\r\n\tif ( checkFloor() )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::NOFLOOR;\r\n\t}\r\n\tm_anatomy.setFluidLevelonTile( g->w()->fluidLevel( m_position ) );\r\n\tif ( m_anatomy.statusChanged() )\r\n\t{\r\n\t\tauto status = m_anatomy.status();\r\n\t\tif ( status & AS_DEAD )\r\n\t\t{\r\n\t\t\tGlobal::logger().log( LogType::COMBAT, m_name + \"died. Bummer!\", m_id );\r\n\t\t\tdie();\r\n\t\t\t// TODO check for other statuses\r\n\t\t}\r\n\t}\r\n\r\n\tif ( isDead() )\r\n\t{\r\n\t\tqDebug() << m_name << \" expires \" << GameState::tick + Global::util->ticksPerDay;\r\n\t\tm_expires    = GameState::tick + Global::util->ticksPerDay * 2;\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::DEAD;\r\n\t}\r\n\r\n\tif ( m_job && ( m_job->isAborted() || m_job->isCanceled() ) )\r\n\t{\r\n\t\tqDebug() << m_job->type() << \" job is canceled\";\r\n\t\tcleanUpJob( false );\r\n\t\tm_behaviorTree->halt();\r\n\t}\r\n\r\n\tif ( !m_carryBandages && m_carriedBandages > 0 )\r\n\t{\r\n\t\twhile ( m_carriedBandages > 0 )\r\n\t\t{\r\n\t\t\tif ( m_inventoryItems.size() > 0 )\r\n\t\t\t{\r\n\t\t\t\tauto item = m_inventoryItems.takeFirst();\r\n\t\t\t\tif ( g->inv()->itemSID( item ) == \"Bandage\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setInJob( item, 0 );\r\n\t\t\t\t\tg->inv()->putDownItem( item, m_position );\r\n\t\t\t\t\t--m_carriedBandages;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_carriedItems.append( item );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_carriedBandages = 0;\r\n\t\t\t\tm_carriedFood     = 0;\r\n\t\t\t\tm_carriedDrinks   = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( !m_carryFood && m_carriedFood > 0 )\r\n\t{\r\n\t\twhile ( m_carriedFood > 0 )\r\n\t\t{\r\n\t\t\tif ( m_inventoryItems.size() > 0 )\r\n\t\t\t{\r\n\t\t\t\tauto item = m_inventoryItems.takeFirst();\r\n\t\t\t\tif ( g->inv()->nutritionalValue( item ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setInJob( item, 0 );\r\n\t\t\t\t\tg->inv()->putDownItem( item, m_position );\r\n\t\t\t\t\t--m_carriedFood;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_carriedItems.append( item );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_carriedBandages = 0;\r\n\t\t\t\tm_carriedFood     = 0;\r\n\t\t\t\tm_carriedDrinks   = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( !m_carryDrinks && m_carriedDrinks > 0 )\r\n\t{\r\n\t\twhile ( m_carriedDrinks > 0 )\r\n\t\t{\r\n\t\t\tif ( m_inventoryItems.size() > 0 )\r\n\t\t\t{\r\n\t\t\t\tauto item = m_inventoryItems.takeFirst();\r\n\t\t\t\tif ( g->inv()->drinkValue( item ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setInJob( item, 0 );\r\n\t\t\t\t\tg->inv()->putDownItem( item, m_position );\r\n\t\t\t\t\t--m_carriedDrinks;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_carriedItems.append( item );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_carriedBandages = 0;\r\n\t\t\t\tm_carriedFood     = 0;\r\n\t\t\t\tm_carriedDrinks   = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n#ifdef CHECKTIME\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tm_behaviorTree->tick();\r\n\t}\r\n\tauto elapsed = timer.elapsed();\r\n\tif ( elapsed > 100 )\r\n\t{\r\n\t\tqDebug() << m_name << \"just needed\" << elapsed << \"ms for bt tick\";\r\n\t\tGlobal::cfg->set( \"Pause\", true );\r\n\t}\r\n#else\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tif ( Global::debugMode )\r\n\t\t{\r\n\t\t\tQElapsedTimer et;\r\n\t\t\tet.start();\r\n\r\n\t\t\tm_behaviorTree->tick();\r\n\r\n\t\t\tauto ela = et.elapsed();\r\n\t\t\tif ( ela > 30 )\r\n\t\t\t{\r\n\t\t\t\tif ( m_job )\r\n\t\t\t\t{\r\n\t\t\t\t\tqDebug() << \"LOOPTIME\" << m_name << ela << \"ms\"\r\n\t\t\t\t\t\t\t << \"job:\" << m_job->type() << m_job->pos().toString();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_behaviorTree->tick();\r\n\t\t}\r\n\t}\r\n#endif\r\n\r\n\tmove( oldPos );\r\n\tupdateLight( oldPos, m_position );\r\n\r\n\tm_lastOnTick = tickNumber;\r\n\r\n\tif ( m_jobChanged )\r\n\t{\r\n\t\treturn CreatureTickResult::JOBCHANGED;\r\n\t}\r\n\treturn CreatureTickResult::OK;\r\n}\r\n\r\nvoid Gnome::die()\r\n{\r\n\tCreature::die();\r\n\tcleanUpJob( false );\r\n\tfor ( Workshop* w : g->wsm()->workshops() )\r\n\t{\r\n\t\tif ( w->assignedGnome() == id() )\r\n\t\t{\r\n\t\t\tw->assignGnome( 0 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Gnome::checkFloor()\r\n{\r\n\tFloorType ft = g->w()->floorType( m_position );\r\n\tif ( ft == FloorType::FT_NOFLOOR )\r\n\t{\r\n\t\tif ( m_job )\r\n\t\t{\r\n\t\t\tm_job->setAborted( true );\r\n\t\t}\r\n\r\n\t\tPosition oneDown( m_position.x, m_position.y, m_position.z - 1 );\r\n\t\tforceMove( oneDown );\r\n\t\tg->w()->discover( oneDown );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Gnome::setJobAborted( QString caller )\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tm_job->setAborted( true );\r\n\t\tlog( \"GnomeManager aborted my job.\" );\r\n\t}\r\n}\r\n\r\nbool Gnome::evalNeeds( bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tif ( seasonChanged )\r\n\t{\r\n\t\t//log( GameState::CurrentYearAndSeason\" ).toString() );\r\n\t}\r\n\r\n\tbool needAction        = false;\r\n\tunsigned char priority = 0;\r\n\tQString action;\r\n\tQString needKey;\r\n\r\n\tif ( minuteChanged )\r\n\t{\r\n\t\tfor ( auto need : Global::needIDs )\r\n\t\t{\r\n\t\t\t//update need values\r\n\t\t\tfloat decay  = Global::needDecays.value( need );\r\n\t\t\tfloat oldVal = m_needs[need].toFloat();\r\n\t\t\tfloat newVal = oldVal + decay;\r\n\r\n\t\t\tm_needs.insert( need, newVal );\r\n\r\n\t\t\tif ( need == \"Hunger\" || need == \"Thirst\" )\r\n\t\t\t{\r\n\t\t\t\tif ( newVal < -100 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_thoughtBubble = \"\";\r\n\t\t\t\t\tdie();\r\n\t\t\t\t\tif ( need == \"Hunger\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tlog( \"Starved to death.\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( need == \"Thirst\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tlog( \"Died from thirst.\" );\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\treturn true;\r\n}\r\n\r\nvoid Gnome::updateLight( Position oldPos, Position newPos )\r\n{\r\n#if 0\r\n\tif( oldPos == newPos )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tWorld& w = Global::w();\r\n\tint intensity = 10;\r\n\tw.putLight( oldPos, -intensity );\r\n\tw.putLight( oldPos.x - 1, oldPos.y, oldPos.z, -intensity );\r\n\tw.putLight( oldPos.x, oldPos.y - 1, oldPos.z, -intensity );\r\n\tw.putLight( oldPos.x + 1, oldPos.y, oldPos.z, -intensity );\r\n\tw.putLight( oldPos.x, oldPos.y + 1, oldPos.z, -intensity );\r\n\r\n\tw.putLight( newPos, intensity );\r\n\tw.putLight( newPos.x - 1, newPos.y, newPos.z, intensity );\r\n\tw.putLight( newPos.x, newPos.y - 1, newPos.z, intensity );\r\n\tw.putLight( newPos.x + 1, newPos.y, newPos.z, intensity );\r\n\tw.putLight( newPos.x, newPos.y + 1, newPos.z, intensity );\r\n#endif\r\n}\r\n\r\nQString Gnome::getActivity()\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\treturn m_job->requiredSkill();\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"idle\";\r\n\t}\r\n}\r\n\r\nvoid Gnome::setOwnedRoom( unsigned int id )\r\n{\r\n\tm_equipment.roomID = id;\r\n\tif ( id )\r\n\t{\r\n\t\tlog( GameState::currentDayTime + \": I got a new room.\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tlog( GameState::currentDayTime + \": They took my room away.\" );\r\n\t}\r\n}\r\n\r\nunsigned int Gnome::ownedRoom()\r\n{\r\n\treturn m_equipment.roomID;\r\n}\r\n\r\nScheduleActivity Gnome::schedule( unsigned char hour )\r\n{\r\n\tif ( hour < 24 && m_schedule.size() == 24 )\r\n\t{\r\n\t\treturn m_schedule[hour];\r\n\t}\r\n\treturn ScheduleActivity::None;\r\n}\r\n\r\nvoid Gnome::setSchedule( unsigned char hour, ScheduleActivity activity )\r\n{\r\n\tif ( hour < 24 && m_schedule.size() == 24 )\r\n\t{\r\n\t\tm_schedule[hour] = activity;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_schedule.clear();\r\n\t\tfor ( int i = 0; i < 24; ++i )\r\n\t\t{\r\n\t\t\tm_schedule.append( ScheduleActivity::None );\r\n\t\t}\r\n\t\tm_schedule[hour] = activity;\r\n\t}\r\n}\r\n\r\nvoid Gnome::updateMoveSpeed()\r\n{\r\n\tint skill   = getSkillLevel( \"Hauling\" );\r\n\tint speed   = DB::execQuery( \"SELECT Speed FROM MoveSpeed WHERE CREATURE = \\\"Gnome\\\" AND Skill = \\\"\" + QString::number( skill ) + \"\\\"\" ).toInt();\r\n\tm_moveSpeed = qMax( 30, speed );\r\n}\r\n\r\nvoid Gnome::assignWorkshop( unsigned int id )\r\n{\r\n\tm_assignedWorkshop = id;\r\n}\r\n\r\nEquipment Gnome::equipment()\r\n{\r\n\treturn m_equipment;\r\n}\r\n\r\nQString Gnome::rightHandItem()\r\n{\r\n\treturn m_equipment.rightHandHeld.material + \" \" + m_equipment.rightHandHeld.item;\r\n}\r\n\r\nQString Gnome::rightHandAttackSkill()\r\n{\r\n\treturn QString::number( m_rightHandAttackSkill );\r\n}\r\n\r\nQString Gnome::rightHandAttackValue()\r\n{\r\n\treturn QString::number( m_rightHandAttackValue );\r\n}\r\n\r\nvoid Gnome::updateAttackValues()\r\n{\r\n\tm_leftHandAttackSkill  = getSkillLevel( \"Unarmed\" );\r\n\tm_leftHandAttackValue  = attribute( \"Str\" );\r\n\tm_rightHandAttackSkill = getSkillLevel( \"Unarmed\" );\r\n\tm_rightHandAttackValue = attribute( \"Str\" );\r\n}\r\n\r\nbool Gnome::attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID )\r\n{\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\t// from which side is the attack coming\r\n\tAnatomySide ds = AS_CENTER;\r\n\tswitch ( m_facing )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tif ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_FRONT;\r\n\t\t\telse if ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_BACK;\r\n\t\t\tif ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_RIGHT );\r\n\t\t\telse if ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_LEFT );\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tif ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_LEFT;\r\n\t\t\telse if ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_RIGHT;\r\n\t\t\tif ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_FRONT );\r\n\t\t\telse if ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_BACK );\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tif ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_FRONT;\r\n\t\t\telse if ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_BACK;\r\n\t\t\tif ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_RIGHT );\r\n\t\t\telse if ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_LEFT );\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tif ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_LEFT;\r\n\t\t\telse if ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_RIGHT;\r\n\t\t\tif ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_FRONT );\r\n\t\t\telse if ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_BACK );\r\n\t\t\tbreak;\r\n\t}\r\n\t// attacker skill vs our dodge or block chance\r\n\r\n\tint dodge = getSkillLevel( \"Dodge\" );\r\n\tif ( ds & AS_BACK )\r\n\t{\r\n\t\tskill *= 1.5;\r\n\t}\r\n\r\n\tbool hit = skill >= dodge;\r\n\tif ( dodge > skill )\r\n\t{\r\n\t\tint diff = dodge - skill;\r\n\t\tdiff     = qMax( 5, 20 - diff );\r\n\t\thit |= rand() % 100 > diff;\r\n\t}\r\n\r\n\tif ( hit ) // check block\r\n\t{\r\n\t}\r\n\r\n\tif ( hit )\r\n\t{\r\n\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" took \" + QString::number( strength ) + \" damage.\", m_id );\r\n\t\tm_anatomy.damage( &m_equipment, dt, da, ds, strength );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" dogded the attack. Skill:\" + QString::number( skill ) + \" Dodge: \" + QString::number( dodge ), m_id );\r\n\t}\r\n\r\n\tbool aeExists = false;\r\n\tfor ( auto& ae : m_aggroList )\r\n\t{\r\n\t\tif ( ae.id == attackerID )\r\n\t\t{\r\n\t\t\tae.aggro += strength;\r\n\t\t\taeExists = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !aeExists )\r\n\t{\r\n\t\tAggroEntry newAE { strength, attackerID };\r\n\t\tm_aggroList.append( newAE );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid Gnome::setAllowedCarryItems( bool bandages, bool food, bool drinks )\r\n{\r\n\tm_carryBandages = bandages;\r\n\tm_carryFood     = food;\r\n\tm_carryDrinks   = drinks;\r\n}"
  },
  {
    "path": "src/game/gnome.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/behaviortree/bt_node.h\"\r\n#include \"canwork.h\"\r\n\r\n#include <QHash>\r\n\r\n#include <functional>\r\n#include <string>\r\n#include <unordered_map>\r\n\r\nstruct Uniform;\r\n\r\nclass Gnome : public CanWork\r\n{\r\npublic:\r\n\tGnome( Position& pos, QString name, Gender gender, Game* game );\r\n\tGnome( QVariantMap& in, Game* game );\r\n\t~Gnome();\r\n\r\n\tvirtual void init();\r\n\r\n\tvirtual void serialize( QVariantMap& out );\r\n\r\n\tvirtual void updateSprite();\r\n\tQVariantList createSpriteDef( QString type, bool isBack );\r\n\r\n\tvirtual CreatureTickResult onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid die() override;\r\n\r\n\t// return true if no floor present\r\n\tbool checkFloor();\r\n\r\n\t//return true if need needs action\r\n\tbool evalNeeds( bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid addNeed( QString id, int level );\r\n\tint need( QString id );\r\n\r\n\tvoid selectProfession( QString profession );\r\n\r\n\tQString profession()\r\n\t{\r\n\t\treturn m_profession;\r\n\t}\r\n\tvoid setProfession( QString profession )\r\n\t{\r\n\t\tselectProfession( profession );\r\n\t}\r\n\r\n\tvoid updateLight( Position oldPos, Position newPos );\r\n\r\n\tvoid setJobAborted( QString caller );\r\n\r\n\tQStringList skillPrios()\r\n\t{\r\n\t\treturn m_skillPriorities;\r\n\t}\r\n\tvoid setSkillPrios( QStringList prioList )\r\n\t{\r\n\t\tm_skillPriorities = prioList;\r\n\t}\r\n\r\n\tQString getActivity();\r\n\r\n\tvoid setOwnedRoom( unsigned int id );\r\n\tunsigned int ownedRoom();\r\n\r\n\tScheduleActivity schedule( unsigned char hour );\r\n\tvoid setSchedule( unsigned char hour, ScheduleActivity activity );\r\n\tQList<ScheduleActivity> schedule() { return m_schedule; }\r\n\r\n\tvirtual void updateMoveSpeed();\r\n\r\n\tvoid assignWorkshop( unsigned int id );\r\n\r\n\tEquipment equipment();\r\n\r\n\tQString rightHandItem();\r\n\tQString rightHandAttackSkill();\r\n\tQString rightHandAttackValue();\r\n\r\n\tvoid updateAttackValues();\r\n\tbool attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID );\r\n\r\n\tvoid setAllowedCarryItems( bool bandages, bool food, bool drinks );\r\n\r\n\tbool equipItem();\r\n\r\nprotected:\r\n\tfloat m_gainFromSleep = 0.035f;\r\n\r\n\tQString m_profession = \"Gnomad\";\r\n\r\n\tbool m_hungryLog     = false;\r\n\tbool m_veryHungryLog = false;\r\n\tbool m_thirstyLog    = false;\r\n\tbool m_veryThirstLog = false;\r\n\tbool m_sleepyLog     = false;\r\n\r\n\tbool m_carryBandages            = false;\r\n\tbool m_carryFood                = false;\r\n\tbool m_carryDrinks              = false;\r\n\tunsigned char m_carriedBandages = 0;\r\n\tunsigned char m_carriedFood     = 0;\r\n\tunsigned char m_carriedDrinks   = 0;\r\n\r\n\tQList<ScheduleActivity> m_schedule;\r\n\r\n\tvoid initTaskMap();\r\n\r\n\tvoid setConcealed( QString part, bool concealed );\r\n\tbool checkUniformItem( QString slot, Uniform* uniform, bool& dropped );\r\n\tbool m_uniformWorn             = false;\r\n\tquint64 m_nextUniformCheckTick = 0;\r\n\r\n\tBT_RESULT conditionIsHungry( bool halt = false );\r\n\tBT_RESULT conditionIsVeryHungry( bool halt = false );\r\n\tBT_RESULT conditionIsThirsty( bool halt = false );\r\n\tBT_RESULT conditionIsVeryThirsty( bool halt = false );\r\n\tBT_RESULT conditionIsSleepy( bool halt = false );\r\n\tBT_RESULT conditionAllItemsInPlaceForJob( bool halt = false );\r\n\tBT_RESULT conditionIsButcherJob( bool halt = false );\r\n\tBT_RESULT conditionAllPickedUp( bool halt = false );\r\n\tBT_RESULT conditionIsFull( bool halt = false );\r\n\tBT_RESULT conditionIsDrinkFull( bool halt = false );\r\n\tBT_RESULT conditionIsTrainingTime( bool halt = false );\r\n\tBT_RESULT conditionIsTrainer( bool halt = false );\r\n\tBT_RESULT conditionIsCivilian( bool halt = false );\r\n\tBT_RESULT conditionHasHuntTarget( bool halt = false );\r\n\r\n\tBT_RESULT actionSleep( bool halt );\r\n\tBT_RESULT actionFindBed( bool halt );\r\n\r\n\tBT_RESULT actionFindFood( bool halt );\r\n\tBT_RESULT actionFindDrink( bool halt );\r\n\r\n\tBT_RESULT actionFindDining( bool halt );\r\n\tBT_RESULT actionPickUpItem( bool halt );\r\n\r\n\tBT_RESULT actionEat( bool halt );\r\n\tBT_RESULT actionDrink( bool halt );\r\n\r\n\tBT_RESULT actionMove( bool halt );\r\n\r\n\tBT_RESULT actionClaimItems( bool halt );\r\n\tbool claimFromLinkedStockpile( QString itemSID, QString materialSID, int count, bool requireSame, QStringList restriction );\r\n\r\n\tBT_RESULT actionDropItem( bool halt );\r\n\tBT_RESULT actionDropAllItems( bool halt );\r\n\tBT_RESULT actionEquipTool( bool halt );\r\n\tBT_RESULT actionCheckUniform( bool halt );\r\n\tBT_RESULT actionCheckBandages( bool halt );\r\n\tBT_RESULT actionUniformCleanUp( bool halt );\r\n\tBT_RESULT actionFindTool( bool halt );\r\n\tBT_RESULT actionGetItemDropPosition( bool halt );\r\n\tBT_RESULT actionGetWorkPosition( bool halt );\r\n\r\n\tBT_RESULT actionGetJob( bool halt );\r\n\tBT_RESULT actionInitJob( bool halt );\r\n\tBT_RESULT actionAbortJob( bool halt );\r\n\tBT_RESULT actionFinishJob( bool halt );\r\n\tBT_RESULT actionWork( bool halt );\r\n\r\n\tBT_RESULT actionInitAnimalJob( bool halt );\r\n\tBT_RESULT actionGrabAnimal( bool halt );\r\n\tBT_RESULT actionReleaseAnimal( bool halt );\r\n\tBT_RESULT actionButcherAnimal( bool halt );\r\n\tBT_RESULT actionDyeAnimal( bool halt );\r\n\tBT_RESULT actionHarvestAnimal( bool halt );\r\n\tBT_RESULT actionTameAnimal( bool halt );\r\n\tBT_RESULT actionFinalMoveAnimal( bool halt );\r\n\r\n\tBT_RESULT actionAlwaysRunning( bool halt );\r\n\r\n\tBT_RESULT actionAttackTarget( bool halt );\r\n\tBT_RESULT actionFindTrainingGround( bool halt );\r\n\tBT_RESULT actionTrain( bool halt );\r\n\tBT_RESULT actionFindTrainerPosition( bool halt );\r\n\tBT_RESULT actionSuperviseTraining( bool halt );\r\n\r\n\tBT_RESULT actionGetTarget( bool halt );\r\n\r\n\tBT_RESULT actionDoMission( bool halt );\r\n\tBT_RESULT actionLeaveForMission( bool halt );\r\n\tBT_RESULT actionReturnFromMission( bool halt );\r\n};\r\n"
  },
  {
    "path": "src/game/gnomeactions.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/logger.h\"\r\n#include \"../base/pathfinder.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/eventmanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/neighbormanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/room.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/stockpile.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/soundmanager.h\"\r\n#include \"../game/workshop.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n#include \"game.h\"\r\n#include \"gnome.h\"\r\n#include \"gnomemanager.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n\r\nBT_RESULT Gnome::actionFinishJob( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFinishJob\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\t//job is finished\r\n\tcleanUpJob( true );\r\n\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionAbortJob( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionAbortJob\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tcleanUpJob( false );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionSleep( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionSleep\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t{\r\n\t\t\tsetThoughtBubble( \"\" );\r\n\t\t\tm_log.append( \"I was rudely awoken.\" );\r\n\t\t\tunclaimAll();\r\n\t\t\treturn BT_RESULT::IDLE;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( thoughtBubble() != \"Sleeping\" )\r\n\t{\r\n\t\tm_gainFromSleep = ( DB::select( \"GainFromSleep\", \"Needs\", \"Sleep\" ).toFloat() / Global::util->ticksPerMinute );\r\n\t\tsetThoughtBubble( \"Sleeping\" );\r\n\t\tm_log.append( \"Going to sleep.\" );\r\n\t}\r\n\r\n\tif ( m_job )\r\n\t{\r\n\t\tcleanUpJob( false );\r\n\t}\r\n\r\n\tfloat oldVal = m_needs[\"Sleep\"].toFloat();\r\n\tfloat newVal = oldVal + m_gainFromSleep;\r\n\tm_needs.insert( \"Sleep\", newVal );\r\n\r\n\tm_anatomy.heal();\r\n\r\n\tunsigned int hour = qMin( 23, GameState::hour );\r\n\tauto activity     = m_schedule[hour];\r\n\r\n\tif ( newVal >= 100. && activity != ScheduleActivity::Sleep )\r\n\t{\r\n\t\tsetThoughtBubble( \"\" );\r\n\t\tm_log.append( \"Woke up.\" );\r\n\r\n\t\tunclaimAll();\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindBed( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFindBed\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\t// gnome has room and room has bed?\r\n\tif ( m_equipment.roomID )\r\n\t{\r\n\t\tRoom* room = g->rm()->getRoom( m_equipment.roomID );\r\n\t\tQList<unsigned int> beds;\r\n\t\tif ( room )\r\n\t\t{\r\n\t\t\tbeds = room->beds();\r\n\t\t}\r\n\t\tif ( !beds.empty() )\r\n\t\t{\r\n\t\t\tif ( m_job )\r\n\t\t\t{\r\n\t\t\t\tcleanUpJob( false );\r\n\t\t\t}\r\n\r\n\t\t\tunsigned int bedID = beds.first();\r\n\r\n\t\t\taddClaimedItem( bedID, m_id );\r\n\t\t\tsetCurrentTarget( g->inv()->getItemPos( bedID ).toString() );\r\n\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\t// dormitory exists and has free bed?\r\n\tQList<unsigned int> dorms = g->rm()->getDorms();\r\n\r\n\tfor ( auto dorm : dorms )\r\n\t{\r\n\t\tQList<unsigned int> beds;\r\n\t\tRoom* room = g->rm()->getRoom( dorm );\r\n\t\tif ( room )\r\n\t\t{\r\n\t\t\tbeds = room->beds();\r\n\t\t}\r\n\t\tif ( !beds.empty() )\r\n\t\t{\r\n\t\t\tfor ( auto bedID : beds )\r\n\t\t\t{\r\n\t\t\t\tif ( !g->inv()->isInJob( bedID ) && !g->inv()->isUsedBy( bedID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcleanUpJob( false );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\taddClaimedItem( bedID, m_id );\r\n\t\t\t\t\tsetCurrentTarget( g->inv()->getItemPos( bedID ).toString() );\r\n\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionMove( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionMove\" );\r\n\t//if ( Global::debugMode )\r\n\t//qDebug() << \"actionMove\" << m_currentPath.size();\r\n\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionMove - halt\" );\r\n\t\tm_currentPath.clear();\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\t// gnome has a path, move on path and return\r\n\tif ( !m_currentPath.empty() )\r\n\t{\r\n\t\tif ( m_animal )\r\n\t\t{\r\n\t\t\tif ( m_moveCooldown <= m_moveSpeed )\r\n\t\t\t{\r\n\t\t\t\tauto animal = g->cm()->animal( m_animal );\r\n\t\t\t\tif ( animal )\r\n\t\t\t\t{\r\n\t\t\t\t\tanimal->setFollowPosition( m_position );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( m_currentAttackTarget )\r\n\t\t{\r\n\t\t\tif ( conditionTargetAdjacent( false ) == BT_RESULT::SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\tqDebug() << m_name << \"target adjecent, finish movement\";\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\r\n\t\t\tif ( conditionTargetPositionValid( false ) == BT_RESULT::FAILURE )\r\n\t\t\t{\r\n\t\t\t\t// Repath\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tPosition oldPos = m_position;\r\n\r\n\t\tif ( !moveOnPath() )\r\n\t\t{\r\n\t\t\t//abortJob( \"actionMove - 1\" );\r\n\t\t\tm_currentPath.clear();\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\r\n\t\tif ( m_lightIntensity && m_position != oldPos )\r\n\t\t{\r\n\t\t\tg->w()->moveLight( m_id, m_position, m_lightIntensity );\r\n\t\t}\r\n\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tPosition targetPos = currentTarget();\r\n\r\n\t// check if we are already on the tile\r\n\tif ( m_position == targetPos )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tPathFinderResult pfr = g->pf()->getPath( m_id, m_position, targetPos, m_ignoreNoPass, m_currentPath );\r\n\tswitch ( pfr )\r\n\t{\r\n\t\tcase PathFinderResult::NoConnection:\r\n\t\t\t//abortJob( \"actionMove - no connection - [\" + m_position.toString() + \"] [\" + targetPos.toString() + \"]\" );\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\tcase PathFinderResult::Running:\r\n\t\tcase PathFinderResult::FoundPath:\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindFood( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFindFood\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tauto itemID = g->inv()->getFoodItem( m_position );\r\n\t//m_log.append( \"Looking for food.\" );\r\n\r\n\tif ( itemID )\r\n\t{\r\n\t\t// we found food, clean up job before we set some job variables again\r\n\t\tif ( m_job )\r\n\t\t{\r\n\t\t\tcleanUpJob( false );\r\n\t\t}\r\n\r\n\t\taddClaimedItem( itemID, m_id );\r\n\t\tm_itemToPickUp = itemID;\r\n\t\tsetCurrentTarget( g->inv()->getItemPos( itemID ).toString() );\r\n\t\t//m_log.append( \"Found food.\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\t//m_log.append( \"Didn't find food.\" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindDrink( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFindDrink\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tauto itemID = g->inv()->getDrinkItem( m_position );\r\n\t//m_log.append( \"Looking for something to drink.\" );\r\n\tif ( itemID )\r\n\t{\r\n\t\t// we found food, clean up job before we set some job variables again\r\n\t\tif ( m_job )\r\n\t\t{\r\n\t\t\tcleanUpJob( false );\r\n\t\t}\r\n\r\n\t\taddClaimedItem( itemID, m_id );\r\n\t\tm_itemToPickUp = itemID;\r\n\t\tsetCurrentTarget( g->inv()->getItemPos( itemID ).toString() );\r\n\t\t//m_log.append( \"Found drinks.\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\t//m_log.append( \"Didn't find drinks.\" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindDining( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFindDining\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tQList<unsigned int> dhl = g->rm()->getDinings();\r\n\t//m_log.append( \"Looking for a dining room.\" );\r\n\tm_currentAction             = \"find dining\";\r\n\tunsigned int closestChairID = 0;\r\n\tint dist                    = 1000000;\r\n\tfor ( auto dh : dhl )\r\n\t{\r\n\t\tRoom* room = g->rm()->getRoom( dh );\r\n\t\tif ( room )\r\n\t\t{\r\n\t\t\tQList<unsigned int> chairs = room->chairs();\r\n\t\t\tif ( !chairs.empty() )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto chairID : chairs )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !g->inv()->isInJob( chairID ) && !g->inv()->isUsedBy( chairID ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint curDist = m_position.distSquare( g->inv()->getItemPos( chairID ), 5 );\r\n\t\t\t\t\t\tif ( curDist < dist )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tdist           = curDist;\r\n\t\t\t\t\t\t\tclosestChairID = chairID;\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\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( closestChairID != 0 )\r\n\t{\r\n\t\taddClaimedItem( closestChairID, m_id );\r\n\t\tauto chairPos = g->inv()->getItemPos( closestChairID );\r\n\t\tsetCurrentTarget( chairPos );\r\n\r\n\t\tm_facingAfterMove = g->w()->getTile( chairPos ).wallRotation;\r\n\r\n\t\t//m_log.append( \"Found a dining room.\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\t//m_log.append( \"Didn't find a dining room.\" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionEat( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionEat\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionEat - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\r\n\t// first visit\r\n\tif ( m_currentAction != \"eating\" )\r\n\t{\r\n\t\t//m_log.append( \"Starting to eat.\" );\r\n\t\tm_currentAction  = \"eating\";\r\n\t\tm_taskFinishTick = GameState::tick + Global::util->ticksPerMinute * 15; // TODO set duration depending on food item or other circumstances\r\n\t\tunsigned int carriedItem = m_carriedItems.first();\r\n\t\t//printf(\"eat %s \\n\", g->inv()->itemSID( carriedItem ).toStdString().c_str() );\r\n\t\tg->sm()->playEffect(\"actionEat\" , m_position, g->inv()->itemSID( carriedItem ) );\r\n\t\t\r\n\t}\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tif ( m_carriedItems.empty() )\r\n\t{\r\n\t\t//abortJob( \"actionEat - no item\" );\r\n\t\tunclaimAll();\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tunsigned int carriedItem = m_carriedItems.first();\r\n\tunsigned char nutrition  = g->inv()->nutritionalValue( carriedItem );\r\n\r\n\tfloat oldVal = m_needs[\"Hunger\"].toFloat();\r\n\tfloat newVal = qMin( 150.f, oldVal + nutrition );\r\n\tif ( newVal > 30 )\r\n\t{\r\n\t\tm_hungryLog     = false;\r\n\t\tm_veryHungryLog = false;\r\n\t}\r\n\r\n\tm_needs.insert( \"Hunger\", newVal );\r\n\tm_startedEating = true;\r\n\r\n\tQString logText( \"I just ate a \" + S::s( \"$ItemName_\" + g->inv()->itemSID( carriedItem ) ) + \".\" );\r\n\t//m_log.append( logText );\r\n\r\n\tg->inv()->destroyObject( carriedItem );\r\n\tm_carriedItems.clear();\r\n\r\n\tsetThoughtBubble( \"\" );\r\n\r\n\tunclaimAll();\r\n\t//m_log.append( \"Finished eating.\" );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionDrink( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionDrink\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionDrink - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\r\n\t// first visit\r\n\tif ( m_currentAction != \"drinking\" )\r\n\t{\r\n\t\t//m_log.append( \"Starting to drink.\" );\r\n\t\tm_currentAction  = \"drinking\";\r\n\t\tm_taskFinishTick = GameState::tick + Global::util->ticksPerMinute * 15; // TODO set duration depending on food item or other circumstances\r\n\t\t\r\n\t\tunsigned int carriedItem = m_carriedItems.first();\r\n\t\t//printf(\"drink %s %d\\n\", g->inv()->itemSID( carriedItem ).toStdString().c_str(), g->inv()->quality( carriedItem ) );\r\n\t\tg->sm()->playEffect(\"actionDrink\" , m_position, g->inv()->itemSID( carriedItem ) );\r\n\t}\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tif ( m_carriedItems.empty() )\r\n\t{\r\n\t\t//abortJob( \"actionDrink - no item\" );\r\n\t\tunclaimAll();\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tunsigned int carriedItem = m_carriedItems.first();\r\n\tunsigned char drinkValue = g->inv()->drinkValue( carriedItem );\r\n\r\n\tfloat oldVal = m_needs[\"Thirst\"].toFloat();\r\n\tfloat newVal = qMin( 150.f, oldVal + drinkValue );\r\n\tif ( newVal > 30 )\r\n\t{\r\n\t\tm_thirstyLog    = false;\r\n\t\tm_veryThirstLog = false;\r\n\t}\r\n\tm_needs.insert( \"Thirst\", newVal );\r\n\tm_startedDrinking = false;\r\n\r\n\tQString logText( \"I just drank a \" + S::s( \"$ItemName_\" + g->inv()->itemSID( carriedItem ) ) + \".\" );\r\n\t//m_log.append( logText );\r\n\r\n\tg->inv()->destroyObject( carriedItem );\r\n\tm_carriedItems.clear();\r\n\tsetThoughtBubble( \"\" );\r\n\r\n\tunclaimAll();\r\n\t//m_log.append( \"Finished drinking.\" );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionPickUpItem( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionPickUpItem\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_itemToPickUp )\r\n\t{\r\n\t\t//abortJob( \"actionPickUpItem - no item\" );\r\n\t\tm_log.append( \"Strange! Nothing to pick up.\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_position != g->inv()->getItemPos( m_itemToPickUp ) )\r\n\t{\r\n\t\tlog( \"Cannot pick up item that is not here\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tg->inv()->pickUpItem( m_itemToPickUp, m_id );\r\n\r\n\tif ( m_btBlackBoard.contains( \"ClaimedInventoryItem\" ) )\r\n\t{\r\n\t\tif ( m_itemToPickUp == m_btBlackBoard.value( \"ClaimedInventoryItem\" ).toUInt() )\r\n\t\t{\r\n\t\t\tm_inventoryItems.append( m_itemToPickUp );\r\n\t\t\tif ( g->inv()->itemSID( m_itemToPickUp ) == \"Bandage\" )\r\n\t\t\t{\r\n\t\t\t\tm_carriedBandages += 1;\r\n\t\t\t}\r\n\t\t\telse if ( g->inv()->nutritionalValue( m_itemToPickUp ) > 0 )\r\n\t\t\t{\r\n\t\t\t\t++m_carriedFood;\r\n\t\t\t}\r\n\t\t\telse if ( g->inv()->drinkValue( m_itemToPickUp ) > 0 )\r\n\t\t\t{\r\n\t\t\t\t++m_carriedDrinks;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_carriedItems.append( m_itemToPickUp );\r\n\t\t}\r\n\t\tm_btBlackBoard.remove( \"ClaimedInventoryItem\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_carriedItems.append( m_itemToPickUp );\r\n\t}\r\n\r\n\tif ( g->inv()->isInStockpile( m_itemToPickUp ) )\r\n\t{\r\n\t\tg->spm()->removeItem( m_job->stockpile(), g->inv()->getItemPos( m_itemToPickUp ), m_itemToPickUp );\r\n\t}\r\n\tif ( g->inv()->isInContainer( m_itemToPickUp ) )\r\n\t{\r\n\t\tg->inv()->removeItemFromContainer( m_itemToPickUp );\r\n\t}\r\n\r\n\tm_itemToPickUp = 0;\r\n\tlog( \"Picked up an item. \" + g->inv()->materialSID( m_itemToPickUp ) + \" \" + g->inv()->itemSID( m_itemToPickUp ) );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionGetJob( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionGetJob\" );\r\n\r\n\tif ( m_jobCooldown > 0 )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n#ifdef CHECKTIME\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tm_jobID      = g->jm()->getJob( m_skillPriorities, m_id, m_position );\r\n\tauto elapsed = timer.elapsed();\r\n\tif ( elapsed > 100 )\r\n\t{\r\n\t\tqDebug() << m_name << \"JobManager just needed\" << elapsed << \"ms for getJob\";\r\n\t\tGlobal::cfg->set( \"Pause\", true );\r\n\t}\r\n#else\r\n\tQElapsedTimer et;\r\n\tet.start();\r\n\r\n\tm_jobID = g->jm()->getJob( m_skillPriorities, m_id, m_position );\r\n#endif\r\n\r\n\tif ( m_jobID != 0 )\r\n\t{\r\n\t\tm_jobChanged = true;\r\n\t\tm_job        = g->jm()->getJob( m_jobID );\r\n\t\tif ( !m_job )\r\n\t\t{\r\n\t\t\tqDebug() << \"jm returned null ptr for jobid \" << m_jobID;\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\r\n\t\t//no change to jobsprite\r\n\t\tg->jm()->setJobBeingWorked( m_jobID, false );\r\n\t\tm_job->setIsWorked( true );\r\n\t\tm_job->setWorkedBy( m_id );\r\n\r\n\t\tlog( \"JobType \" + m_job->type() );\r\n\t\tm_btBlackBoard.insert( \"JobType\", m_job->type() );\r\n\t\tm_currentAction = \"job\";\r\n\r\n\t\tbool mayTrap = DB::select( \"MayTrapGnome\", \"Jobs\", m_job->type() ).toBool();\r\n\r\n\t\tm_workPositionQueue = PriorityQueue<Position, int>();\r\n\r\n\t\t// determine which position is the work position\r\n\t\tif ( mayTrap )\r\n\t\t{\r\n\t\t\tfor ( auto s : m_job->possibleWorkPositions() )\r\n\t\t\t{\r\n\t\t\t\tPosition ss( s );\r\n\t\t\t\tint hasJob = g->w()->hasJob( ss );\r\n\t\t\t\tm_workPositionQueue.put( ss, ( 5 - g->w()->walkableNeighbors( s ) ) * 100 + m_position.distSquare( ss ) + hasJob * 10 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto s : m_job->possibleWorkPositions() )\r\n\t\t\t{\r\n\t\t\t\tPosition ss( s );\r\n\t\t\t\tint hasJob = g->w()->hasJob( ss );\r\n\t\t\t\t//qDebug() << m_job->id() << \"[\" << ss.toString() << \"]\" ;\r\n\t\t\t\tm_workPositionQueue.put( ss, m_position.distSquare( ss ) + hasJob * 10 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tQString logText( \"Got a new \" + S::s( \"$SkillName_\" + m_job->requiredSkill() ) + \" job\" );\r\n\t\tlog( logText );\r\n\r\n\t\tif ( Global::debugMode )\r\n\t\t{\r\n\t\t\tauto ela = et.elapsed();\r\n\t\t\tif ( ela > 20 )\r\n\t\t\t{\r\n\t\t\t\tif ( m_job )\r\n\t\t\t\t{\r\n\t\t\t\t\tqDebug() << \"GETJOB\" << m_name << ela << \"ms\"\r\n\t\t\t\t\t\t\t << \"job:\" << m_job->type() << m_job->pos().toString();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// didn't get a suitable job, so wait some ticks before asking again\r\n\t\tm_jobCooldown = 100;\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionInitAnimalJob( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionInitAnimalJob\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\tif ( !a || a->toDestroy() )\r\n\t{\r\n\t\t//abortJob( \"grabAnimal()\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\ta->setImmobile( true );\r\n\tsetCurrentTarget( a->getPos() );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionInitJob( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionInitJob\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( Global::debugMode )\r\n\t{\r\n\t\tlog( \"job pos:\" + m_job->pos().toString() );\r\n\t\tlog( \"work position queue size:\" + QString::number( m_workPositionQueue.size() ) );\r\n\t}\r\n\twhile ( !m_workPositionQueue.empty() )\r\n\t{\r\n\t\tPosition currentCheckPos = m_workPositionQueue.get();\r\n\t\tif ( Global::debugMode )\r\n\t\t\tlog( \"Check connection: \" + m_position.toString() + \" \" + currentCheckPos.toString() );\r\n\r\n\t\tif ( g->pf()->checkConnectedRegions( m_position, currentCheckPos ) )\r\n\t\t{\r\n\t\t\t// found a suitable working position\r\n\t\t\tif ( Global::debugMode )\r\n\t\t\t\tlog( \"Set workpos: \" + currentCheckPos.toString() );\r\n\t\t\tm_job->setWorkPos( currentCheckPos );\r\n\t\t\t// if item input was set before ( workshop job) don't overwrite it\r\n\t\t\tif ( m_job->posItemInput().isZero() )\r\n\t\t\t{\r\n\t\t\t\tm_job->setPosItemInput( currentCheckPos );\r\n\t\t\t}\r\n\r\n\t\t\tbool hasItems = m_job->requiredItems().size() == claimedItems().size();\r\n\t\t\tif ( Global::debugMode )\r\n\t\t\t\tlog( \"Has items: \" + hasItems ? \"true\" : \"false\" );\r\n\t\t\tg->jm()->setJobBeingWorked( m_jobID, m_job->requiredTool().type.isEmpty() && hasItems );\r\n\t\t\t//log( \"Init \" + S::s( \"$SkillName_\" + m_job->requiredSkill() ) + \" job done.\" );\r\n\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\t//abortJob( \"initJob - job not reachable \" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nbool Gnome::claimFromLinkedStockpile( QString itemSID, QString materialSID, int count, bool requireSame, QStringList restriction )\r\n{\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\tint claimed  = 0;\r\n\tWorkshop* ws = g->wsm()->workshopAt( m_job->pos() );\r\n\tif ( ws && ws->linkedStockpile() && g->spm()->getStockpile( ws->linkedStockpile() ) )\r\n\t{\r\n\t\tStockpile* sp = g->spm()->getStockpile( ws->linkedStockpile() );\r\n\t\t// is the whole needed number in the stockpile?\r\n\t\tif ( materialSID == \"any\" )\r\n\t\t{\r\n\t\t\tQList<QString> materials = g->inv()->materialsForItem( itemSID, count );\r\n\r\n\t\t\tif ( requireSame )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto mat : materials )\r\n\t\t\t\t{\r\n\t\t\t\t\tbool matAllowed = ( restriction.empty() || restriction.contains( mat ) );\r\n\t\t\t\t\tif ( matAllowed )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( sp->count( itemSID, mat ) < count )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tunsigned int item = 0;\r\n\t\t\t\t\t\t\tfor ( auto spf : sp->getFields() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// if exists get item from that position\r\n\t\t\t\t\t\t\t\titem = g->inv()->getItemAtPos( spf->pos, true, itemSID, mat );\r\n\t\t\t\t\t\t\t\tif ( item )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tg->inv()->moveItemToPos( item, m_job->posItemInput() );\r\n\t\t\t\t\t\t\t\t\tsp->setInfiNotFull( spf->pos );\r\n\t\t\t\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t\t\t\t\t++claimed;\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}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( restriction.empty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned int item = 0;\r\n\t\t\t\t\t\tfor ( auto spf : sp->getFields() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// if exists get item from that position\r\n\t\t\t\t\t\t\titem = g->inv()->getItemAtPos( spf->pos, true, itemSID, \"any\" );\r\n\t\t\t\t\t\t\tif ( item )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tg->inv()->moveItemToPos( item, m_job->posItemInput() );\r\n\t\t\t\t\t\t\t\tsp->setInfiNotFull( spf->pos );\r\n\t\t\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t\t\t\t++claimed;\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}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned int item = 0;\r\n\t\t\t\t\t\tfor ( auto spf : sp->getFields() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// if exists get item from that position\r\n\t\t\t\t\t\t\titem = g->inv()->getItemAtPos( spf->pos, true, itemSID, \"any\" );\r\n\t\t\t\t\t\t\tif ( item && restriction.contains( g->inv()->materialSID( item ) ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tg->inv()->moveItemToPos( item, m_job->posItemInput() );\r\n\t\t\t\t\t\t\t\tsp->setInfiNotFull( spf->pos );\r\n\t\t\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t\t\t\t++claimed;\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}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( claimed == count )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( sp->count( itemSID, materialSID ) < count )\r\n\t\t\t{\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\t//if yes\r\n\t\tif ( materialSID != \"any\" )\r\n\t\t{\r\n\t\t\t// get from linked stockpile\r\n\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t{\r\n\t\t\t\tunsigned int item = 0;\r\n\t\t\t\tfor ( auto spf : sp->getFields() )\r\n\t\t\t\t{\r\n\t\t\t\t\t// if exists get item from that position\r\n\t\t\t\t\titem = g->inv()->getItemAtPos( spf->pos, true, itemSID, materialSID );\r\n\t\t\t\t\tif ( item )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->moveItemToPos( item, m_job->posItemInput() );\r\n\t\t\t\t\t\tsp->setInfiNotFull( spf->pos );\r\n\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t\t++claimed;\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 ( claimed == count )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nBT_RESULT Gnome::actionClaimItems( bool halt )\r\n{\r\n\tQElapsedTimer et;\r\n\tet.start();\r\n\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionClaimItems\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( claimedItems().size() )\r\n\t{\r\n\t\tqDebug() << \"Error: no items should be claimed here.\";\r\n\t\tunclaimAll();\r\n\t}\r\n\r\n\tif ( m_job->type() == \"CraftAtWorkshop\" )\r\n\t{\r\n\t\tWorkshop* ws = g->wsm()->workshopAt( m_job->pos() );\r\n\t\tfor ( auto component : m_job->requiredItems() )\r\n\t\t{\r\n\t\t\tQString itemSID         = component.itemSID;\r\n\t\t\tQString materialSID     = component.materialSID;\r\n\t\t\tbool requireSame        = component.requireSame;\r\n\t\t\tQStringList restriction = component.materialRestriction;\r\n\t\t\tif ( restriction.size() == 1 && restriction.first().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\trestriction.clear();\r\n\t\t\t}\r\n\r\n\t\t\tint count        = component.count;\r\n\t\t\tint countClaimed = 0;\r\n\t\t\t// check if item exists in linked stockpile\r\n\t\t\tif ( claimFromLinkedStockpile( itemSID, materialSID, count, requireSame, restriction ) )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( requireSame && materialSID == \"any\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tQList<QString> materials = g->inv()->materialsForItem( itemSID, count );\r\n\t\t\t\t\tif ( materials.empty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbool found = false;\r\n\t\t\t\t\tfor ( auto mat : materials )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbool matAllowed = ( restriction.empty() || restriction.contains( mat ) );\r\n\t\t\t\t\t\tif ( matAllowed )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tauto items = g->inv()->getClosestItems( m_job->pos(), true, itemSID, mat, count );\r\n\t\t\t\t\t\t\tif ( items.size() < count )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tfor ( auto item : items )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tfound = true;\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\tif ( !found )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tlog( \"failed to claim: \" + itemSID + \" \" + materialSID );\r\n\t\t\t\t\t\t//abortJob( \"claimMaterial() not enough\" );\r\n\t\t\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned int item = g->inv()->getClosestItem( m_job->pos(), true, itemSID, materialSID );\r\n\t\t\t\t\t\tif ( item )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\t\tlog( \"failed to claim: \" + itemSID + \" \" + materialSID );\r\n\t\t\t\t\t\t\t//abortJob( \"claimMaterial() not enough\" );\r\n\t\t\t\t\t\t\treturn BT_RESULT::FAILURE;\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\telse if ( m_job->type() == \"HauleItem\" )\r\n\t{\r\n\t\tfor ( auto itemID : m_job->itemsToHaul() )\r\n\t\t{\r\n\t\t\taddClaimedItem( itemID, m_job->id() );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor ( auto component : m_job->requiredItems() )\r\n\t\t{\r\n\t\t\tint count          = component.count;\r\n\t\t\tQString itemID     = component.itemSID;\r\n\t\t\tQString materialID = component.materialSID;\r\n\t\t\tif ( Global::debugMode )\r\n\t\t\t\tlog( \"claim \" + QString::number( count ) + \" \" + materialID + \" \" + itemID );\r\n\r\n\t\t\tQStringList restrictions = component.materialRestriction;\r\n\t\t\tif ( restrictions.size() == 1 && restrictions.first().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\trestrictions.clear();\r\n\t\t\t}\r\n\r\n\t\t\tif ( materialID == \"any\" && !restrictions.empty() )\r\n\t\t\t{\r\n\t\t\t\tQSet<QString> matTypes;\r\n\t\t\t\tfor ( auto type : restrictions )\r\n\t\t\t\t{\r\n\t\t\t\t\tmatTypes.insert( type );\r\n\t\t\t\t\tunsigned int item = g->inv()->getClosestItem2( m_job->pos(), true, itemID, matTypes );\r\n\t\t\t\t\tif ( item )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tlog( \"claim failed ##1\" );\r\n\t\t\t\t\t\t//abortJob( \"claimMaterial()\" );\r\n\t\t\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfor ( int i = 0; i < count; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int item = g->inv()->getClosestItem( m_job->workPos(), true, itemID, materialID );\r\n\t\t\t\t\tif ( item )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\taddClaimedItem( item, m_job->id() );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( Global::debugMode )\r\n\t\t\t\t\t\t\tlog( \"claim failed ##2\" );\r\n\t\t\t\t\t\t//abortJob( \"claimMaterial()\" );\r\n\t\t\t\t\t\treturn BT_RESULT::FAILURE;\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\tg->jm()->setJobBeingWorked( m_jobID, m_job->requiredTool().type.isEmpty() );\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionClaimItems success\" );\r\n\r\n\tif ( Global::debugMode )\r\n\t{\r\n\t\tauto ela = et.elapsed();\r\n\t\tif ( ela > 30 )\r\n\t\t{\r\n\t\t\tif ( m_job )\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"CLAIMITEMS\" << m_name << ela << \"ms\"\r\n\t\t\t\t\t\t << \"job:\" << m_job->type() << m_job->pos().toString();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindTool( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFindTool\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tauto rt = m_job->requiredTool();\r\n\tif ( rt.type.isEmpty() || m_type == CreatureType::AUTOMATON )\r\n\t{\r\n\t\tsetCurrentTarget( m_position );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tunsigned int equippedItem = m_equipment.rightHandHeld.itemID;\r\n\tint equippedToolLevel     = Global::util->toolLevel( equippedItem );\r\n\r\n\tif ( equippedItem )\r\n\t{\r\n\t\tif ( g->inv()->itemSID( equippedItem ) == rt.type && equippedToolLevel >= rt.level )\r\n\t\t{\r\n\t\t\t// gnome already has the required tool equipped\r\n\t\t\tsetCurrentTarget( m_position );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// wrong tool equipped,\r\n\t\t\t// drop tool\r\n\t\t\tg->inv()->putDownItem( equippedItem, m_position );\r\n\t\t\tg->inv()->setInJob( equippedItem, 0 );\r\n\t\t\tm_equipment.rightHandHeld.itemID = 0;\r\n\t\t\tm_equipment.rightHandHeld.item.clear();\r\n\t\t\tm_equipment.rightHandHeld.materialID = 0;\r\n\t\t\tm_equipment.rightHandHeld.material.clear();\r\n\t\t\tequipHand( 0, \"Right\" );\r\n\t\t\t//return BT_RESULT::RUNNING;\r\n\t\t}\r\n\t}\r\n\t//no item equipped\r\n\tQMap<QString, int> mc = g->inv()->materialCountsForItem( rt.type );\r\n\tQStringList keys      = mc.keys();\r\n\r\n\tfor ( auto key : keys )\r\n\t{\r\n\t\tif ( mc[key] > 0 )\r\n\t\t{\r\n\t\t\tint tl = Global::util->toolLevel( key );\r\n\t\t\tif ( tl >= rt.level )\r\n\t\t\t{\r\n\t\t\t\t// there are a number of tools of the required level in the world\r\n\t\t\t\tauto tool = g->inv()->getClosestItem( m_position, true, rt.type, key );\r\n\t\t\t\tif ( tool )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_job->setToolPosition( g->inv()->getItemPos( tool ) );\r\n\t\t\t\t\tg->inv()->setInJob( tool, m_job->id() );\r\n\t\t\t\t\tm_btBlackBoard.insert( \"ClaimedTool\", tool );\r\n\r\n\t\t\t\t\tsetCurrentTarget( g->inv()->getItemPos( tool ) );\r\n\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t//abortJob( \"checkTool()\" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionEquipTool( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionEquipTool\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_job->requiredTool().type.isEmpty() || m_type == CreatureType::AUTOMATON )\r\n\t{\r\n\t\t//log( \"No tool required\" );\r\n\t\tg->jm()->setJobBeingWorked( m_jobID, true );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tif ( m_equipment.rightHandHeld.itemID )\r\n\t{\r\n\t\tint equippedToolLevel = Global::util->toolLevel( m_equipment.rightHandHeld.itemID );\r\n\t\tif ( m_equipment.rightHandHeld.item == m_job->requiredTool().type && equippedToolLevel >= m_job->requiredTool().level )\r\n\t\t{\r\n\t\t\tg->jm()->setJobBeingWorked( m_jobID, true );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\r\n\tunsigned int claimedTool = m_btBlackBoard.value( \"ClaimedTool\" ).toUInt();\r\n\tif ( claimedTool )\r\n\t{\r\n\t\tif ( m_position == g->inv()->getItemPos( claimedTool ) )\r\n\t\t{\r\n\t\t\tg->inv()->pickUpItem( claimedTool, m_id );\r\n\t\t\tm_equipment.rightHandHeld.itemID     = claimedTool;\r\n\t\t\tm_equipment.rightHandHeld.item       = g->inv()->itemSID( claimedTool );\r\n\t\t\tm_equipment.rightHandHeld.materialID = g->inv()->materialUID( claimedTool );\r\n\t\t\tm_equipment.rightHandHeld.material   = g->inv()->materialSID( claimedTool );\r\n\r\n\t\t\tm_btBlackBoard.remove( \"ClaimedTool\" );\r\n\r\n\t\t\tequipHand( claimedTool, \"Right\" );\r\n\r\n\t\t\tg->jm()->setJobBeingWorked( m_jobID, true );\r\n\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\t//abortJob( \"pickUpTool()\" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nbool Gnome::checkUniformItem( QString slot, Uniform* uniform, bool& dropped )\r\n{\r\n\tif ( m_jobID )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tauto part = Global::creaturePartLookUp.value( slot );\r\n\r\n\tQString item     = uniform->parts[slot].item;\r\n\tQString material = uniform->parts[slot].material;\r\n\r\n\tQString wiSID         = \"\";\r\n\tQString wiMat         = \"\";\r\n\tunsigned int wornItem = 0;\r\n\r\n\tswitch ( part )\r\n\t{\r\n\t\tcase CP_ARMOR_HEAD:\r\n\t\t\tif ( m_equipment.head.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.head.itemID;\r\n\t\t\t\twiSID    = m_equipment.head.item;\r\n\t\t\t\twiMat    = m_equipment.head.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_ARMOR_TORSO:\r\n\t\t\tif ( m_equipment.chest.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.chest.itemID;\r\n\t\t\t\twiSID    = m_equipment.chest.item;\r\n\t\t\t\twiMat    = m_equipment.chest.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_ARMOR_ARM:\r\n\t\t\tif ( m_equipment.arm.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.arm.itemID;\r\n\t\t\t\twiSID    = m_equipment.arm.item;\r\n\t\t\t\twiMat    = m_equipment.arm.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_ARMOR_HAND:\r\n\t\t\tif ( m_equipment.hand.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.hand.itemID;\r\n\t\t\t\twiSID    = m_equipment.hand.item;\r\n\t\t\t\twiMat    = m_equipment.hand.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_ARMOR_LEG:\r\n\t\t\tif ( m_equipment.leg.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.leg.itemID;\r\n\t\t\t\twiSID    = m_equipment.leg.item;\r\n\t\t\t\twiMat    = m_equipment.leg.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_ARMOR_FOOT:\r\n\t\t\tif ( m_equipment.foot.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.foot.itemID;\r\n\t\t\t\twiSID    = m_equipment.foot.item;\r\n\t\t\t\twiMat    = m_equipment.foot.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_LEFT_HAND_HELD:\r\n\t\t\tif ( m_equipment.leftHandHeld.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.leftHandHeld.itemID;\r\n\t\t\t\twiSID    = m_equipment.leftHandHeld.item;\r\n\t\t\t\twiMat    = m_equipment.leftHandHeld.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_RIGHT_HAND_HELD:\r\n\t\t\tif ( m_equipment.rightHandHeld.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.rightHandHeld.itemID;\r\n\t\t\t\twiSID    = m_equipment.rightHandHeld.item;\r\n\t\t\t\twiMat    = m_equipment.rightHandHeld.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase CP_BACK:\r\n\t\t\tif ( m_equipment.back.itemID )\r\n\t\t\t{\r\n\t\t\t\twornItem = m_equipment.back.itemID;\r\n\t\t\t\twiSID    = m_equipment.back.item;\r\n\t\t\t\twiMat    = m_equipment.back.material;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif ( wornItem )\r\n\t{\r\n\t\tif ( wiSID != item || ( ( wiMat != material ) && ( material != \"any\" ) ) )\r\n\t\t{\r\n\t\t\tlog( \"Drop item:\" + wiMat + \" \" + wiSID + \" looking for:\" + material + \" \" + item );\r\n\t\t\t//drop current item\r\n\t\t\tdropped = true;\r\n\t\t\tg->inv()->putDownItem( wornItem, m_position );\r\n\t\t\tg->inv()->setInJob( wornItem, 0 );\r\n\r\n\t\t\tif ( item == \"none\" || item.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !item.isEmpty() )\r\n\t{\r\n\t\tauto itemToGet = g->inv()->getClosestItem( m_position, true, item, material );\r\n\r\n\t\tif ( itemToGet )\r\n\t\t{\r\n\t\t\tauto pos = g->inv()->getItemPos( itemToGet );\r\n\r\n\t\t\tm_btBlackBoard.insert( \"ClaimedUniformItem\", itemToGet );\r\n\t\t\tm_btBlackBoard.insert( \"ClaimedUniformItemSlot\", slot );\r\n\r\n\t\t\tm_jobID = g->jm()->addJob( \"EquipItem\", pos, 0, true );\r\n\r\n\t\t\tif ( m_jobID != 0 )\r\n\t\t\t{\r\n\t\t\t\tm_jobChanged = true;\r\n\t\t\t\tm_job        = g->jm()->getJob( m_jobID );\r\n\t\t\t\tif ( m_job )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setInJob( itemToGet, m_jobID );\r\n\t\t\t\t\t//no change to jobsprite\r\n\t\t\t\t\tg->jm()->setJobBeingWorked( m_jobID, true );\r\n\t\t\t\t\tm_job->setIsWorked( true );\r\n\t\t\t\t\tm_job->setWorkedBy( m_id );\r\n\t\t\t\t\tm_job->setDestroyOnAbort( true );\r\n\t\t\t\t\tlog( \"JobType \" + m_job->type() );\r\n\t\t\t\t\tm_btBlackBoard.insert( \"JobType\", m_job->type() );\r\n\t\t\t\t\tm_currentAction = \"job\";\r\n\r\n\t\t\t\t\tm_workPositionQueue = PriorityQueue<Position, int>();\r\n\t\t\t\t\tm_workPositionQueue.put( pos, m_position.distSquare( pos ) );\r\n\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\nBT_RESULT Gnome::actionCheckUniform( bool halt = false )\r\n{\r\n\tif ( GameState::tick > m_nextUniformCheckTick )\r\n\t{\r\n\t\tif ( m_roleID )\r\n\t\t{\r\n\t\t\tUniform* uniform = g->mil()->uniform( m_roleID );\r\n\t\t\tif ( uniform )\r\n\t\t\t{\r\n\t\t\t\tbool dropped = false;\r\n\t\t\t\tbool success = false;\r\n\t\t\t\tif ( checkUniformItem( \"HeadArmor\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.head.item.clear();\r\n\t\t\t\t\t\tm_equipment.head.material.clear();\r\n\t\t\t\t\t\tm_equipment.head.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.head.materialID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"ChestArmor\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.chest.item.clear();\r\n\t\t\t\t\t\tm_equipment.chest.material.clear();\r\n\t\t\t\t\t\tm_equipment.chest.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.chest.materialID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"ArmArmor\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.arm.item.clear();\r\n\t\t\t\t\t\tm_equipment.arm.material.clear();\r\n\t\t\t\t\t\tm_equipment.arm.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.arm.materialID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"HandArmor\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.hand.item.clear();\r\n\t\t\t\t\t\tm_equipment.hand.material.clear();\r\n\t\t\t\t\t\tm_equipment.hand.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.hand.materialID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"LegArmor\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.leg.item.clear();\r\n\t\t\t\t\t\tm_equipment.leg.material.clear();\r\n\t\t\t\t\t\tm_equipment.leg.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.leg.materialID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"FootArmor\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.foot.item.clear();\r\n\t\t\t\t\t\tm_equipment.foot.material.clear();\r\n\t\t\t\t\t\tm_equipment.foot.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.foot.materialID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"Back\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.back.item.clear();\r\n\t\t\t\t\t\tm_equipment.back.material.clear();\r\n\t\t\t\t\t\tm_equipment.back.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.back.materialID = 0;\r\n\r\n\t\t\t\t\t\tif ( m_inventoryItems.size() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tfor ( auto item : m_inventoryItems )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tg->inv()->setInJob( item, 0 );\r\n\t\t\t\t\t\t\t\tg->inv()->putDownItem( item, m_position );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tm_inventoryItems.clear();\r\n\t\t\t\t\t\t\tm_carriedDrinks   = 0;\r\n\t\t\t\t\t\t\tm_carriedFood     = 0;\r\n\t\t\t\t\t\t\tm_carriedBandages = 0;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"LeftHandHeld\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.leftHandHeld.item.clear();\r\n\t\t\t\t\t\tm_equipment.leftHandHeld.material.clear();\r\n\t\t\t\t\t\tm_equipment.leftHandHeld.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.leftHandHeld.materialID = 0;\r\n\r\n\t\t\t\t\t\tequipHand( 0, \"Left\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( checkUniformItem( \"RightHandHeld\", uniform, dropped ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( dropped )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_equipment.rightHandHeld.item.clear();\r\n\t\t\t\t\t\tm_equipment.rightHandHeld.material.clear();\r\n\t\t\t\t\t\tm_equipment.rightHandHeld.itemID     = 0;\r\n\t\t\t\t\t\tm_equipment.rightHandHeld.materialID = 0;\r\n\r\n\t\t\t\t\t\tequipHand( 0, \"Right\" );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsuccess = true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( dropped )\r\n\t\t\t\t{\r\n\t\t\t\t\tupdateSprite();\r\n\t\t\t\t}\r\n\t\t\t\tif ( success )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_nextUniformCheckTick = GameState::tick + 300;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( m_uniformWorn )\r\n\t\t\t{\r\n\t\t\t\tUniform uniform;\r\n\t\t\t\tbool dropped = false;\r\n\t\t\t\tcheckUniformItem( \"HeadArmor\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"ChestArmor\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"ArmArmor\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"HandArmor\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"LegArmor\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"FootArmor\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"LeftHandHeld\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"RightHandHeld\", &uniform, dropped );\r\n\t\t\t\tcheckUniformItem( \"Back\", &uniform, dropped );\r\n\t\t\t\tequipHand( 0, \"Left\" );\r\n\t\t\t\tequipHand( 0, \"Right\" );\r\n\t\t\t\tm_uniformWorn = false;\r\n\t\t\t\tif ( dropped )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_equipment.clearAllItems();\r\n\t\t\t\t\tupdateSprite();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionUniformCleanUp( bool halt )\r\n{\r\n\tauto item = m_btBlackBoard.value( \"ClaimedUniformItem\" ).toUInt();\r\n\tg->inv()->setInJob( item, 0 );\r\n\tm_btBlackBoard.remove( \"ClaimedUniformItem\" );\r\n\tm_btBlackBoard.remove( \"ClaimedUniformItemSlot\" );\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionCheckBandages( bool halt )\r\n{\r\n\tif ( m_equipment.back.item == \"Backpack\" )\r\n\t{\r\n\t\tunsigned int itemToGet = 0;\r\n\t\tif ( m_carryBandages && m_carriedBandages < 3 )\r\n\t\t{\r\n\t\t\titemToGet = g->inv()->getClosestItem( m_position, true, \"Bandage\", \"any\" );\r\n\t\t}\r\n\t\telse if ( m_carryFood && m_carriedFood < 3 )\r\n\t\t{\r\n\t\t\titemToGet = g->inv()->getFoodItem( m_position );\r\n\t\t\tif ( itemToGet )\r\n\t\t\t{\r\n\t\t\t\tif ( m_position.distSquare( g->inv()->getItemPos( itemToGet ) ) > 10 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_carryDrinks && m_carriedDrinks < 3 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\titemToGet = g->inv()->getDrinkItem( m_position );\r\n\t\t\t\t\t\tif ( m_position.distSquare( g->inv()->getItemPos( itemToGet ) ) > 10 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\titemToGet = 0;\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\telse if ( m_carryDrinks && m_carriedDrinks < 3 )\r\n\t\t{\r\n\t\t\titemToGet = g->inv()->getDrinkItem( m_position );\r\n\t\t\tif ( m_position.distSquare( g->inv()->getItemPos( itemToGet ) ) > 10 )\r\n\t\t\t{\r\n\t\t\t\titemToGet = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( itemToGet )\r\n\t\t{\r\n\t\t\tauto pos = g->inv()->getItemPos( itemToGet );\r\n\t\t\tg->inv()->setInJob( itemToGet, m_id );\r\n\t\t\tm_itemToPickUp = itemToGet;\r\n\t\t\tm_btBlackBoard.insert( \"ClaimedInventoryItem\", itemToGet );\r\n\t\t\tsetCurrentTarget( pos );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionGetItemDropPosition( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionGetItemDropPosition\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tPosition pos = m_job->posItemInput();\r\n\tif ( pos.isZero() )\r\n\t{\r\n\t\t//abortJob( \"actionGetItemDropPosition()\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tsetCurrentTarget( pos );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionDropItem( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionDropItem\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\twhile ( m_carriedItems.size() )\r\n\t{\r\n\t\tunsigned int carriedItem = m_carriedItems.takeFirst();\r\n\t\tif ( carriedItem != 0 )\r\n\t\t{\r\n\t\t\tg->inv()->putDownItem( carriedItem, m_position );\r\n\t\t\tif ( m_job->stockpile() != 0 )\r\n\t\t\t{\r\n\t\t\t\tlog( \"Put \" + g->inv()->materialSID( carriedItem ) + \" \" + g->inv()->itemSID( carriedItem ) + \" into stockpile at \" + m_position.toString() );\r\n\t\t\t\tg->spm()->insertItem( m_job->stockpile(), m_position, carriedItem );\r\n\t\t\t}\r\n\t\t\t//m_job->removeClaimedItem2( item );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t\t/*\r\n\t\telse\r\n\t\t{\r\n\t\t\tqDebug() << name() << \"drop item failed - null item\";\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t\t*/\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionDropAllItems( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionDropItem\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tfor ( auto item : m_carriedItems )\r\n\t{\r\n\t\tif ( item )\r\n\t\t{\r\n\t\t\tg->inv()->putDownItem( item, m_position );\r\n\t\t\tif ( m_job->stockpile() != 0 )\r\n\t\t\t{\r\n\t\t\t\tlog( \"Put \" + g->inv()->materialSID( item ) + \" \" + g->inv()->itemSID( item ) + \" into stockpile at \" + m_position.toString() );\r\n\t\t\t\tg->spm()->insertItem( m_job->stockpile(), m_position, item );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_carriedItems.clear();\r\n\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionGetWorkPosition( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionGetWorkPosition\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tsetCurrentTarget( m_job->workPos() );\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::actionWork( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionWork\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionWorkJob() - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_job->isCanceled() )\r\n\t{\r\n\t\t//abortJob( \"Canceled\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\t//first visit\r\n\tif ( m_currentAction != \"work job\" )\r\n\t{\r\n\t\tm_currentAction = \"work job\";\r\n\t\tm_taskList      = DB::selectRows( \"Jobs_Tasks\", \"ID\", m_job->type() );\r\n\t\tif ( m_taskList.size() > 0 )\r\n\t\t{\r\n\t\t\tm_currentTask = m_taskList.takeFirst();\r\n\r\n\t\t\tQString skillID = m_job->requiredSkill();\r\n\t\t\tfloat current   = Global::util->reverseFib( m_skills.value( skillID ).toUInt() );\r\n\t\t\tfloat ticks     = getDurationTicks( m_currentTask.value( \"Duration\" ), m_job );\r\n\r\n\t\t\tticks                = qMax( 10., qMin( 1000., ticks - ( ( ticks / 20. ) * current ) ) );\r\n\t\t\tm_taskFinishTick     = GameState::tick + ticks;\r\n\t\t\tm_totalDurationTicks = ticks;\r\n\t\t\tg->sm()->playEffect( m_job->type(), m_position, m_job->item() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// job has no task, that's for example the case with hauling jobs\r\n\t\t\tlog( \"Nothing else to do.\" );\r\n\t\t\tm_currentTask.clear();\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\r\n\tQString taskName = m_currentTask.value( \"Task\" ).toString();\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\tif ( m_taskFunctions.contains( taskName + \"Animate\" ) )\r\n\t\t{\r\n\t\t\tm_taskFunctions[taskName + \"Animate\"]();\r\n\t\t}\r\n\t\tif ( (m_taskFinishTick-GameState::tick) % 60 == 0) {\r\n\t\t\t// Play sound again\r\n\t\t\tg->sm()->playEffect( m_job->type(), m_position, m_job->item() );\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tif ( m_taskFunctions.contains( taskName ) )\r\n\t{\r\n\t\tif ( !m_taskFunctions[taskName]() )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\r\n\t\tif ( m_repeatJob )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\r\n\t\tif ( m_taskList.size() > 0 )\r\n\t\t{\r\n\t\t\tm_currentTask = m_taskList.takeFirst();\r\n\r\n\t\t\tQString skillID = m_job->requiredSkill();\r\n\t\t\tfloat current   = Global::util->reverseFib( m_skills.value( skillID ).toUInt() );\r\n\t\t\tfloat ticks     = getDurationTicks( m_currentTask.value( \"Duration\" ), m_job );\r\n\t\t\tif ( ticks > 0 )\r\n\t\t\t{\r\n\t\t\t\tticks = qMax( 10., qMin( 1000., ticks - ( ( ticks / 20. ) * current ) ) );\r\n\t\t\t}\r\n\t\t\tm_taskFinishTick     = GameState::tick + ticks;\r\n\t\t\tm_totalDurationTicks = ticks;\r\n\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_job->setCanceled();\r\n\t\t//abortJob( \"task name doesn't exist -\" + taskName + \" - \"  );\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionGrabAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionGrabAnimal\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\tif ( !a || a->toDestroy() )\r\n\t{\r\n\t\t//abortJob( \"grabAnimal()\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ta->setFollowID( m_id );\r\n\t\tm_animal = m_job->animal();\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n}\r\n\r\nBT_RESULT Gnome::actionReleaseAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionReleaseAnimal\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tm_animal  = 0;\r\n\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\tif ( a )\r\n\t{\r\n\t\ta->setFollowID( 0 );\r\n\t\ta->setImmobile( false );\r\n\t\ta->setInJob( 0 );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionFinalMoveAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionFinalMoveAnimal\" );\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tauto animal = g->cm()->animal( m_animal );\r\n\tif ( animal )\r\n\t{\r\n\t\tanimal->setFollowPosition( m_position );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionButcherAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionButcherAnimal\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionButcherAnimal() - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_job->isAborted() )\r\n\t{\r\n\t\tm_job->setAborted( false );\r\n\t\t//abortJob( \"Aborted\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( m_job->isCanceled() )\r\n\t{\r\n\t\t//abortJob( \"Canceled\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\t//first visit?\r\n\tif ( m_currentAction != \"butcher animal\" )\r\n\t{\r\n\t\tm_currentAction = \"butcher animal\";\r\n\r\n\t\tQString skillID      = m_job->requiredSkill();\r\n\t\tfloat current        = Global::util->reverseFib( m_skills.value( skillID ).toUInt() );\r\n\t\tm_totalDurationTicks = 50; //TODO get that number from DB\r\n\t\tm_taskFinishTick     = GameState::tick + 50;\r\n\t}\r\n\r\n\tQString taskName = m_currentTask.value( \"Task\" ).toString();\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\tif ( a )\r\n\t{\r\n\t\ta->setFollowID( 0 );\r\n\t\tm_animal = 0;\r\n\r\n\t\tif ( a->pastureID() )\r\n\t\t{\r\n\t\t\tauto pasture = g->fm()->getPasture( a->pastureID() );\r\n\t\t\tif ( pasture )\r\n\t\t\t{\r\n\t\t\t\tpasture->removeAnimal( a->id() );\r\n\t\t\t\tg->fm()->emitUpdateSignalPasture( pasture->id() );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tauto onbutchlist = DB::selectRows( \"Animals_OnButcher\", \"ID\", a->species() );\r\n\t\tfor ( auto obv : onbutchlist )\r\n\t\t{\r\n\t\t\tauto obm       = obv;\r\n\t\t\tQString itemID = obm.value( \"ItemID\" ).toString();\r\n\t\t\tint amount     = obm.value( \"Amount\" ).toInt();\r\n\t\t\tif ( a->isYoung() )\r\n\t\t\t{\r\n\t\t\t\tamount /= 2;\r\n\t\t\t}\r\n\t\t\tfor ( int i = 0; i < amount; ++i )\r\n\t\t\t{\r\n\t\t\t\tif ( itemID == \"Bone\" || itemID == \"Skull\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( m_job->posItemOutput(), itemID, { a->species() + \"Bone\" } );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( m_job->posItemOutput(), itemID, { a->species() } );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\ta->destroy();\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionDyeAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionDyeAnimal\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionButcherAnimal() - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_job->isAborted() )\r\n\t{\r\n\t\tm_job->setAborted( false );\r\n\t\t//abortJob( \"Aborted\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( m_job->isCanceled() )\r\n\t{\r\n\t\t//abortJob( \"Canceled\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\t//first visit?\r\n\tif ( m_currentAction != \"dye animal\" )\r\n\t{\r\n\t\tm_currentAction = \"dye animal\";\r\n\r\n\t\tQString skillID      = m_job->requiredSkill();\r\n\t\tfloat current        = Global::util->reverseFib( m_skills.value( skillID ).toUInt() );\r\n\t\tm_totalDurationTicks = 50; //TODO get that number from DB\r\n\t\tm_taskFinishTick     = GameState::tick + 50;\r\n\t}\r\n\r\n\tQString taskName = m_currentTask.value( \"Task\" ).toString();\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\tif ( a )\r\n\t{\r\n\t\ta->setFollowID( 0 );\r\n\t\tm_animal = 0;\r\n\r\n\t\tdestroyClaimedItems();\r\n\r\n\t\ta->setDye( m_job->material() );\r\n\t\ta->setInJob( 0 );\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionHarvestAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionHarvestAnimal\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionButcherAnimal() - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( m_job->isAborted() )\r\n\t{\r\n\t\tm_job->setAborted( false );\r\n\t\t//abortJob( \"Aborted\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( m_job->isCanceled() )\r\n\t{\r\n\t\t//abortJob( \"Canceled\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\t//first visit?\r\n\tif ( m_currentAction != \"harvest animal\" )\r\n\t{\r\n\t\tm_currentAction = \"harvest animal\";\r\n\r\n\t\tQString skillID      = m_job->requiredSkill();\r\n\t\tfloat current        = Global::util->reverseFib( m_skills.value( skillID ).toUInt() );\r\n\t\tm_totalDurationTicks = 100;\r\n\t\tm_taskFinishTick     = GameState::tick + 100;\r\n\t}\r\n\r\n\tQString taskName = m_currentTask.value( \"Task\" ).toString();\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tAnimal* a = g->cm()->animal( m_animal );\r\n\tif ( a )\r\n\t{\r\n\t\tQString type = a->species();\r\n\t\tQString dye  = a->dye();\r\n\r\n\t\tint amount     = a->numProduce();\r\n\t\tQString itemID = a->producedItem();\r\n\r\n\t\tif ( !dye.isEmpty() )\r\n\t\t{\r\n\t\t\ttype = Global::util->addDyeMaterial( type, dye );\r\n\t\t}\r\n\r\n\t\tfor ( int i = 0; i < amount; ++i )\r\n\t\t{\r\n\t\t\tg->inv()->createItem( m_position, itemID, { type } );\r\n\t\t}\r\n\t\ta->harvest();\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionTameAnimal( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionTameAnimal\" );\r\n\tif ( halt )\r\n\t{\r\n\t\t//abortJob( \"actionButcherAnimal() - halt\" );\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( m_job->isAborted() )\r\n\t{\r\n\t\tm_job->setAborted( false );\r\n\t\t//abortJob( \"Aborted\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\tif ( m_job->isCanceled() )\r\n\t{\r\n\t\t//abortJob( \"Canceled\" );\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\t//first visit?\r\n\tif ( m_currentAction != \"tame animal\" )\r\n\t{\r\n\t\tm_currentAction = \"tame animal\";\r\n\r\n\t\tQString skillID      = m_job->requiredSkill();\r\n\t\tfloat current        = Global::util->reverseFib( m_skills.value( skillID ).toUInt() );\r\n\t\tm_totalDurationTicks = 100;\r\n\t\tm_taskFinishTick     = GameState::tick + 100;\r\n\t}\r\n\r\n\tif ( GameState::tick < m_taskFinishTick )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tAnimal* a = g->cm()->animal( m_job->animal() );\r\n\tif ( a )\r\n\t{\r\n\t\ta->setTame( true );\r\n\r\n\t\tauto pasture = g->fm()->getPastureAtPos( m_job->posItemInput() );\r\n\r\n\t\tpasture->addAnimal( a->id() );\r\n\t\tlog( \"Tamed a \" + a->species() );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\tlog( \"Failed to tame.\" );\r\n\t//abortJob( \"tame failed\" );\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionAlwaysRunning( bool halt )\r\n{\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Gnome::actionAttackTarget( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionAttackTarget\" );\r\n\tCreature* creature = g->cm()->creature( m_currentAttackTarget );\r\n\r\n\tif ( creature && !creature->isDead() )\r\n\t{\r\n\t\tm_facing = getFacing( m_position, creature->getPos() );\r\n\r\n\t\t//do we have\r\n\t\tif ( m_globalCooldown <= 0 )\r\n\t\t{\r\n\t\t\tif ( m_rightHandArmed || m_leftHandArmed )\r\n\t\t\t{\r\n\t\t\t\tif ( m_rightHandCooldown <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" attacks \" + creature->name(), m_id );\r\n\t\t\t\t\t// attack with main hand\r\n\t\t\t\t\tcreature->attack( DT_SLASH, m_anatomy.randomAttackHeight(), m_rightHandAttackSkill, m_rightHandAttackValue, m_position, m_id );\r\n\t\t\t\t\tm_rightHandCooldown = qMax( 5, 20 - m_rightHandAttackSkill );\r\n\t\t\t\t\tm_globalCooldown    = 5;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( m_leftHandCooldown <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// wielding an offhand weapon?\r\n\t\t\t\t\tif ( m_leftHandHasWeapon )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" attacks \" + creature->name(), m_id );\r\n\t\t\t\t\t\tcreature->attack( DT_SLASH, m_anatomy.randomAttackHeight(), m_leftHandAttackSkill, m_leftHandAttackValue, m_position, m_id );\r\n\t\t\t\t\t\tm_leftHandCooldown = qMax( 5, 20 - m_leftHandAttackSkill );\r\n\t\t\t\t\t\tm_globalCooldown   = 5;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse //unarmed combat\r\n\t\t\t{\r\n\t\t\t\tif ( m_rightHandCooldown <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" punches \" + creature->name(), m_id );\r\n\t\t\t\t\t// attack with main hand\r\n\t\t\t\t\tcreature->attack( DT_BLUNT, m_anatomy.randomAttackHeight(), m_rightHandAttackSkill, m_rightHandAttackValue, m_position, m_id );\r\n\t\t\t\t\tm_rightHandCooldown = qMax( 5, 20 - m_rightHandAttackSkill );\r\n\t\t\t\t\tm_globalCooldown    = 5;\r\n\t\t\t\t}\r\n\t\t\t\telse if ( m_leftHandCooldown <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t// wielding an offhand weapon?\r\n\t\t\t\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" punches \" + creature->name(), m_id );\r\n\t\t\t\t\tcreature->attack( DT_BLUNT, m_anatomy.randomAttackHeight(), m_leftHandAttackSkill, m_leftHandAttackValue, m_position, m_id );\r\n\t\t\t\t\tm_leftHandCooldown = qMax( 5, 20 - m_leftHandAttackSkill );\r\n\t\t\t\t\tm_globalCooldown   = 5;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindTrainingGround( bool halt )\r\n{\r\n\tauto tgs = g->wsm()->getTrainingGrounds();\r\n\r\n\tPriorityQueue<Workshop*, int> pq;\r\n\r\n\tfor ( auto tg : tgs )\r\n\t{\r\n\t\tif ( g->pf()->checkConnectedRegions( m_position, tg->pos() ) )\r\n\t\t{\r\n\t\t\tpq.put( tg, m_position.distSquare( tg->pos() ) );\r\n\t\t}\r\n\t}\r\n\tif ( !pq.empty() )\r\n\t{\r\n\t\tauto tg = pq.get();\r\n\t\tsetCurrentTarget( tg->pos() );\r\n\t\tm_trainCounter   = -1;\r\n\t\tm_trainingGround = tg->id();\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionTrain( bool halt )\r\n{\r\n\tif ( m_trainCounter == 0 )\r\n\t{\r\n\t\tm_log.append( \"Finished Training session.\" );\r\n\t\tm_trainCounter = -1;\r\n\t\tauto ws        = g->wsm()->workshop( m_trainingGround );\r\n\t\tif ( ws )\r\n\t\t{\r\n\t\t\tQString type = ws->type();\r\n\t\t\tif ( type == \"MeleeTraining\" )\r\n\t\t\t{\r\n\t\t\t\tunsigned int trainer = ws->assignedGnome();\r\n\t\t\t\tint skillGain        = 3;\r\n\t\t\t\tif ( trainer )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto tg = g->gm()->gnome( trainer );\r\n\t\t\t\t\tif ( tg )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( tg->getPos() == ws->inputPos() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( tg->getSkillLevel( \"Melee\" ) > getSkillLevel( \"Melee\" ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tskillGain = 6;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif ( tg->getSkillLevel( \"Dodge\" ) > getSkillLevel( \"Dodge\" ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tskillGain = 6;\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\tgainSkill( \"Melee\", skillGain );\r\n\t\t\t\tgainSkill( \"Dodge\", skillGain );\r\n\t\t\t\tm_log.append( \"Gained \" + QString::number( skillGain ) + \"xp in \" + S::s( \"$SkillName_Melee\" ) );\r\n\t\t\t\tm_log.append( \"Gained \" + QString::number( skillGain ) + \"xp in \" + S::s( \"$SkillName_Dodge\" ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_thoughtBubble = \"\";\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\telse if ( m_trainCounter < 0 )\r\n\t{\r\n\t\t// starting training;\r\n\t\tm_trainCounter = Global::util->ticksPerMinute * 15;\r\n\t}\r\n\tm_trainCounter  = qMax( 0, m_trainCounter - 1 );\r\n\tm_thoughtBubble = \"Combat\";\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Gnome::actionFindTrainerPosition( bool halt )\r\n{\r\n\tif ( m_assignedWorkshop )\r\n\t{\r\n\t\tauto ws = g->wsm()->workshop( m_assignedWorkshop );\r\n\t\tif ( ws )\r\n\t\t{\r\n\t\t\tsetCurrentTarget( ws->inputPos() );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\tm_assignedWorkshop = 0;\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionSuperviseTraining( bool halt )\r\n{\r\n\tif ( m_trainCounter == 0 )\r\n\t{\r\n\t\tm_log.append( \"Finished trainer session.\" );\r\n\t\tm_trainCounter = -1;\r\n\t\tauto ws        = g->wsm()->workshop( m_assignedWorkshop );\r\n\t\tif ( ws )\r\n\t\t{\r\n\t\t\tQString type = ws->type();\r\n\t\t\tif ( type == \"MeleeTraining\" )\r\n\t\t\t{\r\n\t\t\t\tgainSkill( \"Melee\", 1 );\r\n\t\t\t\tgainSkill( \"Dodge\", 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_thoughtBubble = \"\";\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\telse if ( m_trainCounter < 0 )\r\n\t{\r\n\t\t// starting training;\r\n\t\tm_trainCounter = Global::util->ticksPerMinute * 15;\r\n\t}\r\n\tm_trainCounter  = qMax( 0, m_trainCounter - 1 );\r\n\tm_thoughtBubble = \"Combat\";\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Gnome::actionGetTarget( bool halt )\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionGetTarget\" );\r\n\r\n\t//!TODO Decide when else to invalidate current target, e.g. because there might a target of higher priority closer to us\r\n\r\n\t// Unset current attack target if invalidated\r\n\tif ( m_currentAttackTarget )\r\n\t{\r\n\t\tconst Creature* creature = g->cm()->creature( m_currentAttackTarget );\r\n\t\tif ( !creature || creature->isDead() || !g->cm()->hasPathTo( m_position, creature->id() ) )\r\n\t\t{\r\n\t\t\tm_currentAttackTarget = 0;\r\n\t\t\tm_thoughtBubble       = \"\";\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Update target position\r\n\t\t\tsetCurrentTarget( creature->getPos() );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !m_currentAttackTarget )\r\n\t{\r\n\t\tconst Creature* bestCandidate = nullptr;\r\n\t\tunsigned int bestDistance     = std::numeric_limits<unsigned int>::max();\r\n\r\n\t\tconst Squad* squad = g->mil()->getSquadForGnome( m_id );\r\n\t\tif ( squad )\r\n\t\t{\r\n\t\t\t// Search for targets already attacked by squad mates first\r\n\t\t\tfor ( const auto& gnomeID : squad->gnomes )\r\n\t\t\t{\r\n\t\t\t\tconst Gnome* gnome = g->gm()->gnome( gnomeID );\r\n\t\t\t\tif ( gnome && gnome->m_currentAttackTarget )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst Creature* creature = g->cm()->creature( gnome->m_currentAttackTarget );\r\n\t\t\t\t\tif ( creature && g->cm()->hasPathTo( m_position, creature->id() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst unsigned int dist = m_position.distSquare( creature->getPos() );\r\n\t\t\t\t\t\tbestDistance            = dist;\r\n\t\t\t\t\t\tbestCandidate           = creature;\r\n\t\t\t\t\t\t// Any legal match is a good hit\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 ( !bestCandidate )\r\n\t\t\t{\r\n\t\t\t\t// Next search for hunting targets, anything we could reach\r\n\t\t\t\tfor ( const auto& prio : squad->priorities )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( prio.attitude != MilAttitude::FLEE )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tconst auto& targetSet = g->cm()->animalsByType( prio.type );\r\n\t\t\t\t\t\t//!TODO Sort huntTargets into buckets by regionm so hasPathTo will never fail\r\n\t\t\t\t\t\tfor ( const auto& targetID : targetSet )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tconst Creature* creature = g->cm()->creature( targetID );\r\n\t\t\t\t\t\t\tif ( creature && !creature->isDead() && g->cm()->hasPathTo( m_position, targetID ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tconst unsigned int dist = m_position.distSquare( creature->getPos() );\r\n\t\t\t\t\t\t\t\tif ( prio.attitude == MilAttitude::ATTACK && ( dist >= 100 || !g->cm()->hasLineOfSightTo( m_position, targetID ) ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Skip attack targets which we don't see ourselves\r\n\t\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tif ( prio.attitude == MilAttitude::DEFEND && ( dist >= 4 || !g->cm()->hasLineOfSightTo( m_position, targetID ) ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t// Skip targets which are not adjacent\r\n\t\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tif ( dist < bestDistance )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tbestDistance  = dist;\r\n\t\t\t\t\t\t\t\t\tbestCandidate = creature;\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}\r\n\t\t\t\t\t\t// Got the closest target\r\n\t\t\t\t\t\tif ( bestCandidate )\r\n\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\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !bestCandidate )\r\n\t\t{\r\n\t\t\twhile ( m_aggroList.size() )\r\n\t\t\t{\r\n\t\t\t\tunsigned int targetID = m_aggroList.first().id;\r\n\t\t\t\tCreature* creature    = g->cm()->creature( targetID );\r\n\r\n\t\t\t\t//!TODO Check if creature isn't in \"flee\" category\r\n\t\t\t\tif ( creature && !creature->isDead() && g->cm()->hasPathTo( m_position, targetID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst auto dist = m_position.distSquare( creature->getPos() );\r\n\t\t\t\t\tbestDistance    = dist;\r\n\t\t\t\t\tbestCandidate   = creature;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_aggroList.pop_front();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( bestCandidate )\r\n\t\t{\r\n\t\t\tm_currentAttackTarget = bestCandidate->id();\r\n\t\t\tsetCurrentTarget( bestCandidate->getPos() );\r\n\t\t\tm_thoughtBubble = \"Combat\";\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn m_currentAttackTarget ? BT_RESULT::SUCCESS : BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionDoMission( bool halt )\r\n{\r\n\tif ( m_mission )\r\n\t{\r\n\t\tif ( GameState::tick >= m_nextCheckTick )\r\n\t\t{\r\n\t\t\tauto mission = g->em()->getMission( m_mission );\r\n\r\n\t\t\tif ( !mission )\r\n\t\t\t{\r\n\t\t\t\t// how is that possible?\r\n\t\t\t\t// need to return the gnome to this world\r\n\t\t\t\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\t\t\t\tm_goneOffMap    = false;\r\n\t\t\t\tm_mission       = 0;\r\n\t\t\t\tm_isOnMission   = false;\r\n\t\t\t\tm_nextCheckTick = 0;\r\n\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t}\r\n\r\n\t\t\tswitch ( mission->step )\r\n\t\t\t{\r\n\t\t\t\tcase MissionStep::TRAVEL:\r\n\t\t\t\t{\r\n\t\t\t\t\tint hours = ( GameState::tick - mission->startTick ) / ( Global::util->ticksPerMinute * Global::util->minutesPerHour );\r\n\r\n\t\t\t\t\tswitch ( mission->type )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase MissionType::EXPLORE:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tfor ( auto& kingdom : g->nm()->kingdoms() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( !kingdom.discovered && !kingdom.discoverMission )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( kingdom.distance <= hours )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tkingdom.discoverMission = true;\r\n\t\t\t\t\t\t\t\t\t\tmission->result.insert( \"Success\", true );\r\n\t\t\t\t\t\t\t\t\t\tmission->result.insert( \"DiscoveredKingdom\", kingdom.id );\r\n\t\t\t\t\t\t\t\t\t\t//qDebug() << \"Found kingdom \" << kingdom.name << kingdom.id;\r\n\t\t\t\t\t\t\t\t\t\tmission->nextCheckTick = GameState::tick + ( GameState::tick - mission->startTick );\r\n\t\t\t\t\t\t\t\t\t\tm_nextCheckTick        = mission->nextCheckTick;\r\n\t\t\t\t\t\t\t\t\t\tmission->step          = MissionStep::RETURN;\r\n\t\t\t\t\t\t\t\t\t\treturn BT_RESULT::RUNNING;\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\tif ( hours > 300 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmission->result.insert( \"Success\", false );\r\n\t\t\t\t\t\t\t\t//qDebug() << \"Found nothing, returning\";\r\n\t\t\t\t\t\t\t\tmission->nextCheckTick = GameState::tick + ( GameState::tick - mission->startTick );\r\n\t\t\t\t\t\t\t\tm_nextCheckTick        = mission->nextCheckTick;\r\n\t\t\t\t\t\t\t\tmission->step          = MissionStep::RETURN;\r\n\t\t\t\t\t\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::EMISSARY:\r\n\t\t\t\t\t\tcase MissionType::RAID:\r\n\t\t\t\t\t\tcase MissionType::SPY:\r\n\t\t\t\t\t\tcase MissionType::SABOTAGE:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( mission->distance <= hours )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tmission->step = MissionStep::ACTION;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tmission->nextCheckTick = GameState::tick + Global::util->ticksPerDay;\r\n\t\t\t\t\tm_nextCheckTick        = mission->nextCheckTick;\r\n\t\t\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t\tcase MissionStep::ACTION:\r\n\t\t\t\t\tswitch ( mission->type )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase MissionType::EXPLORE:\r\n\t\t\t\t\t\t\t//not used\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::EMISSARY:\r\n\t\t\t\t\t\t\tg->nm()->emissary( mission );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::RAID:\r\n\t\t\t\t\t\t\tg->nm()->raid( mission );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::SPY:\r\n\t\t\t\t\t\t\tg->nm()->spy( mission );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::SABOTAGE:\r\n\t\t\t\t\t\t\tg->nm()->sabotage( mission );\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tmission->nextCheckTick = GameState::tick + mission->distance * Global::util->ticksPerMinute * Global::util->minutesPerHour;\r\n\t\t\t\t\tm_nextCheckTick        = mission->nextCheckTick;\r\n\t\t\t\t\tmission->step          = MissionStep::RETURN;\r\n\t\t\t\t\treturn BT_RESULT::RUNNING;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase MissionStep::RETURN:\r\n\t\t\t\t\tswitch ( mission->type )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase MissionType::EXPLORE:\r\n\t\t\t\t\t\t\tif ( mission->result.contains( \"DiscoveredKingdom\" ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tunsigned int kingdomID = mission->result.value( \"DiscoveredKingdom\" ).toUInt();\r\n\t\t\t\t\t\t\t\tg->nm()->discoverKingdom( kingdomID );\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\tcase MissionType::EMISSARY:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::RAID:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::SPY:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase MissionType::SABOTAGE:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\t//qDebug() << \"Mission failure\";\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::actionLeaveForMission( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tg->w()->removeCreatureFromPosition( m_position, m_id );\r\n\tm_goneOffMap = true;\r\n\r\n\tMission* mission = g->em()->getMission( m_mission );\r\n\tif ( mission )\r\n\t{\r\n\t\tmission->leavePos = m_position;\r\n\t\tmission->step     = MissionStep::TRAVEL;\r\n\t\tm_nextCheckTick   = mission->nextCheckTick;\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_mission = 0;\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n}\r\n\r\nBT_RESULT Gnome::actionReturnFromMission( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tMission* mission = g->em()->getMission( m_mission );\r\n\tif ( mission )\r\n\t{\r\n\t\tm_position = mission->leavePos;\r\n\r\n\t\tmission->step = MissionStep::RETURNED;\r\n\t\tmission->result.insert( \"TotalTime\", ( GameState::tick - mission->startTick ) / ( Global::util->ticksPerMinute * Global::util->minutesPerHour ) );\r\n\r\n\t\t//qDebug() << \"Returning from mission at \" << m_position.toString();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// this should never be reached\r\n\t\tqDebug() << \"Returning from mission but mission doesn't exist anymore\";\r\n\t}\r\n\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\tm_goneOffMap = false;\r\n\r\n\tm_mission       = 0;\r\n\tm_isOnMission   = false;\r\n\tm_nextCheckTick = 0;\r\n\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nbool Gnome::equipItem()\r\n{\r\n\tif ( Global::debugMode )\r\n\t\tlog( \"actionEquipUniform\" );\r\n\r\n\tauto itemID = m_btBlackBoard.value( \"ClaimedUniformItem\" ).toUInt();\r\n\tm_btBlackBoard.remove( \"ClaimedUniformItem\" );\r\n\r\n\tQStringList conc;\r\n\r\n\tif ( m_position == g->inv()->getItemPos( itemID ) )\r\n\t{\r\n\t\tg->inv()->pickUpItem( itemID, m_id );\r\n\t\tg->inv()->setInJob( itemID, 0 );\r\n\r\n\t\tQString slot = m_btBlackBoard.value( \"ClaimedUniformItemSlot\" ).toString();\r\n\t\tm_btBlackBoard.remove( \"ClaimedUniformItemSlot\" );\r\n\r\n\t\tQString itemSID          = g->inv()->itemSID( itemID );\r\n\t\tunsigned int materialUID = g->inv()->materialUID( itemID );\r\n\t\tQString materialSID      = g->inv()->materialSID( itemID );\r\n\r\n\t\tauto part = Global::creaturePartLookUp.value( slot );\r\n\r\n\t\tauto& itemSlot = m_equipment.getSlot( part );\r\n\t\tif ( itemSlot.itemID )\r\n\t\t{\r\n\t\t\tqWarning() << \"Trying to equip into occupied slot!\";\r\n\t\t\tg->inv()->putDownItem( itemSlot.itemID, m_position );\r\n\t\t\tg->inv()->setInJob( itemSlot.itemID, 0 );\r\n\t\t}\r\n\t\titemSlot.itemID     = itemID;\r\n\t\titemSlot.item       = itemSID;\r\n\t\titemSlot.materialID = materialUID;\r\n\t\titemSlot.material   = materialSID;\r\n\t\tif ( part == CP_LEFT_HAND_HELD )\r\n\t\t{\r\n\t\t\tequipHand( itemID, \"Left\" );\r\n\t\t\titemSlot.allMats = g->inv()->allMats( itemID );\r\n\t\t}\r\n\t\telse if ( part == CP_RIGHT_HAND_HELD )\r\n\t\t{\r\n\t\t\tequipHand( itemID, \"Right\" );\r\n\t\t\titemSlot.allMats = g->inv()->allMats( itemID );\r\n\t\t}\r\n\r\n\t\tupdateSprite();\r\n\r\n\t\tm_uniformWorn = true;\r\n\r\n\t\tm_renderParamsChanged = true;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}"
  },
  {
    "path": "src/game/gnomeconditions.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"gnome.h\"\r\n#include \"gnomemanager.h\"\r\n#include \"game.h\"\r\n\r\n\r\n#include \"../base/enums.h\"\r\n#include \"../base/global.h\"\r\n\r\n//#include \"../base/config.h\"\r\n#include \"../base/gamestate.h\"\r\n//#include \"../base/util.h\"\r\n//#include \"../base/navmesh.h\"\r\n//#include \"../base/position.h\"\r\n\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n//#include \"../game/farmingmanager.h\"\r\n//#include \"../game/world.h\"\r\n//#include \"../game/stockpile.h\"\r\n//#include \"../game/stockpilemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/workshop.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n//#include \"../game/plant.h\"\r\n\r\n//#include \"../gui/strings.h\"\r\n\r\n//#include \"../gfx/spritefactory.h\"\r\n//#include \"../gfx/sprite.h\"\r\n\r\n#include \"../base/behaviortree/bt_node.h\"\r\n\r\n//#include <QDebug>\r\n\r\nBT_RESULT Gnome::conditionIsHungry( bool halt )\r\n{\r\n\tint hour = qMin( 23, GameState::hour );\r\n\tauto activity      = m_schedule[hour];\r\n\tif ( activity == ScheduleActivity::Eat && m_needs[\"Hunger\"].toFloat() < 90 )\r\n\t{\r\n\t\tsetThoughtBubble( \"Hungry\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tif ( m_needs[\"Hunger\"].toFloat() < 30 )\r\n\t{\r\n\t\tsetThoughtBubble( \"Hungry\" );\r\n\t\tif ( !m_hungryLog )\r\n\t\t{\r\n\t\t\tm_log.append( \"I'm hungry.\" );\r\n\t\t\tm_hungryLog = true;\r\n\t\t}\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsVeryHungry( bool halt )\r\n{\r\n\tif ( m_needs[\"Hunger\"].toFloat() < 0 )\r\n\t{\r\n\t\tsetThoughtBubble( \"Hungry\" );\r\n\t\tif ( !m_veryHungryLog )\r\n\t\t{\r\n\t\t\tm_log.append( \"I'm very hungry.\" );\r\n\t\t\tm_veryHungryLog = true;\r\n\t\t}\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsThirsty( bool halt )\r\n{\r\n\tunsigned int hour = qMin( 23, GameState::hour );\r\n\tauto activity      = m_schedule[hour];\r\n\tif ( activity == ScheduleActivity::Eat && m_needs[\"Thirst\"].toFloat() < 90 )\r\n\t{\r\n\t\tsetThoughtBubble( \"Thirsty\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tif ( m_needs[\"Thirst\"].toFloat() < 30 )\r\n\t{\r\n\t\tsetThoughtBubble( \"Thirsty\" );\r\n\t\tif ( !m_thirstyLog )\r\n\t\t{\r\n\t\t\tm_log.append( \"I'm thirsty.\" );\r\n\t\t\tm_veryThirstLog = true;\r\n\t\t}\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsVeryThirsty( bool halt )\r\n{\r\n\tif ( m_needs[\"Thirst\"].toFloat() < 0 )\r\n\t{\r\n\t\tsetThoughtBubble( \"Thirsty\" );\r\n\t\tif ( !m_veryThirstLog )\r\n\t\t{\r\n\t\t\tm_log.append( \"I'm very thirsty.\" );\r\n\t\t\tm_veryThirstLog = true;\r\n\t\t}\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsSleepy( bool halt )\r\n{\r\n\r\n\tunsigned int hour = qMin( 23, GameState::hour );\r\n\tauto activity      = m_schedule[hour];\r\n\tif ( activity == ScheduleActivity::Sleep )\r\n\t{\r\n\t\tsetThoughtBubble( \"Tired\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tif ( m_needs[\"Sleep\"].toFloat() < 30 )\r\n\t{\r\n\r\n\t\tsetThoughtBubble( \"Tired\" );\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionAllItemsInPlaceForJob( bool halt )\r\n{\r\n\tif ( !m_job || m_itemToPickUp != 0 || !m_carriedItems.isEmpty() )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tauto cil = claimedItems();\r\n\r\n\tPosition inputPos = m_job->posItemInput();\r\n\r\n\tfor ( auto ci : cil )\r\n\t{\r\n\t\tif ( g->inv()->getItemPos( ci ) != inputPos )\r\n\t\t{\r\n\t\t\tm_itemToPickUp = ci;\r\n\t\t\tsetCurrentTarget( g->inv()->getItemPos( ci ) );\r\n\t\t\tlog( \"Item is at \" + g->inv()->getItemPos( ci ).toString() + \" and must go to \" + inputPos.toString() );\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsButcherJob( bool halt )\r\n{\r\n\tif ( m_job )\r\n\t{\r\n\t\tif ( m_job->type() == \"ButcherAnimal\" )\r\n\t\t{\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionAllPickedUp( bool halt )\r\n{\r\n\tif ( !m_job )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tif ( m_job->itemsToHaul().size() == m_carriedItems.size() )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tif ( m_itemToPickUp != 0 )\r\n\t{\r\n\t\treturn BT_RESULT::FAILURE;\r\n\t}\r\n\r\n\tauto cil = m_job->itemsToHaul();\r\n\tPriorityQueue<unsigned int, int> pq;\r\n\r\n\tfor ( auto itemID : cil )\r\n\t{\r\n\t\tif ( g->inv()->isHeldBy( itemID ) == 0 )\r\n\t\t{\r\n\t\t\tpq.put( itemID, g->inv()->distanceSquare( itemID, m_position ) );\r\n\t\t}\r\n\t}\r\n\tif ( !pq.empty() )\r\n\t{\r\n\t\tunsigned int itemID = pq.get();\r\n\t\tsetCurrentTarget( g->inv()->getItemPos( itemID ) );\r\n\t\tm_itemToPickUp = itemID;\r\n\t}\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsFull( bool halt )\r\n{\r\n\tif ( m_needs[\"Hunger\"].toInt() < 100 && m_startedEating )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\tm_startedEating = false;\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsDrinkFull( bool halt )\r\n{\r\n\tif ( m_needs[\"Thirst\"].toInt() < 100 && m_startedDrinking )\r\n\t{\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\tm_startedDrinking = false;\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsTrainingTime( bool halt )\r\n{\r\n\tunsigned int hour = qMin( 23, GameState::hour );\r\n\tauto activity      = m_schedule[hour];\r\n\tif ( activity == ScheduleActivity::Training )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsTrainer( bool halt )\r\n{\r\n\tif ( m_assignedWorkshop )\r\n\t{\r\n\t\tauto ws = g->wsm()->workshop( m_assignedWorkshop );\r\n\t\tif ( ws )\r\n\t\t{\r\n\t\t\tQString type = ws->type();\r\n\t\t\tif ( type == \"MeleeTraining\" )\r\n\t\t\t{\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionIsCivilian( bool halt )\r\n{\r\n\tbool roleIsCivilian = g->mil()->roleIsCivilian( m_roleID);\r\n\tif( m_roleID == 0 || roleIsCivilian )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Gnome::conditionHasHuntTarget( bool halt )\r\n{\r\n\tauto squad = g->mil()->getSquadForGnome( m_id );\r\n\tif( squad )\r\n\t{\r\n\t\tfor( const auto& prio : squad->priorities )\r\n\t\t{\r\n\t\t\tif ( prio.attitude != MilAttitude::FLEE )\r\n\t\t\t{\r\n\t\t\t\tconst auto& targetSet = g->cm()->animalsByType( prio.type );\r\n\t\t\t\tfor ( const auto& targetID : targetSet )\r\n\t\t\t\t{\r\n\t\t\t\t\t//!TODO Bucket targets by region cluster, so this can become amortized constant cost\r\n\t\t\t\t\tif ( g->cm()->hasPathTo( m_position, targetID ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( prio.attitude == MilAttitude::HUNT )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tconst Creature* creature = g->cm()->creature( targetID );\r\n\t\t\t\t\t\tconst unsigned int dist  = m_position.distSquare( creature->getPos() );\r\n\r\n\t\t\t\t\t\tif ( prio.attitude == MilAttitude::DEFEND && dist < 4 && g->cm()->hasLineOfSightTo( m_position, targetID ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( prio.attitude == MilAttitude::ATTACK && dist < 100 && g->cm()->hasLineOfSightTo( m_position, targetID ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn BT_RESULT::SUCCESS;\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\tfor ( const auto& gnomeID : squad->gnomes )\r\n\t\t{\r\n\t\t\tconst Gnome* gnome = g->gm()->gnome( gnomeID );\r\n\t\t\tif ( gnome && gnome->m_currentAttackTarget )\r\n\t\t\t{\r\n\t\t\t\tconst Creature* creature = g->cm()->creature( gnome->m_currentAttackTarget );\r\n\t\t\t\tif ( creature && g->cm()->hasPathTo( m_position, creature->id() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}"
  },
  {
    "path": "src/game/gnomefactory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"gnomefactory.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/gnome.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/gnometrader.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QBitmap>\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QPainter>\r\n\r\nGnomeFactory::GnomeFactory( Game* game ) :\r\n\tg( game )\r\n{\r\n}\r\nGnomeFactory::~GnomeFactory()\r\n{\r\n}\r\n\r\nbool GnomeFactory::init()\r\n{\r\n\treturn true;\r\n}\r\n\r\nGnome* GnomeFactory::createGnome( Position& pos )\r\n{\r\n\tQString name  = \"NotSet\";\r\n\tGender gender = ( rand() % 2 == 0 ) ? Gender::MALE : Gender::FEMALE;\r\n\r\n\tQList<QVariantMap> vnl;\r\n\tif ( gender == Gender::MALE )\r\n\t{\r\n\t\tvnl = DB::selectRows( \"Names\", \"Gender\", \"M\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvnl = DB::selectRows( \"Names\", \"Gender\", \"F\" );\r\n\t}\r\n\r\n\tbool foundName = false;\r\n\twhile ( !foundName )\r\n\t{\r\n\t\tfoundName = true;\r\n\t\tname      = vnl.value( rand() % vnl.size() ).value( \"ID\" ).toString();\r\n\t\tname.replace( 0, 1, name[0].toUpper() );\r\n\t\tfor ( auto& gn : g->gm()->gnomes() )\r\n\t\t{\r\n\t\t\tif ( gn->name() == name )\r\n\t\t\t{\r\n\t\t\t\tfoundName = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tGnome* gnome = new Gnome( pos, name, gender, g );\r\n\tgnome->init();\r\n\r\n\tauto attribs = DB::selectRows( \"Attributes\" );\r\n\r\n\tfor ( auto row : attribs )\r\n\t{\r\n\t\tQString attributeID = row.value( \"ID\" ).toString();\r\n\r\n\t\tgnome->addAttribute( attributeID, rand() % 10 + 1 );\r\n\t}\r\n\r\n\tauto needs = DB::selectRows( \"Needs\" );\r\n\r\n\tfor ( auto row : needs )\r\n\t{\r\n\t\tif ( row.value( \"Creature\" ) == \"Gnome\" )\r\n\t\t{\r\n\t\t\tQString needID = row.value( \"ID\" ).toString();\r\n\t\t\tint max        = row.value( \"Max_\" ).toInt();\r\n\t\t\tgnome->addNeed( needID, max - ( rand() % 20 ) );\r\n\t\t}\r\n\t}\r\n\r\n\tauto skills = DB::selectRows( \"Skills\" );\r\n\r\n\tfor ( auto skill : skills )\r\n\t{\r\n\t\tQString skillID = skill.value( \"ID\" ).toString();\r\n\r\n\t\tgnome->addSkill( skillID, rand() % 2000 );\r\n\t\tgnome->setSkillActive( skillID, true );\r\n\t}\r\n\r\n\tgnome->updateMoveSpeed();\r\n\tgnome->updateAttackValues();\r\n\r\n\treturn gnome;\r\n}\r\n\r\nGnomeTrader* GnomeFactory::createGnomeTrader( Position& pos )\r\n{\r\n\tQString name  = \"NotSet\";\r\n\tGender gender = ( rand() % 2 == 0 ) ? Gender::MALE : Gender::FEMALE;\r\n\r\n\tQList<QVariantMap> vnl;\r\n\tif ( gender == Gender::MALE )\r\n\t{\r\n\t\tvnl = DB::selectRows( \"Names\", \"Gender\", \"M\" );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tvnl = DB::selectRows( \"Names\", \"Gender\", \"F\" );\r\n\t}\r\n\tbool foundName = false;\r\n\twhile ( !foundName )\r\n\t{\r\n\t\tfoundName = true;\r\n\t\tname      = vnl.value( rand() % vnl.size() ).value( \"ID\" ).toString();\r\n\t\tname.replace( 0, 1, name[0].toUpper() );\r\n\t\tfor ( auto& gn : g->gm()->gnomes() )\r\n\t\t{\r\n\t\t\tif ( gn->name() == name )\r\n\t\t\t{\r\n\t\t\t\tfoundName = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tGnomeTrader* gnome = new GnomeTrader( pos, name, gender, g );\r\n\tgnome->init();\r\n\tauto attribs = DB::selectRows( \"Attributes\" );\r\n\r\n\tfor ( auto row : attribs )\r\n\t{\r\n\t\tQString attributeID = row.value( \"ID\" ).toString();\r\n\r\n\t\tgnome->addAttribute( attributeID, rand() % 10 + 1 );\r\n\t}\r\n\r\n\tauto needs = DB::selectRows( \"Needs\" );\r\n\r\n\tfor ( auto row : needs )\r\n\t{\r\n\t\tQString needID = row.value( \"ID\" ).toString();\r\n\t\tint max        = row.value( \"Max_\" ).toInt();\r\n\t\tgnome->addNeed( needID, max - ( rand() % 20 ) );\r\n\t}\r\n\r\n\tauto skills = DB::selectRows( \"Skills\" );\r\n\r\n\tfor ( auto skill : skills )\r\n\t{\r\n\t\tQString skillID = skill.value( \"ID\" ).toString();\r\n\r\n\t\tgnome->addSkill( skillID, rand() % 2000 );\r\n\t\tgnome->setSkillActive( skillID, true );\r\n\t}\r\n\r\n\tgnome->updateMoveSpeed();\r\n\r\n\treturn gnome;\r\n}\r\n\r\nGnome* GnomeFactory::createGnome( QVariantMap values )\r\n{\r\n\tGnome* gnome = new Gnome( values, g );\r\n\tgnome->init();\r\n\treturn gnome;\r\n}\r\n\r\nGnomeTrader* GnomeFactory::createGnomeTrader( QVariantMap values )\r\n{\r\n\tGnomeTrader* gnome = new GnomeTrader( values, g );\r\n\tgnome->init();\r\n\treturn gnome;\r\n}"
  },
  {
    "path": "src/game/gnomefactory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"gnome.h\"\r\n#include \"gnometrader.h\"\r\n\r\n#include <QString>\r\n\r\nclass Game;\r\n\r\nclass GnomeFactory\r\n{\r\n\tQ_DISABLE_COPY_MOVE( GnomeFactory )\r\npublic:\r\n\tGnomeFactory( Game* gm );\r\n\t~GnomeFactory();\r\n\r\n\tbool init();\r\n\r\n\tGnome* createGnome( Position& pos );\r\n\tGnomeTrader* createGnomeTrader( Position& pos );\r\n\tGnome* createGnome( QVariantMap values );\r\n\tGnomeTrader* createGnomeTrader( QVariantMap values );\r\n\r\nprivate:\r\n    QPointer<Game> g;\r\n};\r\n"
  },
  {
    "path": "src/game/gnomemanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"gnomemanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/io.h\"\r\n#include \"../game/creature.h\"\r\n#include \"../game/gnomefactory.h\"\r\n#include \"../game/gnometrader.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QJsonDocument>\r\n#include <QStandardPaths>\r\n\r\nGnomeManager::GnomeManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tloadProfessions();\r\n}\r\n\r\nGnomeManager::~GnomeManager()\r\n{\r\n\tfor ( const auto& gnome : m_gnomes )\r\n\t{\r\n\t\tdelete gnome;\r\n\t}\r\n\tfor ( const auto& gnome : m_specialGnomes )\r\n\t{\r\n\t\tdelete gnome;\r\n\t}\r\n\tfor ( const auto& gnome : m_deadGnomes )\r\n\t{\r\n\t\tdelete gnome;\r\n\t}\r\n\tfor ( const auto& gnome : m_automatons )\r\n\t{\r\n\t\tdelete gnome;\r\n\t}\r\n}\r\n\r\nbool GnomeManager::contains( unsigned int gnomeID )\r\n{\r\n\tfor( const auto& gnome : m_gnomes )\r\n\t{\r\n\t\tif( gnome->id() == gnomeID )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid GnomeManager::addGnome( Position pos )\r\n{\r\n\tGnomeFactory gf( g );\r\n\tm_gnomes.push_back( gf.createGnome( pos ) );\r\n\tm_gnomesByID.insert( m_gnomes.last()->id(), m_gnomes.last() );\r\n}\r\n\r\nunsigned int GnomeManager::addTrader( Position pos, unsigned int workshopID, QString type )\r\n{\r\n\tGnomeFactory gf( g );\r\n\tGnomeTrader* gnome = gf.createGnomeTrader( pos );\r\n\tgnome->setName( \"Trader \" + gnome->name() );\r\n\tgnome->setMarketStall( workshopID );\r\n\r\n\tauto rows = DB::selectRows( \"Traders_Items\", type );\r\n\r\n\tif ( rows.size() )\r\n\t{\r\n\t\tQVariantMap vmTrader;\r\n\t\tvmTrader.insert( \"ID\", type );\r\n\t\tQVariantList items;\r\n\t\tfor ( auto row : rows )\r\n\t\t{\r\n\t\t\titems.append( row );\r\n\t\t}\r\n\t\tvmTrader.insert( \"Items\", items );\r\n\t\tgnome->setTraderDefinition( vmTrader );\r\n\t}\r\n\r\n\tm_specialGnomes.push_back( gnome );\r\n\tm_gnomesByID.insert( gnome->id(), m_specialGnomes.last() );\r\n\treturn gnome->id();\r\n}\r\n\r\nvoid GnomeManager::addAutomaton( Automaton* a )\r\n{\r\n\tm_automatons.append( a );\r\n\tm_gnomesByID.insert( a->id(), m_automatons.last() );\r\n\r\n\t//a->setSpriteID( Global::sf().setAutomatonSprite( a->id(), g->m_inv->spriteID( a->automatonItem() ) ) );\r\n\t//a->updateSprite();\r\n}\r\n\r\nvoid GnomeManager::addAutomaton( QVariantMap values )\r\n{\r\n\tAutomaton* a = new Automaton( values, g );\r\n\tm_automatons.append( a );\r\n\tm_gnomesByID.insert( a->id(), m_automatons.last() );\r\n\r\n\t//a->setSpriteID( Global::sf().setAutomatonSprite( a->id(), g->m_inv->spriteID( a->automatonItem() ) ) );\r\n\t//a->updateSprite();\r\n}\r\n\r\nvoid GnomeManager::addGnome( QVariantMap values )\r\n{\r\n\tGnomeFactory gf( g );\r\n\tGnome* gn( gf.createGnome( values ) );\r\n\tm_gnomes.push_back( gn );\r\n\tm_gnomesByID.insert( gn->id(), m_gnomes.last() );\r\n}\r\n\r\nvoid GnomeManager::addTrader( QVariantMap values )\r\n{\r\n\tGnomeFactory gf( g );\r\n\tGnomeTrader* gt( gf.createGnomeTrader( values ) );\r\n\tm_specialGnomes.push_back( gt );\r\n\tm_gnomesByID.insert( gt->id(), m_specialGnomes.last() );\r\n}\r\n\r\nvoid GnomeManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\t//create possible automaton jobs;\r\n\tcreateJobs();\r\n\r\n\tif ( m_startIndex >= m_gnomes.size() )\r\n\t{\r\n\t\tm_startIndex = 0;\r\n\t}\r\n\tQList<unsigned int> deadGnomes;\r\n\tQList<unsigned int> deadOrGoneSpecial;\r\n\tfor ( int i = m_startIndex; i < m_gnomes.size(); ++i )\r\n\t{\r\n\t\tGnome* gn = m_gnomes[i];\r\n#ifdef CHECKTIME\r\n\t\tQElapsedTimer timer2;\r\n\t\ttimer2.start();\r\n\r\n\t\tCreatureTickResult tr = g->onTick( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\r\n\t\tauto elapsed = timer2.elapsed();\r\n\t\tif ( elapsed > 100 )\r\n\t\t{\r\n\t\t\tqDebug() << g->name() << \"just needed\" << elapsed << \"ms for tick\";\r\n\t\t\tGlobal::cfg->set( \"Pause\", true );\r\n\t\t\treturn;\r\n\t\t}\r\n#else\r\n\t\tCreatureTickResult tr = gn->onTick( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n#endif\r\n\t\tm_startIndex = i + 1;\r\n\t\tswitch ( tr )\r\n\t\t{\r\n\t\t\tcase CreatureTickResult::DEAD:\r\n\t\t\t\tdeadGnomes.append( gn->id() );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::OK:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::JOBCHANGED:\r\n\t\t\t\temit signalGnomeActivity( gn->id(), gn->getActivity() );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::TODESTROY:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::NOFLOOR:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::LEFTMAP:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif ( timer.elapsed() > 5 )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto& gnome : m_specialGnomes )\r\n\t{\r\n\t\tCreatureTickResult tr = gnome->onTick( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\t\tif ( tr == CreatureTickResult::DEAD || tr == CreatureTickResult::LEFTMAP )\r\n\t\t{\r\n\t\t\tdeadOrGoneSpecial.append( gnome->id() );\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto& automaton : m_automatons )\r\n\t{\r\n\t\tCreatureTickResult tr = automaton->onTick( tickNumber, seasonChanged, dayChanged, hourChanged, minuteChanged );\r\n\t\tswitch ( tr )\r\n\t\t{\r\n\t\t\tcase CreatureTickResult::NOFUEL:\r\n\t\t\t\tbreak;\r\n\t\t\tcase CreatureTickResult::NOCORE:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( deadGnomes.size() )\r\n\t{\r\n\t\tfor ( auto gid : deadGnomes )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < m_gnomes.size(); ++i )\r\n\t\t\t{\r\n\t\t\t\tif ( gid == m_gnomes[i]->id() )\r\n\t\t\t\t{\r\n\t\t\t\t\tGnome* dg = m_gnomes[i];\r\n\t\t\t\t\tm_deadGnomes.append( dg );\r\n\t\t\t\t\tm_gnomesByID.insert( dg->id(), m_deadGnomes.last() );\r\n\t\t\t\t\tm_gnomes.removeAt( i );\r\n\t\t\t\t\tg->mil()->removeGnome( gid );\r\n\t\t\t\t\temit signalGnomeDeath( dg->id() );\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 ( deadOrGoneSpecial.size() )\r\n\t{\r\n\t\tfor ( auto gid : deadOrGoneSpecial )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < m_specialGnomes.size(); ++i )\r\n\t\t\t{\r\n\t\t\t\tif ( gid == m_specialGnomes[i]->id() )\r\n\t\t\t\t{\r\n\t\t\t\t\tGnome* dg = m_specialGnomes[i];\r\n\t\t\t\t\tif ( dg->isDead() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_deadGnomes.append( dg );\r\n\t\t\t\t\t\tm_gnomesByID.insert( dg->id(), m_deadGnomes.last() );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_gnomesByID.remove( dg->id() );\r\n\t\t\t\t\t\tg->m_world->addToUpdateList( dg->getPos() );\r\n\t\t\t\t\t\tdelete dg;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_specialGnomes.removeAt( i );\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\tif ( m_deadGnomes.size() )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_deadGnomes.size(); ++i )\r\n\t\t{\r\n\t\t\tGnome* dg = m_deadGnomes[i];\r\n\t\t\tif ( dg->expires() < GameState::tick )\r\n\t\t\t{\r\n\t\t\t\tm_gnomesByID.remove( dg->id() );\r\n\t\t\t\tg->m_world->addToUpdateList( dg->getPos() );\r\n\t\t\t\tm_deadGnomes.removeAt( i );\r\n\t\t\t\tdelete dg;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GnomeManager::forceMoveGnomes( Position from, Position to )\r\n{\r\n\tfor ( auto& gn : m_gnomes )\r\n\t{\r\n\t\t// check gnome position\r\n\t\tif ( gn->getPos().toInt() == from.toInt() )\r\n\t\t{\r\n\t\t\t//qDebug() << \"force move gnome from \" << from.toString() << \" to \" << to.toString();\r\n\t\t\t// move gnome\r\n\t\t\tgn->forceMove( to );\r\n\t\t\t// abort job if he has one\r\n\t\t\tgn->setJobAborted( \"GnomeManager\" );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQList<Gnome*> GnomeManager::gnomesAtPosition( Position pos )\r\n{\r\n\tQList<Gnome*> out;\r\n\tfor ( int i = 0; i < m_gnomes.size(); ++i )\r\n\t{\r\n\t\tif ( m_gnomes[i]->getPos() == pos && !m_gnomes[i]->goneOffMap() )\r\n\t\t{\r\n\t\t\tout.push_back( m_gnomes[i] );\r\n\t\t}\r\n\t}\r\n\tfor ( int i = 0; i < m_specialGnomes.size(); ++i )\r\n\t{\r\n\t\tif ( m_specialGnomes[i]->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( m_specialGnomes[i] );\r\n\t\t}\r\n\t}\r\n\tfor ( int i = 0; i < m_automatons.size(); ++i )\r\n\t{\r\n\t\tif ( m_automatons[i]->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( m_automatons[i] );\r\n\t\t}\r\n\t}\r\n\tfor ( int i = 0; i < m_deadGnomes.size(); ++i )\r\n\t{\r\n\t\tif ( m_deadGnomes[i]->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( m_deadGnomes[i] );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<Gnome*> GnomeManager::deadGnomesAtPosition( Position pos )\r\n{\r\n\tQList<Gnome*> out;\r\n\tfor ( int i = 0; i < m_deadGnomes.size(); ++i )\r\n\t{\r\n\t\tif ( m_deadGnomes[i]->getPos() == pos )\r\n\t\t{\r\n\t\t\tout.push_back( m_deadGnomes[i] );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nGnome* GnomeManager::gnome( unsigned int gnomeID )\r\n{\r\n\tif ( m_gnomesByID.contains( gnomeID ) )\r\n\t{\r\n\t\treturn m_gnomesByID[gnomeID];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nGnomeTrader* GnomeManager::trader( unsigned int traderID )\r\n{\r\n\tif ( m_gnomesByID.contains( traderID ) )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_specialGnomes.size(); ++i )\r\n\t\t{\r\n\t\t\tif ( m_specialGnomes[i]->id() == traderID )\r\n\t\t\t{\r\n\t\t\t\treturn dynamic_cast<GnomeTrader*>( m_specialGnomes[i] );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nAutomaton* GnomeManager::automaton( unsigned int automatonID )\r\n{\r\n\tif ( m_gnomesByID.contains( automatonID ) )\r\n\t{\r\n\t\treturn dynamic_cast<Automaton*>( m_gnomesByID[automatonID] );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQList<Gnome*> GnomeManager::gnomesSorted()\r\n{\r\n\tQList<Gnome*> out = gnomes();\r\n\tstd::sort( out.begin(), out.end(), CreatureCompare() );\r\n\treturn out;\r\n}\r\n\r\nvoid GnomeManager::saveProfessions()\r\n{\r\n\tQVariantList pl;\r\n\tfor ( auto key : m_profs.keys() )\r\n\t{\r\n\t\tQVariantMap pm;\r\n\t\tpm.insert( \"Name\", key );\r\n\t\tpm.insert( \"Skills\", m_profs[key] );\r\n\t\tpl.append( pm );\r\n\t}\r\n\r\n\tQJsonDocument sd = QJsonDocument::fromVariant( pl );\r\n\tIO::saveFile( IO::getDataFolder() + \"/settings/profs.json\", sd );\r\n}\r\n\r\nvoid GnomeManager::loadProfessions()\r\n{\r\n\tQJsonDocument sd;\r\n\tif ( !IO::loadFile( IO::getDataFolder() + \"/settings/profs.json\", sd ) )\r\n\t{\r\n\t\t// if it doesn't exist get from /content/JSON\r\n\t\tif ( IO::loadFile( Global::cfg->get( \"dataPath\" ).toString() + \"/JSON/profs.json\", sd ) )\r\n\t\t{\r\n\t\t\tIO::saveFile( IO::getDataFolder() + \"/settings/profs.json\", sd );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tqDebug() << \"Unable to find profession config!\";\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tauto profList = sd.toVariant().toList();\r\n\r\n\tm_profs.clear();\r\n\r\n\tfor ( auto vprof : profList )\r\n\t{\r\n\t\tQString name       = vprof.toMap().value( \"Name\" ).toString();\r\n\t\tQStringList skills = vprof.toMap().value( \"Skills\" ).toStringList();\r\n\t\tm_profs.insert( name, skills );\r\n\t}\r\n\r\n\tif ( !m_profs.contains( \"Gnomad\" ) )\r\n\t{\r\n\t\tQStringList skills = DB::ids( \"Skills\" );\r\n\t\tm_profs.insert( \"Gnomad\", skills );\r\n\t\tsaveProfessions();\r\n\t}\r\n}\r\n\r\nQStringList GnomeManager::professions()\r\n{\r\n\treturn m_profs.keys();\r\n}\r\n\r\nQStringList GnomeManager::professionSkills( QString profession )\r\n{\r\n\tif ( m_profs.contains( profession ) )\r\n\t{\r\n\t\treturn m_profs.value( profession );\r\n\t}\r\n\treturn QStringList();\r\n}\r\n\r\nQString GnomeManager::addProfession()\r\n{\r\n\tQString name = \"NewProfession\";\r\n\t\r\n\tif( !m_profs.contains( name ) )\r\n\t{\r\n\t\tm_profs.insert( name, QStringList() );\r\n\t\tsaveProfessions();\r\n\t\treturn name;\r\n\t}\r\n\tint suffixNumber = 1;\r\n\r\n\twhile( m_profs.contains( name + QString::number( suffixNumber ) ) )\r\n\t{\r\n\t\t++suffixNumber;\r\n\t}\r\n\tname += QString::number( suffixNumber );\r\n\tm_profs.insert( name, QStringList() );\r\n\tsaveProfessions();\r\n\treturn name;\r\n}\r\n\r\nvoid GnomeManager::addProfession( QString name, QStringList skills )\r\n{\r\n\tif ( !m_profs.contains( name ) )\r\n\t{\r\n\t\tm_profs.insert( name, skills );\r\n\t\tsaveProfessions();\r\n\t}\r\n}\r\n\r\nvoid GnomeManager::removeProfession( QString name )\r\n{\r\n\tif ( name == \"Gnomad\" )\r\n\t\treturn;\r\n\r\n\tm_profs.remove( name );\r\n\tsaveProfessions();\r\n}\r\n\r\nvoid GnomeManager::modifyProfession( QString name, QString newName, QStringList skills )\r\n{\r\n\tif ( name == \"Gnomad\" )\r\n\t\treturn;\r\n\r\n\tm_profs.remove( name );\r\n\r\n\tif ( m_profs.contains( newName ) )\r\n\t{\r\n\t\tm_profs.insert( name, skills );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_profs.insert( newName, skills );\r\n\t}\r\n\r\n\tsaveProfessions();\r\n}\r\n\r\nbool GnomeManager::gnomeCanReach( unsigned int gnomeID, Position pos )\r\n{\r\n\tif ( m_gnomesByID.contains( gnomeID ) )\r\n\t{\r\n\t\treturn g->m_world->regionMap().checkConnectedRegions( m_gnomesByID[gnomeID]->getPos(), pos );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid GnomeManager::createJobs()\r\n{\r\n\tfor ( auto a : m_automatons )\r\n\t{\r\n\t\tif ( a->maintenanceJobID() == 0 )\r\n\t\t{\r\n\t\t\t// has core\r\n\t\t\tif ( a->coreItem() )\r\n\t\t\t{\r\n\t\t\t\t// remove core\r\n\t\t\t\tif ( a->uninstallFlag() )\r\n\t\t\t\t{\r\n\t\t\t\t\tgetUninstallJob( a );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( a->getRefuelFlag() && a->getFuelLevel() <= 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tgetRefuelJob( a );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t// no core but core type is set, install core\r\n\t\t\t\tif ( !a->coreType().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tgetInstallJob( a );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GnomeManager::getRefuelJob( Automaton* a )\r\n{\r\n\tauto jobID = g->jm()->addJob( \"Refuel\", a->getPos(), 0, true );\r\n\tauto job = g->jm()->getJob( jobID );\r\n\tif( job )\r\n\t{\r\n\t\tjob->setAutomaton( a->id() );\r\n\t\tjob->setRequiredSkill( \"Machining\" );\r\n\t\tjob->addPossibleWorkPosition( a->getPos() );\r\n\t\tjob->addRequiredItem( 1, \"RawCoal\", \"any\", {} );\r\n\t\ta->setMaintenanceJob( job );\r\n\t}\r\n}\r\n\r\nvoid GnomeManager::getInstallJob( Automaton* a )\r\n{\r\n\tauto jobID = g->jm()->addJob( \"Install\", a->getPos(), 0, true );\r\n\tauto job = g->jm()->getJob( jobID );\r\n\tif( job )\r\n\t{\r\n\t\tjob->setAutomaton( a->id() );\r\n\t\tjob->setRequiredSkill( \"Machining\" );\r\n\t\tjob->addPossibleWorkPosition( a->getPos() );\r\n\t\tjob->addRequiredItem( 1, a->coreType(), \"any\", {} );\r\n\t\ta->setMaintenanceJob( job );\r\n\t}\r\n}\r\n\r\nvoid GnomeManager::getUninstallJob( Automaton* a )\r\n{\r\n\tauto jobID = g->jm()->addJob( \"Uninstall\", a->getPos(), 0, true );\r\n\tauto job = g->jm()->getJob( jobID );\r\n\tif( job )\r\n\t{\r\n\t\tjob->setAutomaton( a->id() );\r\n\t\tjob->setRequiredSkill( \"Machining\" );\r\n\t\tjob->addPossibleWorkPosition( a->getPos() );\r\n\t\ta->setMaintenanceJob( job );\r\n\t}\r\n}\r\n\r\nvoid GnomeManager::setInMission( unsigned int gnomeID, unsigned int missionID )\r\n{\r\n\tif ( m_gnomesByID.contains( gnomeID ) )\r\n\t{\r\n\t\tm_gnomesByID[gnomeID]->setMission( missionID );\r\n\t\tm_gnomesByID[gnomeID]->setOnMission( true );\r\n\t}\r\n}\r\n\r\nQString GnomeManager::name( unsigned int gnomeID )\r\n{\r\n\tif ( m_gnomesByID.contains( gnomeID ) )\r\n\t{\r\n\t\treturn m_gnomesByID[gnomeID]->name();\r\n\t}\r\n\treturn \"*no name*\";\r\n}\r\n\r\nunsigned int GnomeManager::roleID( unsigned int gnomeID )\r\n{\r\n\tif ( m_gnomesByID.contains( gnomeID ) )\r\n\t{\r\n\t\treturn m_gnomesByID[gnomeID]->roleID();\r\n\t}\r\n\treturn 0;\r\n}\r\n\t\r\nvoid GnomeManager::setRoleID( unsigned int gnomeID, unsigned int roleID )\r\n{\r\n\tif ( m_gnomesByID.contains( gnomeID ) )\r\n\t{\r\n\t\treturn m_gnomesByID[gnomeID]->setRole( roleID );\r\n\t}\r\n}\r\n\r\nint GnomeManager::numGnomes()\r\n{\r\n\treturn m_gnomes.size();\r\n}"
  },
  {
    "path": "src/game/gnomemanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../game/automaton.h\"\r\n#include \"../game/gnome.h\"\r\n#include \"../game/gnometrader.h\"\r\n\r\n#include <QList>\r\n\r\nclass Game;\r\n\r\nclass GnomeManager : public QObject\r\n{\r\n\tfriend class Gnome;\r\n\tfriend class GnomeTrader;\r\n\tfriend class Automaton;\r\n\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( GnomeManager )\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQList<Gnome*> m_gnomes;\r\n\tQList<Gnome*> m_deadGnomes;\r\n\tQMap<unsigned int, Gnome*> m_gnomesByID;\r\n\tQMap<QString, QStringList> m_profs;\r\n\r\n\tQList<Gnome*> m_specialGnomes;\r\n\tQList<Automaton*> m_automatons;\r\n\r\n\tint m_startIndex = 0;\r\n\r\npublic:\r\n\tGnomeManager( Game* parent );\r\n\t~GnomeManager();\r\n\r\n\tvoid loadProfessions();\r\n\tvoid saveProfessions();\r\n\tQStringList professions();\r\n\tQStringList professionSkills( QString profession );\r\n\tQString addProfession();\r\n\tvoid addProfession( QString name, QStringList skills );\r\n\tvoid removeProfession( QString name );\r\n\tvoid modifyProfession( QString name, QString newName, QStringList skills );\r\n\r\n\tvoid addGnome( Position pos );\r\n\tvoid addGnome( QVariantMap values );\r\n\r\n\tunsigned int addTrader( Position pos, unsigned int workshopID, QString type );\r\n\tvoid addTrader( QVariantMap values );\r\n\r\n\tvoid addAutomaton( Automaton* automaton );\r\n\tvoid addAutomaton( QVariantMap values );\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tbool contains( unsigned int gnomeID );\r\n\r\n\tQList<Gnome*>& gnomes()\r\n\t{\r\n\t\treturn m_gnomes;\r\n\t}\r\n\tQList<Gnome*> gnomesSorted();\r\n\tQList<Gnome*>& specialGnomes()\r\n\t{\r\n\t\treturn m_specialGnomes;\r\n\t}\r\n\tQList<Automaton*>& automatons()\r\n\t{\r\n\t\treturn m_automatons;\r\n\t}\r\n\tQList<Gnome*>& deadGnomes()\r\n\t{\r\n\t\treturn m_deadGnomes;\r\n\t}\r\n\r\n\tvoid forceMoveGnomes( Position from, Position to );\r\n\r\n\tQList<Gnome*> gnomesAtPosition( Position pos );\r\n\tQList<Gnome*> deadGnomesAtPosition( Position pos );\r\n\tGnome* gnome( unsigned int gnomeID );\r\n\tGnomeTrader* trader( unsigned int traderID );\r\n\tAutomaton* automaton( unsigned int automatonID );\r\n\r\n\tbool gnomeCanReach( unsigned int gnomeID, Position pos );\r\n\r\n\tvoid createJobs();\r\n\r\n\tvoid setInMission( unsigned int gnomeID, unsigned int missionID );\r\n\r\n\tQString name( unsigned int gnomeID );\r\n\t\r\n\tunsigned int roleID( unsigned int gnomeID );\r\n\tvoid setRoleID( unsigned int gnomeID, unsigned int roleID );\r\n\r\n\tint numGnomes();\r\n\r\nprivate:\r\n\tvoid getRefuelJob( Automaton* a );\r\n\tvoid getInstallJob( Automaton* a );\r\n\tvoid getUninstallJob( Automaton* a );\r\n\r\nsignals:\r\n\tvoid signalGnomeActivity( unsigned int id, QString skillID );\r\n\tvoid signalGnomeDeath( unsigned int id );\r\n};"
  },
  {
    "path": "src/game/gnometrader.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"gnometrader.h\"\r\n#include \"gnomemanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/behaviortree/bt_tree.h\"\r\n#include \"../base/config.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/workshop.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nTraderDefinition::TraderDefinition( QVariantMap& in )\r\n{\r\n\tid = in.value( \"ID\" ).toString();\r\n\r\n\tauto vItems = in.value( \"Items\" ).toList();\r\n\tfor( const auto& vItem : vItems )\r\n\t{\r\n\t\tauto vin = vItem.toMap();\r\n\t\tint amount = 1;\r\n\t\tif( vin.contains( \"Amount\" ) )\r\n\t\t{\r\n\t\t\tamount = vin.value( \"Amount\" ).toInt();\r\n\t\t}\r\n\r\n\t\tTraderItem ti{\tvin.value( \"Type\" ).toString(), \r\n\t\t\t\t\t\tvin.value( \"Item\" ).toString(), \r\n\t\t\t\t\t\tvin.value( \"Material\" ).toString(), \r\n\t\t\t\t\t\tvin.value( \"Gender\" ).toString(), \r\n\t\t\t\t\t\tvin.value( \"Quality\" ).value<unsigned char>(), \r\n\t\t\t\t\t\tvin.value( \"Value_\").toInt(), \r\n\t\t\t\t\t\tamount,\r\n\t\t\t\t\t\tvin.value( \"Reserved\" ).toInt() };\r\n\r\n\t\titems.append( ti );\r\n\t}\r\n}\r\n\t\r\nvoid TraderDefinition::serialize( QVariantMap& out )\r\n{\r\n\tQVariantMap tdOut;\r\n\r\n\ttdOut.insert( \"ID\", id );\r\n\tQVariantList outItems;\r\n\tfor( const auto& item : items )\r\n\t{\r\n\t\tQVariantMap vItem;\r\n\t\tvItem.insert( \"Type\", item.type );\r\n\t\tvItem.insert( \"Item\", item.itemSID );\r\n\t\tvItem.insert( \"Material\", item.materialSID );\r\n\t\tvItem.insert( \"Gender\", item.gender );\r\n\t\tvItem.insert( \"Quality\", item.quality );\r\n\t\tvItem.insert( \"Value_\", item.value );\r\n\t\tvItem.insert( \"Amount\", item.amount );\r\n\t\tvItem.insert( \"Reserved\", item.reserved );\r\n\r\n\t\toutItems.append( vItem );\r\n\t}\r\n\ttdOut.insert( \"Items\", outItems );\r\n\r\n\tout.insert( \"TraderDefinition\", tdOut );\r\n}\r\n\r\n\r\n\r\n\r\nGnomeTrader::GnomeTrader( Position& pos, QString name, Gender gender, Game* game ) :\r\n\tGnome( pos, name, gender, game )\r\n{\r\n\tm_type = CreatureType::GNOME_TRADER;\r\n\r\n\tm_leavesOnTick = GameState::tick + Global::util->ticksPerDayRandomized( 5 );\r\n}\r\n\r\nGnomeTrader::GnomeTrader( QVariantMap& in, Game* game ) :\r\n\tGnome( in, game ),\r\n\tm_leavesOnTick( in.value( \"LeavesOnTick\" ).value<quint64>() ),\r\n\tm_marketStall( in.value( \"MarketStall\" ).toUInt() )\r\n{\r\n\tauto vtd = in.value( \"TraderDefinition\" ).toMap();\r\n\tm_traderDefinition = TraderDefinition( vtd );\r\n\r\n\tm_type = CreatureType::GNOME_TRADER;\r\n}\r\n\r\nvoid GnomeTrader::serialize( QVariantMap& out )\r\n{\r\n\tGnome::serialize( out );\r\n\r\n\tout.insert( \"LeavesOnTick\", m_leavesOnTick );\r\n\tout.insert( \"MarketStall\", m_marketStall );\r\n\tm_traderDefinition.serialize( out );\r\n}\r\n\r\nvoid GnomeTrader::init()\r\n{\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\r\n\tupdateSprite();\r\n\r\n\tinitTaskMap();\r\n\tinitTaskMapTrader();\r\n\r\n\tloadBehaviorTree( \"GnomeTrader\" );\r\n\r\n\tif ( m_btBlackBoard.contains( \"BehaviorTreeState\" ) )\r\n\t{\r\n\t\tQVariantMap btm = m_btBlackBoard.value( \"State\" ).toMap();\r\n\t\tif ( m_behaviorTree )\r\n\t\t{\r\n\t\t\tm_behaviorTree->deserialize( btm );\r\n\t\t\tm_btBlackBoard.remove( \"State\" );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nGnomeTrader::~GnomeTrader()\r\n{\r\n}\r\n\r\nCreatureTickResult GnomeTrader::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tprocessCooldowns( tickNumber );\r\n\r\n\tm_jobChanged    = false;\r\n\tPosition oldPos = m_position;\r\n\r\n\tif ( checkFloor() )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::NOFLOOR;\r\n\t}\r\n\r\n\tif ( isDead() )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::DEAD;\r\n\t}\r\n\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tm_behaviorTree->tick();\r\n\t}\r\n\r\n\tmove( oldPos );\r\n\tupdateLight( oldPos, m_position );\r\n\r\n\tm_lastOnTick = tickNumber;\r\n\r\n\tif ( m_goneOffMap )\r\n\t{\r\n\t\treturn CreatureTickResult::LEFTMAP;\r\n\t}\r\n\r\n\treturn CreatureTickResult::OK;\r\n}\r\n\r\nvoid GnomeTrader::initTaskMapTrader()\r\n{\r\n\tusing namespace std::placeholders;\r\n\r\n\tm_behaviors.insert( \"IsTimeToLeave\", std::bind( &GnomeTrader::conditionIsTimeToLeave, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"GetExitPosition\", std::bind( &GnomeTrader::actionGetExitPosition, this, _1 ) );\r\n\tm_behaviors.insert( \"LeaveMap\", std::bind( &GnomeTrader::actionLeaveMap, this, _1 ) );\r\n\tm_behaviors.insert( \"GetMarketStallPosition\", std::bind( &GnomeTrader::actionGetMarketStallPosition, this, _1 ) );\r\n\tm_behaviors.insert( \"Trade\", std::bind( &GnomeTrader::actionTrade, this, _1 ) );\r\n}\r\n\r\nBT_RESULT GnomeTrader::conditionIsTimeToLeave( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\r\n\tif ( GameState::tick > m_leavesOnTick )\r\n\t{\r\n\t\tlog( \"It's time to leave\" );\r\n\r\n\t\tauto ws = g->wsm()->workshop( m_marketStall );\r\n\t\tws->assignGnome( 0 );\r\n\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT GnomeTrader::actionGetMarketStallPosition( bool halt )\r\n{\r\n\tQ_UNUSED( halt ); // action takes only one tick, halt has no effect\r\n\tauto ws = g->wsm()->workshop( m_marketStall );\r\n\tsetCurrentTarget( ws->inputPos() );\r\n\tm_facingAfterMove = ws->rotation();\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\nBT_RESULT GnomeTrader::actionTrade( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\treturn BT_RESULT::SUCCESS;\r\n}\r\n\r\n\r\n\r\n\r\nvoid GnomeTrader::setInventory( QVariantList items )\r\n{\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\tm_traderDefinition.items.clear();\r\n\r\n\tfor ( auto vEntry : items )\r\n\t{\r\n\t\tQVariantMap entry = vEntry.toMap();\r\n\t\tint min           = entry.value( \"Min_\" ).toInt();\r\n\t\tint max           = entry.value( \"Max_\" ).toInt();\r\n\t\tint modVal        = ( max - min ) + min;\r\n\t\tint amount        = 0;\r\n\t\tif ( modVal > 0 )\r\n\t\t{\r\n\t\t\tamount = rand() % modVal;\r\n\t\t}\r\n\r\n\t\tif ( amount > 0 )\r\n\t\t{\r\n\t\t\tTraderItem ti{  entry.value( \"Type\" ).toString(), \r\n\t\t\t\t\t\t    entry.value( \"Item\" ).toString(), \r\n\t\t\t\t\t\t    entry.value( \"Material\" ).toString(), \r\n\t\t\t\t\t\t\tentry.value( \"Gender\" ).toString(), \r\n\t\t\t\t\t\t\tentry.value( \"Quality\" ).value<unsigned char>(), \r\n\t\t\t\t\t\t\tentry.value( \"Value_\").toInt(), \r\n\t\t\t\t\t\t\tamount, 0 };\r\n\t\t\t\r\n\t\t\tm_traderDefinition.items.append( ti );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQList<TraderItem>& GnomeTrader::inventory()\r\n{\r\n\treturn m_traderDefinition.items;\r\n}\r\n\r\nvoid GnomeTrader::setMarketStall( unsigned int id )\r\n{\r\n\tm_marketStall = id;\r\n}\r\n\r\nvoid GnomeTrader::setTraderDefinition( QVariantMap map )\r\n{\r\n\tm_traderDefinition.id = map.value( \"ID\" ).toString();\r\n\tsetInventory( map.value( \"Items\" ).toList() );\r\n}\r\n"
  },
  {
    "path": "src/game/gnometrader.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/gnome.h\"\r\n#include <QVariantMap>\r\n\r\nstruct TraderItem {\r\n\tQString type;\r\n\tQString itemSID;\r\n\tQString materialSID;\r\n\tQString gender;\r\n\tunsigned char quality = 0;\r\n\tint value = 0;\r\n\tint amount = 0;\r\n\tint reserved = 0;\r\n};\r\n\r\nstruct TraderDefinition {\r\n\tQString id;\r\n\tQList<TraderItem> items;\r\n\r\n\tTraderDefinition() {};\r\n\tTraderDefinition( QVariantMap& in );\r\n\tvoid serialize( QVariantMap& out );\r\n};\r\n\r\nclass GnomeTrader : public Gnome\r\n{\r\npublic:\r\n\tGnomeTrader( Position& pos, QString name, Gender gender, Game* game );\r\n\tGnomeTrader( QVariantMap& in, Game* game );\r\n\t~GnomeTrader();\r\n\r\n\tvirtual void serialize( QVariantMap& out );\r\n\r\n\tvoid init();\r\n\r\n\tvoid setMarketStall( unsigned int id );\r\n\tvoid setTraderDefinition( QVariantMap map );\r\n\r\n\tCreatureTickResult onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvoid setInventory( QVariantList items );\r\n\r\n\tQList<TraderItem>& inventory();\r\n\r\n\tvoid initTaskMapTrader();\r\n\r\n\tBT_RESULT conditionIsTimeToLeave( bool halt = false );\r\n\tBT_RESULT actionGetMarketStallPosition( bool halt );\r\n\tBT_RESULT actionTrade( bool halt );\r\n\r\nprivate:\r\n\tquint64 m_leavesOnTick     = 0;\r\n\tunsigned int m_marketStall = 0;\r\n\tTraderDefinition m_traderDefinition;\r\n};\r\n"
  },
  {
    "path": "src/game/grove.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"grove.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nGrove::~Grove()\r\n{\r\n\tfor ( const auto& field : m_fields )\r\n\t{\r\n\t\tdelete field;\r\n\t}\r\n}\r\n\r\nGroveProperties::GroveProperties( QVariantMap& in )\r\n{\r\n\tauto vjpl = in.value( \"JobPriorities\" ).toList();\r\n\tfor ( const auto& vjp : vjpl )\r\n\t{\r\n\t\tjobPriorities.append( vjp.value<quint8>() );\r\n\t}\r\n\r\n\ttreeType  = in.value( \"TreeType\" ).toString();\r\n\tplant     = in.value( \"Plant\" ).toBool();\r\n\tpickFruit = in.value( \"PickFruit\" ).toBool();\r\n\tfell      = in.value( \"Fell\" ).toBool();\r\n\r\n\tautoPick = in.value( \"AutoPick\" ).toBool();\r\n\tautoFell = in.value( \"AutoFell\" ).toBool();\r\n\r\n\tautoPickMin = in.value( \"AutoPickMin\" ).toInt();\r\n\tautoPickMax = in.value( \"AutoPickMax\" ).toInt();\r\n\tautoFellMin = in.value( \"AutoFellMin\" ).toInt();\r\n\tautoFellMax = in.value( \"AutoFellMax\" ).toInt();\r\n}\r\n\r\nvoid GroveProperties::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"Type\", \"grove\" );\r\n\r\n\tout.insert( \"TreeType\", treeType );\r\n\tout.insert( \"Plant\", plant );\r\n\tout.insert( \"PickFruit\", pickFruit );\r\n\tout.insert( \"Fell\", fell );\r\n\r\n\tout.insert( \"AutoPick\", autoPick );\r\n\tout.insert( \"AutoFell\", autoFell );\r\n\r\n\tout.insert( \"AutoPickMin\", autoPickMin );\r\n\tout.insert( \"AutoPickMax\", autoPickMax );\r\n\tout.insert( \"AutoFellMin\", autoFellMin );\r\n\tout.insert( \"AutoFellMax\", autoFellMax );\r\n\r\n\tQVariantList jpl;\r\n\tfor ( auto jp : jobPriorities )\r\n\t{\r\n\t\tjpl.append( jp );\r\n\t}\r\n\tout.insert( \"JobPriorities\", jpl );\r\n}\r\n\r\nGrove::Grove( QList<QPair<Position, bool>> tiles, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_name = \"Grove\";\r\n\r\n\tm_properties.jobPriorities.clear();\r\n\tm_properties.jobPriorities.push_back( GroveJobs::PlantTree );\r\n\tm_properties.jobPriorities.push_back( GroveJobs::PickFruit );\r\n\tm_properties.jobPriorities.push_back( GroveJobs::FellTree );\r\n\r\n\tfor ( const auto& p : tiles )\r\n\t{\r\n\t\tif ( p.second )\r\n\t\t{\r\n\t\t\tGroveField* grofi = new GroveField;\r\n\t\t\tgrofi->pos        = p.first;\r\n\t\t\tm_fields.insert( p.first.toInt(), grofi );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nGrove::Grove( QVariantMap vals, Game* game ) :\r\n\tWorldObject( vals, game ),\r\n\tm_properties( vals )\r\n{\r\n\tQVariantList vfl = vals.value( \"Fields\" ).toList();\r\n\tfor ( const auto& vf : vfl )\r\n\t{\r\n\t\tauto vfm          = vf.toMap();\r\n\t\tGroveField* grofi = new GroveField;\r\n\t\tgrofi->pos        = Position( vfm.value( \"Pos\" ).toString() );\r\n\t\tif( vfm.contains( \"Job\" ) )\r\n\t\t{\r\n\t\t\tgrofi->job = g->jm()->getJob( vfm.value( \"Job\" ).toUInt() );\r\n\t\t}\r\n\t\tm_fields.insert( grofi->pos.toInt(), grofi );\r\n\t}\r\n}\r\n\r\nQVariant Grove::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tWorldObject::serialize( out );\r\n\tm_properties.serialize( out );\r\n\tQVariantList tiles;\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tQVariantMap entry;\r\n\t\tentry.insert( \"Pos\", field->pos.toString() );\r\n\t\tif( field->job )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> spJob = field->job.toStrongRef();\r\n\t\t\tentry.insert( \"Job\", spJob->id() );\r\n\t\t}\r\n\t\ttiles.append( entry );\r\n\t}\r\n\tout.insert( \"Fields\", tiles );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Grove::onTick( quint64 tick )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn;\r\n\t\r\n\tfor( auto& gf : m_fields )\r\n\t{\r\n\t\tif( !gf->job )\r\n\t\t{\r\n\t\t\tTile& tile = g->w()->getTile( gf->pos );\r\n\r\n\t\t\tif( !g->w()->plants().contains( gf->pos.toInt() ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_properties.plant && g->w()->noTree( gf->pos, 2, 2 ) && g->w()->isWalkable( gf->pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString mat    = DB::select( \"Material\", \"Plants\", m_properties.treeType ).toString();\r\n\t\t\t\t\tQString seedID = DB::select( \"SeedItemID\", \"Plants\", m_properties.treeType ).toString();\r\n\r\n\t\t\t\t\tauto item = g->inv()->getClosestItem( m_fields.first()->pos, true, seedID, mat );\r\n\t\t\t\t\tif ( item == 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tunsigned int jobID = g->jm()->addJob( \"PlantTree\", gf->pos, 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob->setItem( m_properties.treeType );\r\n\t\t\t\t\t\tjob->addRequiredItem( 1, seedID, mat, QStringList() );\r\n\t\t\t\t\t\tgf->job = job;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tPlant& tree = g->w()->plants()[gf->pos.toInt()];\r\n\t\t\t\tif ( !tree.isTree() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif ( m_properties.pickFruit && tree.harvestable() )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int jobID = g->jm()->addJob( \"HarvestTree\", gf->pos, 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgf->job = job;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tif ( m_properties.fell && tree.matureWood() )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int jobID = g->jm()->addJob( \"FellTree\", gf->pos, 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgf->job = job;\r\n\t\t\t\t\t}\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\n\tupdateAutoForester();\r\n}\r\n\r\nvoid Grove::updateAutoForester()\r\n{\r\n\tif ( m_properties.autoPick )\r\n\t{\r\n\t\tunsigned int count = g->inv()->itemCount( \"Fruit\", m_properties.treeType );\r\n\t\tunsigned int min   = m_properties.autoPickMin;\r\n\t\tunsigned int max   = m_properties.autoPickMax;\r\n\t\tif ( count < min )\r\n\t\t{\r\n\t\t\tm_properties.pickFruit = true;\r\n\t\t}\r\n\t\tif ( count > max )\r\n\t\t{\r\n\t\t\tm_properties.pickFruit = false;\r\n\t\t}\r\n\t}\r\n\tif ( m_properties.autoFell )\r\n\t{\r\n\t\tunsigned int count = g->inv()->itemCount( \"RawWood\", m_properties.treeType );\r\n\t\tunsigned int min   = m_properties.autoFellMin;\r\n\t\tunsigned int max   = m_properties.autoFellMax;\r\n\t\tif ( count < min )\r\n\t\t{\r\n\t\t\tm_properties.fell = true;\r\n\t\t}\r\n\t\tif ( count > max )\r\n\t\t{\r\n\t\t\tm_properties.fell = false;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\nbool Grove::canDelete() const\r\n{\r\n\treturn true;\r\n}\r\n\r\nbool Grove::removeTile( const Position & pos )\r\n{\r\n\tGroveField* gf = m_fields.value( pos.toInt() );\r\n\r\n\tm_fields.remove( pos.toInt() );\r\n\r\n\tg->w()->clearTileFlag( pos, TileFlag::TF_GROVE );\r\n\tdelete gf;\r\n\t// if last tile deleted return true\r\n\treturn m_fields.empty();\r\n}\r\n\r\nvoid Grove::addTile( const Position & pos )\r\n{\r\n\tGroveField* grofi = new GroveField;\r\n\tgrofi->pos        = pos;\r\n\tm_fields.insert( pos.toInt(), grofi );\r\n\r\n\tg->w()->setTileFlag( pos, TileFlag::TF_GROVE );\r\n}\r\n\r\nint Grove::numTrees()\r\n{\r\n\tint numTrees = 0;\r\n\tfor( auto& gf : m_fields )\r\n\t{\r\n\t\tif( g->w()->plants().contains( gf->pos.toInt() ) )\r\n\t\t{\r\n\t\t\tif( g->w()->plants()[gf->pos.toInt()].isTree() )\r\n\t\t\t{\r\n\t\t\t\t++numTrees;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn numTrees;\r\n}"
  },
  {
    "path": "src/game/grove.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/worldobject.h\"\r\n#include \"../game/job.h\"\r\n\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QPair>\r\n#include <QVariantMap>\r\n\r\nclass Job;\r\nclass Game;\r\n\r\nstruct GroveField\r\n{\r\n\tPosition pos;\r\n\tQWeakPointer<Job> job;\r\n};\r\n\r\nenum GroveJobs : int\r\n{\r\n\tPlantTree,\r\n\tPickFruit,\r\n\tFellTree\r\n};\r\n\r\nstruct GroveProperties\r\n{\r\n\tQString treeType = \"\";\r\n\tQList<qint8> jobPriorities;\r\n\r\n\tbool plant     = true;\r\n\tbool pickFruit = true;\r\n\tbool fell      = true;\r\n\r\n\tbool autoPick = false;\r\n\tbool autoFell = false;\r\n\r\n\tunsigned int autoPickMin = 0;\r\n\tunsigned int autoPickMax = 0;\r\n\tunsigned int autoFellMin = 0;\r\n\tunsigned int autoFellMax = 0;\r\n\r\n\tvoid serialize( QVariantMap& out ) const;\r\n\tGroveProperties() {};\r\n\tGroveProperties( QVariantMap& in );\r\n};\r\n\r\nclass Grove : public WorldObject\r\n{\r\n\tfriend class AggregatorAgri;\r\n\tQ_DISABLE_COPY_MOVE( Grove )\r\npublic:\r\n\tGrove() = delete;\r\n\tGrove( QList<QPair<Position, bool>> tiles, Game* game );\r\n\tGrove( QVariantMap vals, Game* game );\r\n\t~Grove();\r\n\r\n\tQVariant serialize() const;\r\n\r\n\tvoid onTick( quint64 tick );\r\n\r\n\tbool canDelete() const;\r\n\r\n\tbool removeTile( const Position & pos );\r\n\tvoid addTile( const Position & pos );\r\n\r\n\tint numTrees();\r\n\r\n\tint numPlots() { return m_fields.size(); }\r\n\r\nprivate:\r\n\tGroveProperties m_properties;\r\n\r\n\tQMap<unsigned int, GroveField*> m_fields;\r\n\r\n\tvoid updateAutoForester();\r\n\r\n\tQMap<int, int> m_prioValues;\r\n\r\n\tGroveProperties& properties()\r\n\t{\r\n\t\treturn m_properties;\r\n\t}\r\n};\r\n"
  },
  {
    "path": "src/game/inventory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"inventory.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/octree.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/itemhistory.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QJsonDocument>\r\n#include <QJsonValue>\r\n\r\nInventory::Inventory( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tm_itemHistory = new ItemHistory( this );\r\n\tinit();\r\n}\r\n\r\nInventory::~Inventory()\r\n{\r\n\tm_items.clear();\r\n\tm_positionHash.clear();\r\n\tm_hash.clear();\r\n\r\n\tm_categoriesSorted.clear();\r\n\tm_groupsSorted.clear();\r\n\tm_itemsSorted.clear();\r\n\r\n\tm_materialsInTypes.clear();\r\n\r\n\tm_foodItems.clear();\r\n\tm_drinkItems.clear();\r\n\r\n\tfor ( const auto& octtreeGroup : m_octrees )\r\n\t{\r\n\t\tfor (const auto& octree : octtreeGroup)\r\n\t\t{\r\n\t\t\tdelete octree;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Inventory::init()\r\n{\r\n\tm_dimX = Global::dimX;\r\n\tm_dimY = Global::dimY;\r\n\tm_dimZ = Global::dimZ;\r\n\r\n\tfor ( auto categoryMap : DB::selectRows( \"ItemGrouping\" ) )\r\n\t{\r\n\t\tQString categoryID = categoryMap.value( \"ID\" ).toString();\r\n\t\t//qDebug() << \"--\" << categoryID;\r\n\r\n\t\tm_categoriesSorted.push_back( categoryID );\r\n\t\tm_groupsSorted[categoryID];\r\n\t\tm_itemsSorted[categoryID];\r\n\r\n\t\tauto groupList = DB::execQuery2( \"SELECT DISTINCT \\\"ItemGroup\\\" FROM Items WHERE \\\"Category\\\" = \\\"\" + categoryID + \"\\\"\" );\r\n\t\tfor ( auto group : groupList )\r\n\t\t{\r\n\t\t\tQString groupID = group.toString();\r\n\t\t\t//qDebug() << \"----\" << groupID;\r\n\t\t\tm_groupsSorted[categoryID].push_back( groupID );\r\n\t\t\tm_itemsSorted[categoryID][groupID];\r\n\r\n\t\t\tauto vItemList = DB::execQuery2( \"SELECT ID FROM Items WHERE \\\"Category\\\" = \\\"\" + categoryID + \"\\\" AND \\\"ItemGroup\\\" = \\\"\" + groupID + \"\\\"\" );\r\n\r\n\t\t\tfor ( auto vItem : vItemList )\r\n\t\t\t{\r\n\t\t\t\tQString itemID = vItem.toString();\r\n\t\t\t\tm_itemsSorted[categoryID][groupID].push_back( itemID );\r\n\t\t\t\tm_hash[itemID];\r\n\r\n\t\t\t\tfor ( auto materialID : Global::util->possibleMaterialsForItem( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_hash[itemID].insert( materialID, QHash<unsigned int, Item*>() );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto row : DB::selectRows( \"Materials\" ) )\r\n\t{\r\n\t\tm_materialsInTypes[row.value( \"Type\" ).toString()].append( row.value( \"ID\" ).toString() );\r\n\t}\r\n\tPriorityQueue<QString, int> pqFood;\r\n\tPriorityQueue<QString, int> pqDrink;\r\n\tfor ( auto row : DB::selectRows( \"Items\" ) )\r\n\t{\r\n\t\tint eatVal = row.value( \"EatValue\" ).toInt();\r\n\t\tif ( eatVal > 0 )\r\n\t\t{\r\n\t\t\tpqFood.put( row.value( \"ID\" ).toString(), eatVal );\r\n\t\t}\r\n\t\tint drinkVal = row.value( \"DrinkValue\" ).toInt();\r\n\t\tif ( drinkVal > 0 )\r\n\t\t{\r\n\t\t\tpqDrink.put( row.value( \"ID\" ).toString(), drinkVal );\r\n\t\t}\r\n\t}\r\n\twhile ( !pqFood.empty() )\r\n\t{\r\n\t\tm_foodItemLookup.push_front( pqFood.get() );\r\n\t}\r\n\twhile ( !pqDrink.empty() )\r\n\t{\r\n\t\tm_drinkItemLookup.push_front( pqDrink.get() );\r\n\t}\r\n}\r\n\r\nvoid Inventory::saveFilter()\r\n{\r\n\tQVariantList filter;\r\n\tfor ( auto itemID : m_hash.keys() )\r\n\t{\r\n\t\tfor ( auto materialID : m_hash[itemID].keys() )\r\n\t\t{\r\n\t\t\tfilter.append( itemID + \"_\" + materialID );\r\n\t\t}\r\n\t}\r\n\tGameState::itemFilter = filter;\r\n}\r\n\r\nvoid Inventory::loadFilter()\r\n{\r\n\tauto list = GameState::itemFilter;\r\n\tfor ( auto vEntry : list )\r\n\t{\r\n\t\tauto entry = vEntry.toString();\r\n\t\tauto comp  = entry.split( \"_\" );\r\n\t\tif ( comp.size() == 2 )\r\n\t\t{\r\n\t\t\tm_hash[comp[0]].insert( comp[1], QHash<unsigned int, Item*>() );\r\n\r\n\t\t\tint x = Global::dimX / 2;\r\n\t\t\tint y = Global::dimY / 2;\r\n\t\t\tint z = Global::dimZ / 2;\r\n\t\t\tm_octrees[comp[0]].insert( comp[1], new Octree( x, y, z, x, y, z ) );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nItem* Inventory::getItem( unsigned int itemUID )\r\n{\r\n\tauto it = m_items.find( itemUID );\r\n\tif ( it != m_items.end() )\r\n\t{\r\n\t\treturn &(*it);\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nbool Inventory::itemExists( unsigned int itemID )\r\n{\r\n\tif ( m_items.contains( itemID ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nunsigned int Inventory::createItem( Position pos, QString itemSID, QString materialSID )\r\n{\r\n\tDBH::itemUID( itemSID );\r\n\t//qDebug() << \"create item \" << pos.toString() << baseItem << material;\r\n\tItem obj( pos, itemSID, materialSID );\r\n\tSprite* sprite = g->m_sf->createSprite( itemSID, { materialSID } );\r\n\tif ( sprite )\r\n\t{\r\n\t\tobj.setSpriteID( sprite->uID );\r\n\t}\r\n\taddObject( obj, itemSID, materialSID );\r\n\r\n\treturn obj.id();\r\n}\r\n\r\nunsigned int Inventory::createItem( Position pos, QString itemSID, QList<unsigned int> components )\r\n{\r\n\tDBH::itemUID( itemSID );\r\n\t//qDebug() << \"create item \" << pos.toString() << itemSID << components;\r\n\tQVariantList compList = DB::select2( \"ItemID\", \"Items_Components\", \"ID\", itemSID );\r\n\r\n\tif ( compList.isEmpty() )\r\n\t{ // item has no components, we use the first material\r\n\t\tif ( components.size() )\r\n\t\t{\r\n\t\t\tauto item = getItem( components.first() );\r\n\t\t\tif ( item )\r\n\t\t\t{\r\n\t\t\t\treturn createItem( pos, itemSID, item->materialSID() );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"####### component item\" << components.first() << \"for createItem\" << itemSID << \"at\" << pos.toString() << \"doesn't exist\";\r\n\t\t\t\treturn 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tqDebug() << \"####### create item, components empty\";\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// first component decides the material of the item for material level bonuses and other things\r\n\t\tQString firstCompSID = compList.first().toMap().value( \"ItemID\" ).toString();\r\n\t\tDBH::itemUID( firstCompSID );\r\n\t\tQString firstMat     = materialSID( components.first() );\r\n\t\tItem obj( pos, itemSID, firstMat );\r\n\r\n\t\tQStringList materialSIDs;\r\n\r\n\t\tfor ( auto UID : components )\r\n\t\t{\r\n\t\t\tauto item = getItem( UID );\r\n\t\t\tif ( item )\r\n\t\t\t{\r\n\t\t\t\tunsigned int itID = item->itemUID();\r\n\t\t\t\tunsigned int maID = item->materialUID();\r\n\t\t\t\tmaterialSIDs.push_back( item->materialSID() );\r\n\t\t\t\tItemMaterial im = { itID, maID };\r\n\t\t\t\tobj.addComponent( im );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// create combined sprite\r\n\t\tSprite* sprite = g->m_sf->createSprite( itemSID, materialSIDs );\r\n\t\tif ( sprite )\r\n\t\t{\r\n\t\t\tobj.setSpriteID( sprite->uID );\r\n\t\t}\r\n\t\taddObject( obj, itemSID, firstMat );\r\n\r\n\t\treturn obj.id();\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::createItem( Position pos, QString itemSID, QVariantList components )\r\n{\r\n\treturn createItem( pos, itemSID, Global::util->variantList2UInt( components ) );\r\n}\r\n\r\nunsigned int Inventory::createItem( const QVariantMap& values )\r\n{\r\n\tif ( values.value( \"ItemSID\" ).toString().isEmpty() )\r\n\t{\r\n\t\tqDebug() << \"missing itemSID\" << values.value( \"ID\" ).toUInt() << \"at\" << values.value( \"Position\" ).toString();\r\n\t\treturn 0;\r\n\t}\r\n\tif ( values.value( \"MaterialSID\" ).toString().isEmpty() )\r\n\t{\r\n\t\tqDebug() << \"missing materialSID\" << values.value( \"ID\" ).toUInt() << \"at\" << values.value( \"Position\" ).toString();\r\n\t\treturn 0;\r\n\t}\r\n\tDBH::itemUID( values.value( \"ItemSID\" ).toString() );\r\n\t//Item obj( pos, baseItem, material );\r\n\tItem obj( values );\r\n\r\n\tQString baseItem = obj.itemSID();\r\n\tQString material = obj.materialSID();\r\n\t//qDebug() << \"inventory create item \" << baseItem << material;\r\n\r\n\tQString spr    = DBH::spriteID( baseItem );\r\n\tSprite* sprite = nullptr;\r\n\tif ( obj.components().isEmpty() )\r\n\t{\r\n\t\tsprite = g->m_sf->createSprite( baseItem, { material } );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tQList<QString> materialSIDs;\r\n\t\tfor ( auto comp : obj.components() )\r\n\t\t{\r\n\t\t\tmaterialSIDs.push_back( DBH::materialSID( comp.materialUID ) );\r\n\t\t}\r\n\t\t// create combined sprite\r\n\t\tsprite = g->m_sf->createSprite( baseItem, materialSIDs );\r\n\t}\r\n\tif ( sprite )\r\n\t{\r\n\t\tobj.setSpriteID( sprite->uID );\r\n\t}\r\n\r\n\taddObject( obj, baseItem, material );\r\n\r\n\treturn obj.id();\r\n}\r\n\r\nOctree* Inventory::octree( const QString& itemSID, const QString& materialSID )\r\n{\r\n\tif ( !m_octrees.contains( itemSID ) || !m_octrees[itemSID].contains( materialSID ) )\r\n\t{\r\n\t\tint x = Global::dimX / 2;\r\n\t\tint y = Global::dimY / 2;\r\n\t\tint z = Global::dimZ / 2;\r\n\t\tm_octrees[itemSID].insert( materialSID, new Octree( x, y, z, x, y, z ) );\r\n\t}\r\n\treturn m_octrees[itemSID][materialSID];\r\n}\r\n\r\nvoid Inventory::addObject( Item& object, const QString& itemID, const QString& materialID )\r\n{\r\n\tm_items.insert( object.id(), object );\r\n\tItem* item = getItem( object.id() );\r\n\t\r\n\tOctree* ot = octree( itemID, materialID );\r\n\r\n\tif ( !item->isHeldBy() )\r\n\t{\r\n\t\tif ( m_positionHash.contains( item->getPos().toInt() ) )\r\n\t\t{\r\n\t\t\tm_positionHash[item->getPos().toInt()].insert( item->id() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tPositionEntry entry;\r\n\t\t\tentry.insert( item->id() );\r\n\t\t\tm_positionHash.insert( item->getPos().toInt(), entry );\r\n\t\t}\r\n\r\n\t\tPosition pos = item->getPos();\r\n\t\tot->insertItem( pos.x, pos.y, pos.z, item->id() );\r\n\t\t\r\n\t\tif ( !item->isConstructed() && !item->isInContainer() )\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( item->getPos(), object.spriteID() );\r\n\t\t}\r\n\r\n\t\tif ( item->isConstructed() || item->isInStockpile() )\r\n\t\t{\r\n\t\t\taddToWealth( item );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( object.nutritionalValue() != 0 )\r\n\t{\r\n\t\tm_foodItems.insert( object.id(), object.nutritionalValue() );\r\n\t}\r\n\tif ( object.drinkValue() != 0 )\r\n\t{\r\n\t\tm_drinkItems.insert( object.id(), object.drinkValue() );\r\n\t}\r\n\r\n\tif ( m_hash[itemID].contains( materialID ) )\r\n\t{\r\n\t\tm_hash[itemID][materialID].insert( item->id(), item );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_hash[itemID].insert( materialID, QHash<unsigned int, Item*>() );\r\n\t\tm_hash[itemID][materialID].insert( item->id(), item );\r\n\t}\r\n\r\n\tm_itemHistory->plusItem( itemID, materialID );\r\n\r\n\tm_itemsChanged = true;\r\n\r\n\temit signalAddItem( itemID, materialID );\r\n}\r\n\r\nvoid Inventory::destroyObject( unsigned int id )\r\n{\r\n\tif ( m_items.contains( id ) )\r\n\t{\r\n\t\tItem* item = getItem( id );\r\n\t\tif ( item )\r\n\t\t{\r\n\t\t\t// clear all pointers in convinience containers\r\n\t\t\tunsigned int tileID = item->getPos().toInt();\r\n\t\t\tif ( m_positionHash.contains( tileID ) )\r\n\t\t\t{\r\n\t\t\t\tm_positionHash[tileID].remove( id );\r\n\t\t\t\tif ( m_positionHash[tileID].empty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_positionHash.remove( tileID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( item->isInContainer() )\r\n\t\t\t{\r\n\t\t\t\tremoveItemFromContainer( id );\r\n\t\t\t}\r\n\r\n\t\t\tQString materialSID = DBH::materialSID( item->materialUID() );\r\n\t\t\tQString itemSID     = DBH::itemSID( item->itemUID() );\r\n\r\n\t\t\tPosition pos = item->getPos();\r\n\t\t\tOctree* ot = octree( itemSID, materialSID );\r\n\t\t\tot->removeItem( pos.x, pos.y, pos.z, id );\r\n\t\t\t\r\n\t\t\tm_hash[itemSID][materialSID].remove( id );\r\n\r\n\t\t\tm_foodItems.remove( id );\r\n\t\t\tm_drinkItems.remove( id );\r\n\t\t\t// finally remove object\r\n\t\t\tm_items.remove( id );\r\n\r\n\t\t\tm_itemHistory->minusItem( itemSID, materialSID );\r\n\r\n\t\t\temit signalRemoveItem( itemSID, materialSID );\r\n\t\t}\r\n\r\n\t\tm_itemsChanged = true;\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::getFirstObjectAtPosition( const Position& pos )\r\n{\r\n\tif ( m_positionHash.contains( pos.toInt() ) )\r\n\t{\r\n\t\tif ( !m_positionHash[pos.toInt()].empty() )\r\n\t\t{\r\n\t\t\tfor ( auto itemUID : m_positionHash[pos.toInt()].values() )\r\n\t\t\t{\r\n\t\t\t\tif ( !isConstructed( itemUID ) && !isInContainer( itemUID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn itemUID;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_positionHash.remove( pos.toInt() );\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nbool Inventory::getObjectsAtPosition( const Position& pos, PositionEntry& pe )\r\n{\r\n\tif ( m_positionHash.contains( pos.toInt() ) && !m_positionHash[pos.toInt()].empty() )\r\n\t{\r\n\t\tpe = m_positionHash[pos.toInt()];\r\n\t\treturn true;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_positionHash.remove( pos.toInt() );\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nint Inventory::countItemsAtPos( Position& pos )\r\n{\r\n\tif ( m_positionHash.contains( pos.toInt() ) )\r\n\t{\r\n\t\tint size = m_positionHash[pos.toInt()].size();\r\n\t\tif ( size > 0 )\r\n\t\t{\r\n\t\t\treturn size;\r\n\t\t}\r\n\r\n\t\tm_positionHash.remove( pos.toInt() );\r\n\t\treturn 0;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Inventory::getClosestItem( const Position& pos, bool allowInStockpile, QString itemSID, QString materialSID )\r\n{\r\n\tauto out = getClosestItems( pos, allowInStockpile, itemSID, materialSID, 1 );\r\n\tif ( !out.isEmpty() )\r\n\t{\r\n\t\treturn out.first();\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Inventory::getClosestItem2( const Position& pos, bool allowInStockpile, QString itemSID, QSet<QString> materialTypes )\r\n{\r\n\tfor ( auto matType : materialTypes )\r\n\t{\r\n\t\tfor ( auto materialSID : m_materialsInTypes[matType] )\r\n\t\t{\r\n\t\t\tunsigned int item = getClosestItem( pos, allowInStockpile, itemSID, materialSID );\r\n\t\t\tif ( item )\r\n\t\t\t{\r\n\t\t\t\treturn item;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Inventory::checkReachableItems( Position pos, bool allowInStockpile, int count, QString itemSID, QString materialSID )\r\n{\r\n\tint thisCount  = 0;\r\n\tint partitions = 0;\r\n\r\n\tauto predicate = [&thisCount, this, allowInStockpile, pos, count]( unsigned int itemID ) -> bool {\r\n\t\tauto item = getItem( itemID );\r\n\r\n\t\tif ( item && ( allowInStockpile || !item->isInStockpile() ) && item->isFree() )\r\n\t\t{\r\n\t\t\tif ( g->m_world->regionMap().checkConnectedRegions( pos, item->getPos() ) && g->m_world->fluidLevel( item->getPos() ) < 6 )\r\n\t\t\t{\r\n\t\t\t\t++thisCount;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( thisCount == count )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\treturn true;\r\n\t};\r\n\t\r\n\tif ( materialSID == \"any\" )\r\n\t{\r\n\t\tfor ( auto material : m_octrees[itemSID].keys() )\r\n\t\t{\r\n\t\t\tOctree* ot = octree( itemSID, material );\r\n\t\t\tot->visit( pos.x, pos.y, pos.z, predicate );\r\n\t\t\tif ( thisCount >= count )\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tOctree* ot = octree( itemSID, materialSID );\r\n\t\tot->visit( pos.x, pos.y, pos.z, predicate );\r\n\t}\r\n\r\n\treturn thisCount >= count;\r\n}\r\n\r\nunsigned int Inventory::getItemAtPos( const Position& pos, bool allowInStockpile, QString itemSID, QString materialSID )\r\n{\r\n\tif ( m_positionHash.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto itemIDs = m_positionHash[pos.toInt()];\r\n\r\n\t\tif ( materialSID == \"any\" )\r\n\t\t{\r\n\t\t\tfor ( auto itemID : itemIDs )\r\n\t\t\t{\r\n\t\t\t\tauto item = getItem( itemID );\r\n\t\t\t\tif ( item )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( itemSID == item->itemSID() && ( allowInStockpile || !item->isInStockpile() ) && item->isFree() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn itemID;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_positionHash[pos.toInt()].remove( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto itemID : itemIDs )\r\n\t\t\t{\r\n\t\t\t\tauto item = getItem( itemID );\r\n\t\t\t\tif ( item )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( item->itemSID() == itemSID &&\r\n\t\t\t\t\t\t item->materialSID() == materialSID &&\r\n\t\t\t\t\t\t ( allowInStockpile || !item->isInStockpile() ) && item->isFree() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn itemID;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_positionHash[pos.toInt()].remove( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQList<unsigned int> Inventory::getClosestItems( const Position& pos, bool allowInStockpile, QString itemSID, QString materialSID, int count )\r\n{\r\n\tQList<unsigned int> out;\r\n\r\n\tauto predicate = [&out, this, allowInStockpile, pos, count]( unsigned int itemID ) -> bool {\r\n\t\tauto item = getItem( itemID );\r\n\r\n\t\tif ( item && ( allowInStockpile || !item->isInStockpile() ) && item->isFree() )\r\n\t\t{\r\n\t\t\tif ( g->m_world->regionMap().checkConnectedRegions( pos, item->getPos() ) && g->m_world->fluidLevel( item->getPos() ) < 6 )\r\n\t\t\t{\r\n\t\t\t\tout.append( itemID );\r\n\t\t\t\tif ( out.size() == count )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t};\r\n\r\n\tif ( materialSID == \"any\" )\r\n\t{\r\n\t\tfor ( auto material : m_octrees[itemSID].keys() )\r\n\t\t{\r\n\t\t\tOctree* ot = octree( itemSID, material );\r\n\t\t\tot->visit( pos.x, pos.y, pos.z, predicate );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tOctree* ot = octree( itemSID, materialSID );\r\n\t\tot->visit( pos.x, pos.y, pos.z, predicate );\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQList<unsigned int> Inventory::getClosestItems( const Position& pos, bool allowInStockpile, QList<QPair<QString, QString>> filter, int count )\r\n{\r\n\tQList<unsigned int> out;\r\n\r\n\tfor ( const auto& filterItem : filter )\r\n\t{\r\n\t\tauto& itemSID     = filterItem.first;\r\n\t\tauto& materialSID = filterItem.second;\r\n\r\n\t\tout.append( getClosestItems( pos, allowInStockpile, itemSID, materialSID, count ) );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQList<unsigned int> Inventory::getClosestItemsForStockpile( unsigned int stockpileID, Position& pos, bool allowInStockpile, QSet<QPair<QString, QString>> filter )\r\n{\r\n\tQString itemSID;\r\n\tQString materialSID;\r\n\r\n\tQList<unsigned int> out;\r\n\tQList<unsigned int> items;\r\n\r\n\tfor ( const auto& filterItem : filter )\r\n\t{\r\n\t\titemSID     = filterItem.first;\r\n\t\tmaterialSID = filterItem.second;\r\n\r\n\t\tif ( materialSID == \"any\" )\r\n\t\t{\r\n\t\t\tfor ( auto material : m_octrees[itemSID].keys() )\r\n\t\t\t{\r\n\t\t\t\tOctree* ot = octree( itemSID, material );\r\n\t\t\t\titems += ot->query( pos.x, pos.y, pos.z );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tOctree* ot = octree( itemSID, materialSID );\r\n\t\t\titems += ot->query( pos.x, pos.y, pos.z );\r\n\t\t}\r\n\r\n\t\tfor ( auto itemID : items )\r\n\t\t{\r\n\t\t\tauto item = getItem( itemID );\r\n\r\n\t\t\tif ( item && item->isFree() )\r\n\t\t\t{\r\n\t\t\t\tif ( item->isInStockpile() == stockpileID )\r\n\t\t\t\t{\r\n\t\t\t\t\t//item is in this stockpile\r\n\t\t\t\t}\r\n\t\t\t\telse if ( !item->isInStockpile() )\r\n\t\t\t\t{\r\n\t\t\t\t\t//item isnt in stockpile\r\n\t\t\t\t\tout.append( itemID );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// item is in stockpile so we need to check if we can pull from stockpiles and if the source stockpile allows it\r\n\t\t\t\t\tif ( allowInStockpile && g->m_spm->hasPriority( stockpileID, item->isInStockpile() ) && g->m_spm->allowsPull( item->isInStockpile() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tout.append( itemID );\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\treturn out;\r\n}\r\n\r\nQList<unsigned int> Inventory::tradeInventory( QString itemSID, QString materialSID )\r\n{\r\n\tQList<unsigned int> out;\r\n\r\n\tif ( m_hash.contains( itemSID ) )\r\n\t{\r\n\t\tif ( !m_hash[itemSID].empty() )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemSID][materialSID] )\r\n\t\t\t{\r\n\t\t\t\tif ( item->isInStockpile() && item->isFree() )\r\n\t\t\t\t{\r\n\t\t\t\t\tout.append( item->id() );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQList<unsigned int> Inventory::tradeInventory( QString itemSID, QString materialSID, unsigned char quality )\r\n{\r\n\tQList<unsigned int> out;\r\n\r\n\tif ( m_hash.contains( itemSID ) )\r\n\t{\r\n\t\tif ( !m_hash[itemSID].empty() )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemSID][materialSID] )\r\n\t\t\t{\r\n\t\t\t\tif ( item->isInStockpile() && item->isFree() && item->quality() == quality )\r\n\t\t\t\t{\r\n\t\t\t\t\tout.append( item->id() );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nunsigned int Inventory::getFoodItem( Position& pos )\r\n{\r\n\tfor ( auto foodItem : m_foodItemLookup )\r\n\t{\r\n\t\tauto item = getClosestItem( pos, true, foodItem, \"any\" );\r\n\t\tif ( item )\r\n\t\t{\r\n\t\t\treturn item;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Inventory::getDrinkItem( Position& pos )\r\n{\r\n\tfor ( auto drinkItem : m_drinkItemLookup )\r\n\t{\r\n\t\tauto item = getClosestItem( pos, true, drinkItem, \"any\" );\r\n\t\tif ( item )\r\n\t\t{\r\n\t\t\treturn item;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nPosition Inventory::getPosition( unsigned int itemID )\r\n{\r\n\tItem* item = getItem( itemID );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->getPos();\r\n\t}\r\n\treturn Position();\r\n}\r\n\r\nvoid Inventory::moveItemToPos( unsigned int id, const Position& newPos )\r\n{\r\n\t//qDebug() << \"move item from \" << item( id].getPos().toString() << \" to \" << newPos.toString();\r\n\t// remove from position hash\r\n\tpickUpItem( id, 1 );\r\n\r\n\tputDownItem( id, newPos );\r\n}\r\n\r\nunsigned int Inventory::pickUpItem( unsigned int id, unsigned int creatureID )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setHeldBy( creatureID );\r\n\r\n\t\t//remove from possible stockpile\r\n\t\tunsigned int stockpileID = item->isInStockpile();\r\n\t\tif ( stockpileID )\r\n\t\t{\r\n\t\t\tg->m_spm->removeItem( stockpileID, item->getPos(), id );\r\n\t\t\titem->setInStockpile( 0 );\r\n\t\t\tremoveFromWealth( item );\r\n\t\t}\r\n\r\n\t\tremoveItemFromContainer( id );\r\n\r\n\t\tconst Position& pos = item->getPos();\r\n\t\tif ( m_positionHash.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tm_positionHash[pos.toInt()].remove( id );\r\n\t\t}\r\n\t\tif ( m_positionHash[pos.toInt()].empty() )\r\n\t\t{\r\n\t\t\tm_positionHash.remove( pos.toInt() );\r\n\t\t}\r\n\r\n\t\tOctree* ot = octree( item->itemSID(), item->materialSID() );\r\n\t\tot->removeItem( pos.x, pos.y, pos.z, item->id() );\r\n\r\n\t\tif ( item->isContainer() )\r\n\t\t{\r\n\t\t\tfor ( auto inItemID : item->containedItems() )\r\n\t\t\t{\r\n\t\t\t\tauto inItem = getItem( inItemID );\r\n\r\n\t\t\t\tif ( inItem )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString inItemSID = inItem->itemSID();\r\n\t\t\t\t\tQString inMatSID  = inItem->materialSID();\r\n\r\n\t\t\t\t\tOctree* ot2 = octree( inItemSID, inMatSID );\r\n\t\t\t\t\tot2->removeItem( pos.x, pos.y, pos.z, inItemID );\r\n\t\t\t\t\tm_positionHash[pos.toInt()].remove( inItemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tunsigned int nextItemID = getFirstObjectAtPosition( pos );\r\n\t\tauto nextItem           = getItem( nextItemID );\r\n\t\tif ( nextItem )\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( pos, nextItem->spriteID() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( pos, 0 );\r\n\t\t}\r\n\t\treturn id;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Inventory::putDownItem( unsigned int id, const Position& newPos )\r\n{\r\n\t// insert at new pos in position hash\r\n\tItem* item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setHeldBy( 0 );\r\n\t\tif ( m_positionHash.contains( newPos.toInt() ) )\r\n\t\t{\r\n\t\t\tm_positionHash[newPos.toInt()].insert( id );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tPositionEntry entry;\r\n\t\t\tentry.insert( id );\r\n\t\t\tm_positionHash.insert( newPos.toInt(), entry );\r\n\t\t}\r\n\r\n\t\tOctree* ot = octree( item->itemSID(), item->materialSID() );\r\n\t\tot->insertItem( newPos.x, newPos.y, newPos.z, item->id() );\r\n\t\t\t\r\n\t\tif ( item->isContainer() )\r\n\t\t{\r\n\t\t\tfor ( auto inItemID : item->containedItems() )\r\n\t\t\t{\r\n\t\t\t\tauto inItem = getItem( inItemID );\r\n\r\n\t\t\t\tif ( inItem )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString inItemSID = inItem->itemSID();\r\n\t\t\t\t\tQString inMatSID  = inItem->materialSID();\r\n\t\t\t\t\tif( m_octrees.contains( inItemSID ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( m_octrees[inItemSID].contains( inMatSID ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tauto octree       = m_octrees[inItemSID][inMatSID];\r\n\t\t\t\t\t\t\tif ( octree )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\toctree->insertItem( newPos.x, newPos.y, newPos.z, inItemID );\r\n\t\t\t\t\t\t\t\tm_positionHash[newPos.toInt()].insert( inItemID );\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\r\n\t\t// set new position\r\n\t\titem->setPos( newPos );\r\n\r\n\t\tunsigned int nextItemID = getFirstObjectAtPosition( newPos );\r\n\t\tauto nextItem           = getItem( nextItemID );\r\n\t\tif ( nextItem )\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( newPos, nextItem->spriteID() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( newPos, 0 );\r\n\t\t}\r\n\t\treturn id;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Inventory::isHeldBy( unsigned int id )\r\n{\r\n\tItem* item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isHeldBy();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQList<QString> Inventory::categories()\r\n{\r\n\treturn m_categoriesSorted;\r\n}\r\n\r\nQList<QString> Inventory::groups( QString category )\r\n{\r\n\tif ( m_groupsSorted.contains( category ) )\r\n\t{\r\n\t\treturn m_groupsSorted[category];\r\n\t}\r\n\treturn QList<QString>();\r\n}\r\nQList<QString> Inventory::items( QString category, QString group )\r\n{\r\n\tif ( m_itemsSorted.contains( category ) )\r\n\t{\r\n\t\tif ( m_itemsSorted[category].contains( group ) )\r\n\t\t{\r\n\t\t\treturn m_itemsSorted[category][group];\r\n\t\t}\r\n\t}\r\n\treturn QList<QString>();\r\n}\r\n\r\nQList<QString> Inventory::materials( QString category, QString group, QString item )\r\n{\r\n\tif ( m_hash.contains( item ) )\r\n\t{\r\n\t\treturn m_hash[item].keys();\r\n\t}\r\n\treturn QList<QString>();\r\n}\r\n\r\nbool Inventory::isInGroup( QString category, QString group, unsigned int itemID )\r\n{\r\n\tif ( m_itemsSorted.contains( category ) )\r\n\t{\r\n\t\tif ( m_itemsSorted[category].contains( group ) )\r\n\t\t{\r\n\t\t\tQList<QString> items = m_itemsSorted[category][group];\r\n\t\t\tauto item            = getItem( itemID );\r\n\t\t\tif ( item )\r\n\t\t\t{\r\n\t\t\t\treturn items.contains( item->itemSID() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQMap<QString, int> Inventory::materialCountsForItem( QString itemSID, bool allowInJob )\r\n{\r\n\tQMap<QString, int> mats;\r\n\r\n\tmats.insert( \"any\", 0 );\r\n\r\n\tif ( m_hash.contains( itemSID ) )\r\n\t{\r\n\t\tQList<QString> matKeys = m_hash[itemSID].keys();\r\n\t\tfor ( auto mk : matKeys )\r\n\t\t{\r\n\t\t\tmats.insert( mk, 0 );\r\n\t\t}\r\n\t\tif ( !m_hash[itemSID].empty() )\r\n\t\t{\r\n\t\t\tfor ( auto it : m_hash[itemSID] )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : it )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( ( !item->isInJob() || allowInJob ) && !item->isConstructed() && ( item->isHeldBy() == 0 ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmats[\"any\"]++;\r\n\t\t\t\t\t\tif ( mats.contains( item->materialSID() ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmats[item->materialSID()]++;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tmats.insert( item->materialSID(), 1 );\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\treturn mats;\r\n}\r\n\r\nunsigned int Inventory::itemCount( QString itemID, QString materialID )\r\n{\r\n\tunsigned int result = 0;\r\n\r\n\tif ( materialID == \"any\" )\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) )\r\n\t\t{\r\n\t\t\tfor ( auto it : m_hash[itemID] )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : it )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( item->isFree() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t++result;\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\telse\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) && m_hash[itemID].contains( materialID ) )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemID][materialID] )\r\n\t\t\t{\r\n\t\t\t\tif ( item->isFree() )\r\n\t\t\t\t{\r\n\t\t\t\t\t++result;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nunsigned int Inventory::itemCountWithInJob( QString itemID, QString materialID )\r\n{\r\n\tunsigned int result = 0;\r\n\r\n\tif ( materialID == \"any\" )\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) )\r\n\t\t{\r\n\t\t\tfor ( auto it : m_hash[itemID] )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : it )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !item->isConstructed() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t++result;\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\telse\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) && m_hash[itemID].contains( materialID ) )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemID][materialID] )\r\n\t\t\t{\r\n\t\t\t\tif ( !item->isConstructed() )\r\n\t\t\t\t{\r\n\t\t\t\t\t++result;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nunsigned int Inventory::itemCountInStockpile( QString itemID, QString materialID )\r\n{\r\n\tunsigned int result = 0;\r\n\r\n\tif ( materialID == \"any\" )\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) )\r\n\t\t{\r\n\t\t\tfor ( auto it : m_hash[itemID] )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : it )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( item->isInStockpile() && item->isFree() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t++result;\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\telse\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) && m_hash[itemID].contains( materialID ) )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemID][materialID] )\r\n\t\t\t{\r\n\t\t\t\tif ( item->isInStockpile() && item->isFree() )\r\n\t\t\t\t{\r\n\t\t\t\t\tresult++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nunsigned int Inventory::itemCountNotInStockpile( QString itemID, QString materialID )\r\n{\r\n\tunsigned int result = 0;\r\n\r\n\tif ( materialID == \"any\" )\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) )\r\n\t\t{\r\n\t\t\tfor ( auto it : m_hash[itemID] )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : it )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !item->isInStockpile() && item->isFree() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t++result;\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\telse\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) && m_hash[itemID].contains( materialID ) )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemID][materialID] )\r\n\t\t\t{\r\n\t\t\t\tif ( item->materialSID() == materialID && !item->isInStockpile() && item->isFree() )\r\n\t\t\t\t{\r\n\t\t\t\t\tresult++;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nInventory::ItemCountDetailed Inventory::itemCountDetailed( QString itemID, QString materialID )\r\n{\r\n\tItemCountDetailed result = { 0, 0, 0, 0, 0, 0, 0 };\r\n\r\n\tif ( materialID == \"any\" )\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) )\r\n\t\t{\r\n\t\t\tfor ( auto it : m_hash[itemID] )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto item : it )\r\n\t\t\t\t{\r\n\t\t\t\t\tresult.total++;\r\n\r\n\t\t\t\t\tif ( item->isHeldBy() != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//TODO determine if the item is equipped or just carried\r\n\t\t\t\t\t\tresult.equipped++;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( item->isConstructed() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tresult.constructed++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( item->isInStockpile() )\r\n\t\t\t\t\t\tresult.inStockpile++;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tresult.loose++;\r\n\r\n\t\t\t\t\tif ( item->isInJob() )\r\n\t\t\t\t\t\tresult.inJob++;\r\n\r\n\t\t\t\t\tresult.totalValue += item->value();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( m_hash.contains( itemID ) && m_hash[itemID].contains( materialID ) )\r\n\t\t{\r\n\t\t\tfor ( auto item : m_hash[itemID][materialID] )\r\n\t\t\t{\r\n\t\t\t\tif ( item->materialSID() == materialID )\r\n\t\t\t\t{\r\n\t\t\t\t\tresult.total++;\r\n\r\n\t\t\t\t\tif ( item->isHeldBy() != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t//TODO determine if the item is equipped or just carried\r\n\t\t\t\t\t\tresult.equipped++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( item->isConstructed() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tresult.constructed++;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( item->isInStockpile() )\r\n\t\t\t\t\t\tresult.inStockpile++;\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tresult.loose++;\r\n\r\n\t\t\t\t\tif ( item->isInJob() )\r\n\t\t\t\t\t\tresult.inJob++;\r\n\r\n\t\t\t\t\tresult.totalValue += item->value();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn result;\r\n\r\n\treturn ItemCountDetailed();\r\n}\r\n\r\nbool Inventory::isContainer( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isContainer();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nunsigned int Inventory::isInStockpile( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isInStockpile();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Inventory::setInStockpile( unsigned int id, unsigned int stockpile )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setInStockpile( stockpile );\r\n\t\tif ( stockpile )\r\n\t\t{\r\n\t\t\taddToWealth( item );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::isInJob( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isInJob();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Inventory::setInJob( unsigned int id, unsigned int job )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setInJob( job );\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::isInContainer( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isInContainer();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Inventory::setInContainer( unsigned int id, unsigned int container )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setInContainer( container );\r\n\t}\r\n}\r\n\r\nbool Inventory::isConstructed( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isConstructed();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Inventory::setConstructed( unsigned int id, bool status )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\tif ( item->isConstructed() && !status )\r\n\t\t{\r\n\t\t\tremoveFromWealth( item );\r\n\t\t\temit signalRemoveItem( itemSID( id ), materialSID( id ) );\r\n\t\t}\r\n\t\titem->setIsConstructed( status );\r\n\t\tif ( status )\r\n\t\t{\r\n\t\t\taddToWealth( item );\r\n\t\t\temit signalAddItem( itemSID( id ), materialSID( id ) );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::isUsedBy( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isUsedBy();\r\n\t}\r\n\treturn 0;\r\n}\r\n\t\r\nvoid Inventory::setIsUsedBy( unsigned int id, unsigned int creatureID )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setUsedBy( creatureID );\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::value( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->value();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Inventory::setValue( unsigned int id, unsigned int value )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setValue( value );\r\n\t}\r\n}\r\n\r\nunsigned char Inventory::quality( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->quality();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Inventory::setQuality( unsigned int id, unsigned char quality )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setQuality( quality );\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::madeBy( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->madeBy();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Inventory::setMadeBy( unsigned int id, unsigned int creatureID )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setMadeBy( creatureID );\r\n\t}\r\n}\r\n\r\nvoid Inventory::putItemInContainer( unsigned int id, unsigned int containerID )\r\n{\r\n\tauto item      = getItem( id );\r\n\tauto container = getItem( containerID );\r\n\tif ( item != 0 && container != 0 )\r\n\t{\r\n\t\titem->setInContainer( containerID );\r\n\r\n\t\tcontainer->insertItem( id );\r\n\r\n\t\tunsigned int nextItemID = getFirstObjectAtPosition( container->getPos() );\r\n\t\tauto nextItem           = getItem( nextItemID );\r\n\t\tif ( nextItem )\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( container->getPos(), nextItem->spriteID() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tg->m_world->setItemSprite( container->getPos(), 0 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Inventory::removeItemFromContainer( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\tunsigned int containerID = item->isInContainer();\r\n\t\titem->setInContainer( 0 );\r\n\t\tauto container = getItem( containerID );\r\n\t\tif ( container )\r\n\t\t{\r\n\t\t\tcontainer->removeItem( id );\r\n\t\t\tif ( container->isConstructed() )\r\n\t\t\t{\r\n\t\t\t\tg->m_spm->setInfiNotFull( container->getPos() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQString Inventory::pixmapID( unsigned int id )\r\n{\r\n\t// return DBH::spriteID( DBH::itemSID( m_itemUID ) ) + \"_\" + DBH::materialSID( m_materialUID );\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->getPixmapSID();\r\n\t}\r\n\r\n\treturn \"\";\r\n}\r\n\r\nQString Inventory::designation( unsigned int id )\r\n{\r\n\t//return S::s( \"$MaterialName_\" + DBH::materialSID( m_materialUID ) ) + \" \" + S::s( \"$ItemName_\" + DBH::itemSID( m_itemUID ) );\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->getDesignation();\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nQString Inventory::itemSID( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->itemSID();\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nunsigned int Inventory::itemUID( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->itemUID();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQString Inventory::materialSID( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->materialSID();\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nunsigned int Inventory::materialUID( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->materialUID();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQString Inventory::combinedID( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->combinedSID();\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nunsigned int Inventory::spriteID( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->spriteID();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nPosition Inventory::getItemPos( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->getPos();\r\n\t}\r\n\treturn Position();\r\n}\r\n\r\nvoid Inventory::setItemPos( unsigned int id, const Position& pos )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setPos( pos );\r\n\t}\r\n}\r\n\r\nunsigned char Inventory::stackSize( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->stackSize();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned char Inventory::capacity( unsigned int id )\r\n{\r\n\t//get from containers\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->capacity();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Inventory::requireSame( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->requireSame();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nconst QSet<unsigned int>& Inventory::itemsInContainer( unsigned int containerID )\r\n{\r\n\tauto container = getItem( containerID );\r\n\tif ( container )\r\n\t{\r\n\t\treturn container->containedItems();\r\n\t}\r\n\tstatic const QSet<unsigned int> nullopt;\r\n\treturn nullopt;\r\n}\r\n\r\nunsigned char Inventory::nutritionalValue( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->nutritionalValue();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned char Inventory::drinkValue( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->drinkValue();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint Inventory::attackValue( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->attackValue();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Inventory::isWeapon( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isWeapon();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Inventory::isTool( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->isTool();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Inventory::setColor( unsigned int id, QString color )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\titem->setColor( color );\r\n\t}\r\n}\r\n\r\nunsigned int Inventory::color( unsigned int id )\r\n{\r\n\tauto item = getItem( id );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->color();\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nQList<QString> Inventory::materialsForItem( QString itemSID, int count )\r\n{\r\n\tQList<QString> out;\r\n\r\n\tQMap<QString, int> matCount = materialCountsForItem( itemSID );\r\n\tfor ( auto mc = matCount.begin(); mc != matCount.end(); ++mc )\r\n\t{\r\n\t\tif ( mc.key() != \"any\" )\r\n\t\t{\r\n\t\t\tif ( mc.value() >= count )\r\n\t\t\t{\r\n\t\t\t\tout.push_back( mc.key() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nbool Inventory::isSameTypeAndMaterial( unsigned int id, unsigned int id2 )\r\n{\r\n\tauto item  = getItem( id );\r\n\tauto item2 = getItem( id2 );\r\n\tif ( item != nullptr && item2 != nullptr )\r\n\t{\r\n\t\treturn ( ( item->itemUID() == item2->itemUID() ) && ( item->materialUID() == item2->materialUID() ) );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Inventory::gravity( Position pos )\r\n{\r\n\tif ( !g->m_world->isSolidFloor( pos ) )\r\n\t{\r\n\t\tif ( m_positionHash.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tPosition newPos = pos;\r\n\t\t\tg->m_world->getFloorLevelBelow( newPos, false );\r\n\t\t\tif( newPos == pos )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tauto items = m_positionHash.value( pos.toInt() );\r\n\t\t\tfor ( auto item : items )\r\n\t\t\t{\r\n\t\t\t\tmoveItemToPos( item, newPos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint Inventory::distanceSquare( unsigned int itemID, Position pos )\r\n{\r\n\tauto item = getItem( itemID );\r\n\tif ( item )\r\n\t{\r\n\t\treturn item->distanceSquare( pos, Global::zWeight );\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Inventory::getTradeValue( QString itemSID, QString materialSID, unsigned int quality )\r\n{\r\n\tauto modifiers = DB::select2( \"Modifier\", \"Quality\", \"Rank\", (int)quality );\r\n\tif ( modifiers.size() )\r\n\t{\r\n\t\tauto modifier = modifiers.first().toFloat();\r\n\t\tint value     = DB::select( \"Value\", \"Items\", itemSID ).toFloat() * DB::select( \"Value\", \"Materials\", materialSID ).toFloat() * modifier;\r\n\t\treturn value;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Inventory::itemTradeAvailable( unsigned int itemUID )\r\n{\r\n\tauto item = getItem( itemUID );\r\n\tif ( item )\r\n\t{\r\n\t\treturn (bool)item->isInStockpile() && item->isFree();\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nint Inventory::numFoodItems()\r\n{\r\n\treturn m_foodItems.size();\r\n}\r\n\r\nint Inventory::numDrinkItems()\r\n{\r\n\treturn m_drinkItems.size();\r\n}\r\n\r\nvoid Inventory::sanityCheck()\r\n{\r\n\tqDebug() << \"Starting inventory sanity check ...\";\r\n\tqDebug() << \"Checking containers\";\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tint removed = 0;\r\n\tfor ( auto it : m_hash[\"Crate\"] )\r\n\t{\r\n\t\tfor ( auto crate : it )\r\n\t\t{\r\n\t\t\tauto items = crate->containedItems();\r\n\r\n\t\t\tfor ( auto itemID : items )\r\n\t\t\t{\r\n\t\t\t\tif ( !itemExists( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t//qDebug() << itemID << \"doesn't exist: crate at \" << crate->getPos().toString();\r\n\r\n\t\t\t\t\t++removed;\r\n\t\t\t\t\tcrate->removeItem( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tqDebug() << \"Removed \" << QString::number( removed ) << \" invalid items from crates.\";\r\n\tremoved = 0;\r\n\tfor ( auto it : m_hash[\"Barrel\"] )\r\n\t{\r\n\t\tfor ( auto barrel : it )\r\n\t\t{\r\n\t\t\tauto items = barrel->containedItems();\r\n\r\n\t\t\tfor ( auto itemID : items )\r\n\t\t\t{\r\n\t\t\t\tif ( !itemExists( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t//qDebug() << itemID << \"doesn't exist: crate at \" << crate->getPos().toString();\r\n\t\t\t\t\t++removed;\r\n\t\t\t\t\tbarrel->removeItem( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tqDebug() << \"Removed \" << QString::number( removed ) << \" invalid items from barrels.\";\r\n\tremoved = 0;\r\n\tfor ( auto it : m_hash[\"Sack\"] )\r\n\t{\r\n\t\tfor ( auto sack : it )\r\n\t\t{\r\n\t\t\tauto items = sack->containedItems();\r\n\r\n\t\t\tfor ( auto itemID : items )\r\n\t\t\t{\r\n\t\t\t\tif ( !itemExists( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t//qDebug() << itemID << \"doesn't exist: crate at \" << crate->getPos().toString();\r\n\t\t\t\t\t++removed;\r\n\t\t\t\t\tsack->removeItem( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tqDebug() << \"Removed \" << QString::number( removed ) << \" invalid items from sacks.\";\r\n\tqDebug() << \"Sanity check took \" << timer.elapsed() << \"ms\";\r\n}\r\n\r\nQVariantList Inventory::components( unsigned int itemID )\r\n{\r\n\tauto item = getItem( itemID );\r\n\tif ( item )\r\n\t{\r\n\t\tauto def = item->serialize().toMap();\r\n\t\treturn def.value( \"Components\" ).toList();\r\n\t}\r\n\treturn QVariantList();\r\n}\r\n\r\nint Inventory::numItems()\r\n{\r\n\treturn m_items.size();\r\n}\r\n\r\nint Inventory::kingdomWealth()\r\n{\r\n\treturn m_wealth;\r\n}\r\n\r\nvoid Inventory::addToWealth( Item* item )\r\n{\r\n\tm_wealth += item->value();\r\n}\r\n\r\nvoid Inventory::removeFromWealth( Item* item )\r\n{\r\n\tm_wealth = qMax( 0, m_wealth - item->value() );\r\n}\r\n\r\nbool Inventory::itemsChanged()\r\n{\r\n\tbool out       = m_itemsChanged;\r\n\tm_itemsChanged = false;\r\n\treturn out;\r\n}\r\n\r\nvoid Inventory::setItemsChanged()\r\n{\r\n\tm_itemsChanged = true;\r\n}\r\n\r\nQString Inventory::itemGroup( unsigned int itemID )\r\n{\r\n\tauto item = getItem( itemID );\r\n\tif ( item )\r\n\t{\r\n\t\treturn DBH::itemGroup( item->itemSID() );\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nQList<QString> Inventory::allMats( unsigned int itemID )\r\n{\r\n\tauto item = getItem( itemID );\r\n\tif ( item )\r\n\t{\r\n\t\tQStringList out;\r\n\r\n\t\tauto comps = item->components();\r\n\t\tif( comps.size() )\r\n\t\t{\r\n\t\t\tfor( const auto& comp : comps )\r\n\t\t\t{\r\n\t\t\t\tout.append( DBH::materialSID( comp.materialUID ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tout.append( item->materialSID() );\r\n\t\t}\r\n\r\n\r\n\t\treturn out;\r\n\t}\r\n\treturn QStringList();\r\n}\r\n\r\nItemHistory* Inventory::itemHistory()\r\n{\r\n\treturn m_itemHistory;\r\n}\r\n"
  },
  {
    "path": "src/game/inventory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n\r\n#include \"../base/priorityqueue.h\"\r\n#include \"../game/item.h\"\r\n\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QString>\r\n\r\ntypedef QSet<unsigned int> PositionEntry;\r\ntypedef QHash<unsigned int, PositionEntry> PositionHash;\r\n\r\nclass ItemHistory;\r\nclass Octree;\r\nclass StockpileManager;\r\nclass World;\r\nclass Game;\r\n\r\nclass Inventory : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( Inventory )\r\npublic:\r\n\tInventory() = delete;\r\n\tInventory( Game* parent );\r\n\t~Inventory();\r\n\r\n\tvoid saveFilter();\r\n\tvoid loadFilter();\r\n\r\n\tbool itemExists( unsigned int itemID );\r\n\r\n\tunsigned int createItem( Position pos, QString itemSID, QString material );\r\n\tunsigned int createItem( Position pos, QString itemSID, QList<unsigned int> components );\r\n\tunsigned int createItem( Position pos, QString itemSID, QVariantList components );\r\n\tunsigned int createItem( const QVariantMap& values );\r\n\r\n\tvoid destroyObject( unsigned int id );\r\n\r\n\tunsigned int getFirstObjectAtPosition( const Position& pos );\r\n\tbool getObjectsAtPosition( const Position& pos, PositionEntry& pe );\r\n\r\n\tunsigned int getClosestItem( const Position& pos, bool allowInStockpile, QString itemID, QString materialID = \"any\" );\r\n\t//from construction dialog with materialTypes selected any\r\n\tunsigned int getClosestItem2( const Position& pos, bool allowInStockpile, QString itemID, QSet<QString> materialTypes );\r\n\tunsigned int getItemAtPos( const Position& pos, bool allowInStockpile, QString itemID, QString materialID = \"any\" );\r\n\r\n\tQList<unsigned int> getClosestItems( const Position& pos, bool allowInStockpile, QList<QPair<QString, QString>> filter, int count );\r\n\r\n\t/**\r\n\t* get closest items with connected region check\r\n\t*/\r\n\tQList<unsigned int> getClosestItems( const Position& pos, bool allowInStockpile, QString itemSID, QString materialSID, int count );\r\n\tbool checkReachableItems( Position pos, bool allowInStockpile, int count, QString itemSID, QString materialSID = \"any\" );\r\n\tQList<unsigned int> getClosestItemsForStockpile( unsigned int stockpileID, Position& pos, bool allowInStockpile, QSet<QPair<QString, QString>> filter );\r\n\r\n\tunsigned int getFoodItem( Position& pos );\r\n\tunsigned int getDrinkItem( Position& pos );\r\n\r\n\tQList<unsigned int> tradeInventory( QString itemSID, QString materialSID );\r\n\tQList<unsigned int> tradeInventory( QString itemSID, QString materialSID, unsigned char quality );\r\n\r\n\tvoid moveItemToPos( unsigned int item, const Position& newPos );\r\n\r\n\tunsigned int pickUpItem( unsigned int id, unsigned int creatureID );\r\n\tunsigned int putDownItem( unsigned int id, const Position& newPos );\r\n\tunsigned int isHeldBy( unsigned int id );\r\n\r\n\r\n\tQList<QString> categories();\r\n\tQList<QString> groups( QString category );\r\n\tQList<QString> items( QString category, QString group );\r\n\tQList<QString> materials( QString category, QString group, QString item );\r\n\r\n\tbool isInGroup( QString category, QString group, unsigned int itemUID );\r\n\r\n\tQMap<QString, int> materialCountsForItem( QString itemID, bool allowInJob = false );\r\n\tunsigned int itemCount( QString itemID, QString materialID );\r\n\tunsigned int itemCountWithInJob( QString itemID, QString materialID );\r\n\tunsigned int itemCountInStockpile( QString itemID, QString materialID );\r\n\tunsigned int itemCountNotInStockpile( QString itemID, QString materialID );\r\n\r\n\tstruct ItemCountDetailed\r\n\t{\r\n\t\tunsigned int total;\r\n\t\tunsigned int inJob;\r\n\t\tunsigned int inStockpile;\r\n\t\tunsigned int equipped;\r\n\t\tunsigned int constructed;\r\n\t\tunsigned int loose;\r\n\t\tunsigned int totalValue;\r\n\t};\r\n\tItemCountDetailed itemCountDetailed( QString itemID, QString materialID );\r\n\r\n\r\n\tbool isContainer( unsigned int item );\r\n\r\n\tunsigned int isInStockpile( unsigned int id );\r\n\tvoid setInStockpile( unsigned int id, unsigned int stockpile );\r\n\tunsigned int isInJob( unsigned int id );\r\n\tvoid setInJob( unsigned int id, unsigned int job );\r\n\tunsigned int isInContainer( unsigned int id );\r\n\tvoid setInContainer( unsigned int id, unsigned int container );\r\n\tunsigned int isUsedBy( unsigned int id );\r\n\tvoid setIsUsedBy( unsigned int id, unsigned int creatureID );\r\n\r\n\t\r\n\r\n\tbool isConstructed( unsigned int id );\r\n\tvoid setConstructed( unsigned int id, bool status );\r\n\r\n\tvoid putItemInContainer( unsigned int id, unsigned int container );\r\n\tvoid removeItemFromContainer( unsigned int id );\r\n\r\n\tQString pixmapID( unsigned int item );\r\n\tQString designation( unsigned int item );\r\n\tQString itemSID( unsigned int item );\r\n\tunsigned int itemUID( unsigned int item );\r\n\tQString materialSID( unsigned int item );\r\n\tunsigned int materialUID( unsigned int item );\r\n\tQString combinedID( unsigned int item );\r\n\tunsigned int spriteID( unsigned int item );\r\n\r\n\tPosition getItemPos( unsigned int item );\r\n\tvoid setItemPos( unsigned int item, const Position& pos );\r\n\r\n\tunsigned int value( unsigned int item );\r\n\tvoid setValue( unsigned int item, unsigned int value );\r\n\tunsigned int madeBy( unsigned int item );\r\n\tvoid setMadeBy( unsigned int item, unsigned int creatureID );\r\n\tunsigned char quality( unsigned int item );\r\n\tvoid setQuality( unsigned int item, unsigned char quality );\r\n\r\n\tunsigned char stackSize( unsigned int item );\r\n\tunsigned char capacity( unsigned int item );\r\n\tbool requireSame( unsigned int item );\r\n\r\n\tunsigned char nutritionalValue( unsigned int item );\r\n\tunsigned char drinkValue( unsigned int item );\r\n\r\n\tint attackValue( unsigned int item );\r\n\tbool isWeapon( unsigned int item );\r\n\r\n\tbool isTool( unsigned int item );\r\n\r\n\tvoid setColor( unsigned int item, QString color );\r\n\tunsigned int color( unsigned int item );\r\n\r\n\tconst QSet<unsigned int>& itemsInContainer( unsigned int container );\r\n\r\n\tint countItemsAtPos( Position& pos );\r\n\r\n\tQHash<unsigned int, Item>& allItems()\r\n\t{\r\n\t\treturn m_items;\r\n\t}\r\n\r\n\tQList<QString> materialsForItem( QString itemSID, int count );\r\n\r\n\tbool isSameTypeAndMaterial( unsigned int item, unsigned int item2 );\r\n\r\n\tvoid gravity( Position pos );\r\n\r\n\tint distanceSquare( unsigned int itemID, Position pos );\r\n\r\n\tunsigned int getTradeValue( QString itemSID, QString materialSID, unsigned int quality );\r\n\tbool itemTradeAvailable( unsigned int itemUID );\r\n\r\n\tPosition getPosition( unsigned int itemID );\r\n\r\n\tint numFoodItems();\r\n\tint numDrinkItems();\r\n\r\n\tvoid sanityCheck();\r\n\r\n\tQVariantList components( unsigned int itemID );\r\n\r\n\tvoid addToWealth( Item* item );\r\n\tvoid removeFromWealth( Item* item );\r\n\r\n\tint kingdomWealth();\r\n\tint numItems();\r\n\r\n\tbool itemsChanged();\r\n\tvoid setItemsChanged();\r\n\r\n\tQString itemGroup( unsigned int itemID );\r\n\r\n\tQList<QString> allMats( unsigned int itemID );\r\n\r\n\tItemHistory* itemHistory();\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQPointer<ItemHistory> m_itemHistory;\r\n\r\n\tOctree* octree( const QString& itemSID, const QString& materialSID );\r\n\r\n\tint m_dimX;\r\n\tint m_dimY;\r\n\tint m_dimZ;\r\n\r\n\tQHash<unsigned int, Item> m_items;\r\n\r\n\tPositionHash m_positionHash;\r\n\tQHash<QString, QHash<QString, QHash<unsigned int, Item*>>> m_hash;\r\n\tQHash<QString, QHash<QString, Octree*>> m_octrees;\r\n\r\n\tQList<QString> m_categoriesSorted;\r\n\tQMap<QString, QList<QString>> m_groupsSorted;\r\n\tQMap<QString, QMap<QString, QList<QString>>> m_itemsSorted;\r\n\r\n\tQHash<QString, QStringList> m_materialsInTypes;\r\n\r\n\tQStringList m_foodItemLookup;\r\n\tQStringList m_drinkItemLookup;\r\n\r\n\tQMap<unsigned int, unsigned char> m_foodItems;\r\n\tQMap<unsigned int, unsigned char> m_drinkItems;\r\n\r\n\tvoid addObject( Item& object, const QString& itemID, const QString& materialID );\r\n\tvoid init();\r\n\r\n\tItem* getItem( unsigned int itemUID );\r\n\r\n\tint m_wealth = 0;\r\n\r\n\tbool m_itemsChanged = false; //flag is used for updating the stock overview\r\n\r\nsignals:\r\n\tvoid signalAddItem( QString itemSID, QString materialSID );\r\n\tvoid signalRemoveItem( QString itemSID, QString materialSID );\r\n};\r\n"
  },
  {
    "path": "src/game/item.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"item.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include \"jobmanager.h\"\r\n\r\n#include <QDebug>\r\n#include <QVariantMap>\r\n\r\nItem::Item() :\r\n\tObject( Position( 0, 0, 0 ) )\r\n{\r\n}\r\n\r\nItem::Item( Position& pos, QString itemSID, QString materialSID ) :\r\n\tObject( pos )\r\n{\r\n\tm_itemUID     = DBH::itemUID( itemSID );\r\n\tm_materialUID = DBH::materialUID( materialSID );\r\n\tint value     = DB::select( \"Value\", \"Items\", itemSID ).toFloat() * DB::select( \"Value\", \"Materials\", materialSID ).toFloat();\r\n\tsetValue( value );\r\n\t{\r\n\t\tsetNutritionalValue( DB::select( \"EatValue\", \"Items\", itemSID ).toInt() );\r\n\t\tsetDrinkValue( DB::select( \"DrinkValue\", \"Items\", itemSID ).toInt() );\r\n\t}\r\n\tif ( DB::select( \"IsContainer\", \"Items\", itemSID ).toBool() )\r\n\t{\r\n\t\tif ( !m_extraData )\r\n\t\t{\r\n\t\t\tm_extraData = new ItemExtraData;\r\n\t\t}\r\n\t\tm_extraData->capacity    = DB::select( \"Capacity\", \"Containers\", itemSID ).value<unsigned char>();\r\n\t\tm_extraData->requireSame = DB::select( \"RequireSame\", \"Containers\", itemSID ).toBool();\r\n\t}\r\n}\r\n\r\nItem::Item( QVariantMap in ) :\r\n\tObject( in )\r\n{\r\n\t/*\r\n\tm_id = in.value( \"ID\" ).toUInt();\r\n\tm_position = Position( in.value( \"Position\" ).toString() );\r\n\tm_spriteID = in.value( \"SpriteID\" ).toUInt();\r\n\t*/\r\n\tQString itemSID = in.value( \"ItemSID\" ).toString();\r\n\tm_itemUID       = DBH::itemUID( itemSID );\r\n\tm_materialUID   = DBH::materialUID( in.value( \"MaterialSID\" ).toString() );\r\n\tm_isInStockpile = in.value( \"InStockpile\" ).toUInt();\r\n\tm_isInJob       = in.value( \"InJob\" ).toUInt();\r\n\tm_isUsedBy      = in.value( \"IsUsedBy\" ).toUInt();\r\n\tm_isInContainer = in.value( \"InContainer\" ).toUInt();\r\n\tm_isConstructed = in.value( \"Constructed\" ).toBool();\r\n\tif( in.contains( \"IsHeldBy\") )\r\n\t{\r\n\t\tm_isHeldBy = in.value( \"IsHeldBy\" ).toUInt();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif( in.contains( \"IsPickedUp\" ) )\r\n\t\t{\r\n\t\t\t// legacy save game, need to determine who is holding the item\r\n\t\t\tif( in.value( \"IsPickedUp\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\tm_isHeldBy = 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_value         = in.value( \"Value\" ).toUInt();\r\n\tm_madeBy        = in.value( \"MadeBy\" ).toUInt();\r\n\tm_quality       = in.value( \"Quality\" ).toUInt();\r\n\r\n\tif ( in.value( \"Extra\" ).toBool() )\r\n\t{\r\n\t\tm_extraData = new ItemExtraData;\r\n\t}\r\n\r\n\tif ( in.contains( \"Items\" ) )\r\n\t{\r\n\t\tQVariantList vli = in.value( \"Items\" ).toList();\r\n\t\tfor ( auto item : vli )\r\n\t\t{\r\n\t\t\tm_extraData->containedItems.insert( item.toUInt() );\r\n\t\t}\r\n\t}\r\n\tif ( in.contains( \"Components\" ) )\r\n\t{\r\n\t\tQVariantList vlc = in.value( \"Components\" ).toList();\r\n\t\tfor ( auto item : vlc )\r\n\t\t{\r\n\t\t\tQVariantMap cvm = item.toMap();\r\n\t\t\tItemMaterial im = { (unsigned int)DBH::itemUID( cvm.value( \"ItSID\" ).toString() ),\r\n\t\t\t\t\t\t\t\t(unsigned int)DBH::materialUID( cvm.value( \"MaSID\" ).toString() ) };\r\n\t\t\tm_extraData->components.append( im );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( in.contains( \"EatValue\" ) )\r\n\t{\r\n\t\tm_extraData->nutritionalValue = in.value( \"EatValue\" ).toUInt();\r\n\t}\r\n\tif ( in.contains( \"DrinkValue\" ) )\r\n\t{\r\n\t\tm_extraData->drinkValue = in.value( \"DrinkValue\" ).toUInt();\r\n\t}\r\n\tif ( DBH::itemIsContainer( m_itemUID ) )\r\n\t{\r\n\t\tif ( !m_extraData )\r\n\t\t{\r\n\t\t\tm_extraData = new ItemExtraData;\r\n\t\t}\r\n\t\tm_extraData->capacity    = DB::select( \"Capacity\", \"Containers\", itemSID ).value<unsigned char>();\r\n\t\tm_extraData->requireSame = DB::select( \"RequireSame\", \"Containers\", itemSID ).toBool();\r\n\t}\r\n}\r\n\r\nItem::Item( const Item& other ) :\r\n\tm_itemUID( other.m_itemUID ),\r\n\tm_materialUID( other.m_materialUID ),\r\n\tm_isInStockpile( other.m_isInStockpile ),\r\n\tm_isInJob( other.m_isInJob ),\r\n\tm_isInContainer( other.m_isInContainer ),\r\n\tm_isConstructed( other.m_isConstructed ),\r\n\tm_isHeldBy( other.m_isHeldBy ),\r\n\tm_value( other.m_value ),\r\n\tm_madeBy( other.m_madeBy ),\r\n\tm_quality( other.m_quality ),\r\n\tm_extraData( nullptr )\r\n{\r\n\tm_id       = other.m_id;\r\n\tm_position = other.m_position;\r\n\tm_spriteID = other.m_spriteID;\r\n\r\n\tif ( other.m_extraData != nullptr )\r\n\t{\r\n\t\tm_extraData                   = new ItemExtraData;\r\n\t\tm_extraData->components       = other.m_extraData->components;\r\n\t\tm_extraData->containedItems   = other.m_extraData->containedItems;\r\n\t\tm_extraData->nutritionalValue = other.m_extraData->nutritionalValue;\r\n\t\tm_extraData->drinkValue       = other.m_extraData->drinkValue;\r\n\t\tm_extraData->capacity         = other.m_extraData->capacity;\r\n\t\tm_extraData->requireSame      = other.m_extraData->requireSame;\r\n\t}\r\n}\r\n\r\nItem::~Item()\r\n{\r\n\tif ( m_extraData != nullptr )\r\n\t{\r\n\t\tdelete m_extraData;\r\n\t}\r\n}\r\n\r\nQVariant Item::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tObject::serialize( out );\r\n\t/*\r\n\tout.insert( \"ID\", m_id );\r\n\tout.insert( \"Position\", m_position.toString() );\r\n\tout.insert( \"SpriteID\", m_spriteID );\r\n\t*/\r\n\tout.insert( \"ItemSID\", itemSID() );\r\n\tout.insert( \"MaterialSID\", materialSID() );\r\n\tout.insert( \"InStockpile\", m_isInStockpile );\r\n\tout.insert( \"InJob\", m_isInJob );\r\n\tout.insert( \"InContainer\", m_isInContainer );\r\n\tout.insert( \"Constructed\", m_isConstructed );\r\n\tout.insert( \"IsHeldBy\", m_isHeldBy );\r\n\tout.insert( \"IsUsedBy\", m_isUsedBy );\r\n\tout.insert( \"Value\", m_value );\r\n\tout.insert( \"MadeBy\", m_madeBy );\r\n\tout.insert( \"Quality\", m_quality );\r\n\r\n\tif ( m_extraData != nullptr )\r\n\t{\r\n\t\tout.insert( \"Extra\", true );\r\n\r\n\t\tout.insert( \"EatValue\", m_extraData->nutritionalValue );\r\n\t\tout.insert( \"DrinkValue\", m_extraData->drinkValue );\r\n\r\n\t\tif ( !m_extraData->containedItems.empty() )\r\n\t\t{\r\n\t\t\tQVariantList vli;\r\n\t\t\tfor ( auto i : m_extraData->containedItems )\r\n\t\t\t\tvli.append( i );\r\n\t\t\tout.insert( \"Items\", vli );\r\n\t\t}\r\n\t\tif ( !m_extraData->components.empty() )\r\n\t\t{\r\n\t\t\tQVariantList vli;\r\n\t\t\tfor ( auto comp : m_extraData->components )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap vm;\r\n\t\t\t\tvm.insert( \"ItSID\", DBH::itemSID( comp.itemUID ) );\r\n\t\t\t\tvm.insert( \"MaSID\", DBH::materialSID( comp.materialUID ) );\r\n\t\t\t\tvli.push_back( vm );\r\n\t\t\t}\r\n\t\t\tout.insert( \"Components\", vli );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nunsigned short Item::materialUID() const\r\n{\r\n\treturn m_materialUID;\r\n}\r\n\r\nunsigned short Item::itemUID() const\r\n{\r\n\treturn m_itemUID;\r\n}\r\n\r\nQString Item::getPixmapSID() const\r\n{\r\n\treturn DBH::spriteID( DBH::itemSID( m_itemUID ) ) + \"_\" + DBH::materialSID( m_materialUID );\r\n}\r\n\r\nQString Item::getDesignation() const\r\n{\r\n\treturn S::s( \"$MaterialName_\" + DBH::materialSID( m_materialUID ) ) + \" \" + S::s( \"$ItemName_\" + DBH::itemSID( m_itemUID ) );\r\n}\r\n\r\nQString Item::itemSID() const\r\n{\r\n\treturn DBH::itemSID( m_itemUID );\r\n}\r\n\r\nQString Item::materialSID() const\r\n{\r\n\treturn DBH::materialSID( m_materialUID );\r\n}\r\n\r\nQString Item::combinedSID() const\r\n{\r\n\treturn DBH::itemSID( m_itemUID ) + \"_\" + DBH::materialSID( m_materialUID );\r\n}\r\n\r\nint Item::distanceSquare( const Position& pos, int zWeight ) const\r\n{\r\n\treturn ( m_position.x - pos.x ) * ( m_position.x - pos.x ) + ( m_position.y - pos.y ) * ( m_position.y - pos.y ) + ( m_position.z - pos.z ) * ( m_position.z - pos.z ) * zWeight;\r\n}\r\n\r\nbool Item::isContainer() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->capacity > 0;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nconst QSet<unsigned int>& Item::containedItems() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->containedItems;\r\n\t}\r\n\tstatic const QSet<unsigned int> nullopt;\r\n\treturn nullopt;\r\n}\r\n\r\nunsigned char Item::capacity() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->capacity;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Item::requireSame() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->requireSame;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nunsigned int Item::isInStockpile() const\r\n{\r\n\treturn m_isInStockpile;\r\n}\r\n\r\nvoid Item::setInStockpile( unsigned int stockpile )\r\n{\r\n\tm_isInStockpile = stockpile;\r\n}\r\n\r\nunsigned int Item::isInJob() const\r\n{\r\n\treturn m_isInJob;\r\n}\r\n\r\nvoid Item::setInJob( unsigned int job )\r\n{\r\n\tm_isInJob = job;\r\n}\r\n\r\nunsigned int Item::isInContainer() const\r\n{\r\n\treturn m_isInContainer;\r\n}\r\n\r\nvoid Item::setInContainer( unsigned int container )\r\n{\r\n\tm_isInContainer = container;\r\n}\r\n\r\nunsigned int Item::isHeldBy() const\r\n{\r\n\treturn m_isHeldBy;\r\n}\r\n\r\nvoid Item::setHeldBy( unsigned int creatureID )\r\n{\r\n\tm_isHeldBy = creatureID;\r\n}\r\n\r\nunsigned int Item::isUsedBy() const\r\n{\r\n\treturn m_isUsedBy;\r\n}\r\n\r\nvoid Item::setUsedBy( unsigned int creatureID )\r\n{\r\n\tm_isUsedBy = creatureID;\r\n}\r\n\r\nunsigned char Item::stackSize() const\r\n{\r\n\treturn DB::select( \"StackSize\", \"Items\", DBH::itemSID( m_itemUID ) ).toUInt();\r\n}\r\n\r\nbool Item::isConstructed() const\r\n{\r\n\treturn m_isConstructed;\r\n}\r\n\r\nvoid Item::setIsConstructed( bool value )\r\n{\r\n\tm_isConstructed = value;\r\n}\r\n\r\nvoid Item::addComponent( ItemMaterial im )\r\n{\r\n\tif ( m_extraData == nullptr )\r\n\t{\r\n\t\tm_extraData = new ItemExtraData;\r\n\t}\r\n\tm_extraData->components.push_back( im );\r\n}\r\n\r\nQList<ItemMaterial> Item::components() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->components;\r\n\t}\r\n\treturn {};\r\n}\r\n\r\nunsigned short Item::value() const\r\n{\r\n\treturn m_value * DBH::qualityMod(m_quality);\r\n}\r\n\r\nunsigned int Item::madeBy() const\r\n{\r\n\treturn m_madeBy;\r\n}\r\n\r\nvoid Item::setValue( unsigned short value )\r\n{\r\n\tm_value = value;\r\n}\r\n\r\nvoid Item::setMadeBy( unsigned int creatureID )\r\n{\r\n\tm_madeBy = creatureID;\r\n}\r\n\r\nunsigned char Item::quality() const\r\n{\r\n\treturn m_quality;\r\n}\r\n\r\nvoid Item::setQuality( unsigned char quality )\r\n{\r\n\tm_quality = quality;\r\n}\r\n\r\nunsigned char Item::nutritionalValue() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->nutritionalValue;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Item::setNutritionalValue( unsigned char value )\r\n{\r\n\tif ( value != 0 )\r\n\t{\r\n\t\tif ( m_extraData == nullptr )\r\n\t\t{\r\n\t\t\tm_extraData = new ItemExtraData;\r\n\t\t}\r\n\t\tm_extraData->nutritionalValue = value;\r\n\t}\r\n}\r\n\r\nunsigned char Item::drinkValue() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->drinkValue;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Item::setDrinkValue( unsigned char value )\r\n{\r\n\tif ( value != 0 )\r\n\t{\r\n\t\tif ( m_extraData == nullptr )\r\n\t\t{\r\n\t\t\tm_extraData = new ItemExtraData;\r\n\t\t}\r\n\t\tm_extraData->drinkValue = value;\r\n\t}\r\n}\r\n\r\nunsigned int Item::color() const\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->color;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid Item::setColor( QString color )\r\n{\r\n\t//TODO add alpha\r\n\tif ( !color.isEmpty() )\r\n\t{\r\n\t\tif ( m_extraData == nullptr )\r\n\t\t{\r\n\t\t\tm_extraData = new ItemExtraData;\r\n\t\t}\r\n\t\tm_extraData->color = Global::util->string2Color( color );\r\n\t}\r\n}\r\n\r\nint Item::attackValue() const\r\n{\r\n\treturn DB::select( \"AttackValue\", \"Items\", DBH::itemSID( m_itemUID ) ).toInt();\r\n}\r\n\r\nbool Item::isWeapon() const\r\n{\r\n\treturn DB::select( \"AttackValue\", \"Items\", DBH::itemSID( m_itemUID ) ).toInt() > 0;\r\n}\r\n\r\nbool Item::isTool() const\r\n{\r\n\treturn DB::select( \"IsTool\", \"Items\", DBH::itemSID( m_itemUID ) ).toBool();\r\n}\r\n\r\nbool Item::insertItem( unsigned int itemID )\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\tm_extraData->containedItems.insert( itemID );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Item::removeItem( unsigned int itemID )\r\n{\r\n\tif ( m_extraData )\r\n\t{\r\n\t\treturn m_extraData->containedItems.remove( itemID );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Item::isFree() const\r\n{\r\n\treturn !m_isConstructed && ( m_isInJob == 0 ) && ( m_isHeldBy == 0 ) && ( m_isUsedBy == 0 );\r\n}"
  },
  {
    "path": "src/game/item.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"object.h\"\r\n\r\nstruct ItemMaterial\r\n{\r\n\tunsigned int itemUID;\r\n\tunsigned int materialUID;\r\n};\r\n\r\nstruct ItemExtraData\r\n{\r\n\r\n\tQList<ItemMaterial> components;\r\n\tQSet<unsigned int> containedItems;\r\n\r\n\tunsigned char nutritionalValue = 0;\r\n\tunsigned char drinkValue       = 0;\r\n\r\n\tunsigned int color = 0;\r\n\r\n\tbool requireSame       = false;\r\n\tunsigned char capacity = 0;\r\n};\r\n\r\nclass Item : public Object\r\n{\r\npublic:\r\n\tItem();\r\n\tItem( Position& pos, QString itemSID, QString materialSID );\r\n\tItem( QVariantMap in );\r\n\tItem( const Item& other );\r\n\t~Item();\r\n\r\n\tvirtual QVariant serialize() const;\r\n\r\n\tunsigned short materialUID() const;\r\n\tunsigned short itemUID() const;\r\n\r\n\tQString getPixmapSID() const;\r\n\tQString getDesignation() const;\r\n\tQString itemSID() const;\r\n\tQString materialSID() const;\r\n\tQString combinedSID() const;\r\n\r\n\tbool insertItem( unsigned int itemID );\r\n\tbool removeItem( unsigned int itemID );\r\n\r\n\tint distanceSquare( const Position& pos, int zWeight = 1 ) const;\r\n\r\n\tvirtual bool isContainer() const;\r\n\r\n\tunsigned int isInStockpile() const;\r\n\tvoid setInStockpile( unsigned int stockpile );\r\n\tunsigned int isInJob() const;\r\n\tvoid setInJob( unsigned int job );\r\n\tunsigned int isInContainer() const;\r\n\tvoid setInContainer( unsigned int container );\r\n\tunsigned int isHeldBy() const;\r\n\tvoid setHeldBy( unsigned int creatureID );\r\n\tunsigned int isUsedBy() const;\r\n\tvoid setUsedBy( unsigned int creatureID );\r\n\r\n\tbool isConstructed() const;\r\n\tvoid setIsConstructed( bool value );\r\n\r\n\tunsigned char stackSize() const;\r\n\r\n\tunsigned short value() const;\r\n\tvoid setValue( unsigned short value );\r\n\tunsigned int madeBy() const;\r\n\tvoid setMadeBy( unsigned int creatureID );\r\n\r\n\tconst QSet<unsigned int>& containedItems() const;\r\n\tunsigned char capacity() const;\r\n\tbool requireSame() const;\r\n\r\n\tvoid addComponent( ItemMaterial im );\r\n\r\n\tQList<ItemMaterial> components() const;\r\n\r\n\tunsigned char quality() const;\r\n\tvoid setQuality( unsigned char quality );\r\n\r\n\tunsigned char nutritionalValue() const;\r\n\tvoid setNutritionalValue( unsigned char value );\r\n\r\n\tunsigned char drinkValue() const;\r\n\tvoid setDrinkValue( unsigned char value );\r\n\r\n\tint attackValue() const;\r\n\tbool isWeapon() const;\r\n\r\n\tbool isTool() const;\r\n\r\n\tunsigned int color() const;\r\n\tvoid setColor( QString color );\r\n\r\n\tbool isFree() const;\r\n\r\nprivate:\r\n\tunsigned short m_materialUID = 0;\r\n\tunsigned short m_itemUID     = 0;\r\n\r\n\tbool m_isConstructed = false;\r\n\r\n\tunsigned int m_isInStockpile = 0;\r\n\tunsigned int m_isInContainer = 0;\r\n\tunsigned int m_isInJob       = 0;\r\n\tunsigned int m_isHeldBy      = 0; // indicates the item is carried or equipped by a creature\r\n\tunsigned int m_isUsedBy      = 0;\r\n\r\n\tunsigned short m_value = 0;\r\n\tunsigned int m_madeBy  = 0;\r\n\r\n\tquint8 m_quality = 0; // 0 means item has no quality, quality is rowid of table Quality\r\n\r\n\tItemExtraData* m_extraData = nullptr;\r\n};\r\n"
  },
  {
    "path": "src/game/itemhistory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"itemhistory.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n\r\n#include <QDebug>\r\n\r\nItemHistory::ItemHistory( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nItemHistory::~ItemHistory()\r\n{\r\n}\r\n\r\nvoid ItemHistory::serialize( QVariantMap& out )\r\n{\r\n\tQVariantList items;\r\n\tfor ( auto key : m_itemsPresent.keys() )\r\n\t{\r\n\t\tQVariantMap item;\r\n\t\titem.insert( \"ID\", key );\r\n\t\tauto entry = m_itemsPresent[key];\r\n\t\tQVariantList mats;\r\n\t\tfor ( auto mat : entry )\r\n\t\t{\r\n\t\t\tmats.push_back( mat );\r\n\t\t}\r\n\t\titem.insert( \"Mats\", mats );\r\n\t\titems.push_back( item );\r\n\t}\r\n\tout.insert( \"Items\", items );\r\n\r\n\tQVariantList days;\r\n\tfor ( auto day : m_data )\r\n\t{\r\n\t\tQVariantMap vmDay;\r\n\t\tvmDay.insert( \"Day\", day.day );\r\n\t\tvmDay.insert( \"Season\", day.season );\r\n\t\tvmDay.insert( \"Year\", day.year );\r\n\t\tQVariantList dayData;\r\n\t\tfor ( auto itemKey : day.dayData.data.keys() )\r\n\t\t{\r\n\t\t\tauto entry = day.dayData.data[itemKey];\r\n\t\t\tQVariantMap itemData;\r\n\t\t\titemData.insert( \"ID\", itemKey );\r\n\t\t\tQVariantList matList;\r\n\t\t\tfor ( auto matKey : entry.keys() )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap matData;\r\n\t\t\t\tauto matEntry = entry[matKey];\r\n\t\t\t\tmatData.insert( \"ID\", matKey );\r\n\t\t\t\tmatData.insert( \"Total\", matEntry.total );\r\n\t\t\t\tmatData.insert( \"Plus\", matEntry.plus );\r\n\t\t\t\tmatData.insert( \"Minus\", matEntry.minus );\r\n\t\t\t\tmatList.append( matData );\r\n\t\t\t}\r\n\t\t\titemData.insert( \"Mats\", matList );\r\n\t\t\tdayData.append( itemData );\r\n\t\t}\r\n\t\tvmDay.insert( \"Data\", dayData );\r\n\t\tdays.append( vmDay );\r\n\t}\r\n\r\n\t{\r\n\t\tauto day = m_currentDay;\r\n\t\tQVariantMap vmDay;\r\n\t\tvmDay.insert( \"Day\", day.day );\r\n\t\tvmDay.insert( \"Season\", day.season );\r\n\t\tvmDay.insert( \"Year\", day.year );\r\n\t\tQVariantList dayData;\r\n\t\tfor ( auto itemKey : day.dayData.data.keys() )\r\n\t\t{\r\n\t\t\tauto entry = day.dayData.data[itemKey];\r\n\t\t\tQVariantMap itemData;\r\n\t\t\titemData.insert( \"ID\", itemKey );\r\n\t\t\tQVariantList matList;\r\n\t\t\tfor ( auto matKey : entry.keys() )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap matData;\r\n\t\t\t\tauto matEntry = entry[matKey];\r\n\t\t\t\tmatData.insert( \"ID\", matKey );\r\n\t\t\t\tmatData.insert( \"Total\", matEntry.total );\r\n\t\t\t\tmatData.insert( \"Plus\", matEntry.plus );\r\n\t\t\t\tmatData.insert( \"Minus\", matEntry.minus );\r\n\t\t\t\tmatList.append( matData );\r\n\t\t\t}\r\n\t\t\titemData.insert( \"Mats\", matList );\r\n\t\t\tdayData.append( itemData );\r\n\t\t}\r\n\t\tvmDay.insert( \"Data\", dayData );\r\n\t\tdays.append( vmDay );\r\n\t}\r\n\tout.insert( \"Days\", days );\r\n}\r\n\r\nvoid ItemHistory::deserialize( const QVariantMap& in )\r\n{\r\n\treset();\r\n\r\n\tauto vlItems = in.value( \"Items\" ).toList();\r\n\tfor ( auto entry : vlItems )\r\n\t{\r\n\t\tQString itemSID = entry.toMap().value( \"ID\" ).toString();\r\n\t\tQSet<QString> mats;\r\n\t\tfor ( auto vmat : entry.toMap().value( \"Mats\" ).toList() )\r\n\t\t{\r\n\t\t\tmats.insert( vmat.toString() );\r\n\t\t}\r\n\t\tm_itemsPresent.insert( itemSID, mats );\r\n\t}\r\n\r\n\tauto vlDays = in.value( \"Days\" ).toList();\r\n\r\n\tQVariantMap vCurrentDay;\r\n\tif ( vlDays.size() > 0 )\r\n\t{\r\n\t\tvCurrentDay = vlDays.last().toMap();\r\n\t\tvlDays.pop_back();\r\n\t}\r\n\r\n\tfor ( auto dayEntry : vlDays )\r\n\t{\r\n\t\tauto vmDay = dayEntry.toMap();\r\n\t\tIH_day ihd;\r\n\t\tihd.day    = vmDay.value( \"Day\" ).toInt();\r\n\t\tihd.season = vmDay.value( \"Season\" ).toInt();\r\n\t\tihd.year   = vmDay.value( \"Year\" ).toInt();\r\n\r\n\t\tauto vlItemData = vmDay.value( \"Data\" ).toList();\r\n\r\n\t\tIH_dayData dd;\r\n\r\n\t\tfor ( auto itemEntry : vlItemData )\r\n\t\t{\r\n\t\t\tQString itemSID = itemEntry.toMap().value( \"ID\" ).toString();\r\n\t\t\tauto mats       = itemEntry.toMap().value( \"Mats\" ).toList();\r\n\t\t\tQMap<QString, IH_values> vMats;\r\n\t\t\tfor ( auto matEntry : mats )\r\n\t\t\t{\r\n\t\t\t\tauto vmMat = matEntry.toMap();\r\n\t\t\t\tIH_values iv;\r\n\t\t\t\tiv.total = vmMat.value( \"Total\" ).toInt();\r\n\t\t\t\tiv.plus  = vmMat.value( \"Plus\" ).toInt();\r\n\t\t\t\tiv.minus = vmMat.value( \"Minus\" ).toInt();\r\n\t\t\t\tvMats.insert( vmMat.value( \"ID\" ).toString(), iv );\r\n\t\t\t}\r\n\t\t\tdd.data.insert( itemSID, vMats );\r\n\t\t}\r\n\t\tihd.dayData = dd;\r\n\t\tm_data.push_back( ihd );\r\n\t}\r\n\t{\r\n\t\tauto vmDay = vCurrentDay;\r\n\t\tIH_day ihd;\r\n\t\tihd.day    = vmDay.value( \"Day\" ).toInt();\r\n\t\tihd.season = vmDay.value( \"Season\" ).toInt();\r\n\t\tihd.year   = vmDay.value( \"Year\" ).toInt();\r\n\r\n\t\tauto vlItemData = vmDay.value( \"Data\" ).toList();\r\n\r\n\t\tIH_dayData dd;\r\n\r\n\t\tfor ( auto itemEntry : vlItemData )\r\n\t\t{\r\n\t\t\tQString itemSID = itemEntry.toMap().value( \"ID\" ).toString();\r\n\t\t\tauto mats       = itemEntry.toMap().value( \"Mats\" ).toList();\r\n\t\t\tQMap<QString, IH_values> vMats;\r\n\t\t\tfor ( auto matEntry : mats )\r\n\t\t\t{\r\n\t\t\t\tauto vmMat = matEntry.toMap();\r\n\t\t\t\tIH_values iv;\r\n\t\t\t\tiv.total = vmMat.value( \"Total\" ).toInt();\r\n\t\t\t\tiv.plus  = vmMat.value( \"Plus\" ).toInt();\r\n\t\t\t\tiv.minus = vmMat.value( \"Minus\" ).toInt();\r\n\t\t\t\tvMats.insert( vmMat.value( \"ID\" ).toString(), iv );\r\n\t\t\t}\r\n\t\t\tdd.data.insert( itemSID, vMats );\r\n\t\t}\r\n\t\tihd.dayData  = dd;\r\n\t\tm_currentDay = ihd;\r\n\t}\r\n}\r\n\r\nvoid ItemHistory::reset()\r\n{\r\n\tm_data.clear();\r\n\tm_startUp = true;\r\n\tinit();\r\n}\r\n\r\nvoid ItemHistory::init()\r\n{\r\n\tm_currentDay.dayData.data.clear();\r\n}\r\n\r\nvoid ItemHistory::onTick( bool dayChanged )\r\n{\r\n\tif ( dayChanged )\r\n\t{\r\n\t\tnewDay();\r\n\t}\r\n}\r\n\r\nvoid ItemHistory::newDay()\r\n{\r\n\tm_data.push_back( m_currentDay );\r\n\tm_currentDay.day    = GameState::day;\r\n\tm_currentDay.season = GameState::season;\r\n\tm_currentDay.year   = GameState::year;\r\n\r\n\tauto lastData = m_currentDay.dayData.data;\r\n\tfor ( auto key : lastData.keys() )\r\n\t{\r\n\t\tauto& entry = lastData[key];\r\n\t\tQMap<QString, IH_values> newDayData;\r\n\t\tfor ( auto matKey : entry.keys() )\r\n\t\t{\r\n\t\t\tauto& matEntry = entry[matKey];\r\n\t\t\tIH_values newVals;\r\n\t\t\tnewVals.total = matEntry.total;\r\n\t\t\tnewDayData.insert( matKey, newVals );\r\n\t\t}\r\n\t\tm_currentDay.dayData.data.insert( key, newDayData );\r\n\t}\r\n}\r\n\r\nvoid ItemHistory::plusItem( QString itemSID, QString materialSID )\r\n{\r\n\tif ( m_currentDay.dayData.data.contains( itemSID ) )\r\n\t{\r\n\t\tauto& materialEntry = m_currentDay.dayData.data[itemSID];\r\n\t\tif ( materialEntry.contains( materialSID ) )\r\n\t\t{\r\n\t\t\tauto& counts = materialEntry[materialSID];\r\n\t\t\tcounts.total = counts.total + 1;\r\n\t\t\tif ( !m_startUp )\r\n\t\t\t{\r\n\t\t\t\tcounts.plus = counts.plus + 1;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( m_startUp )\r\n\t\t\t{\r\n\t\t\t\tIH_values mv { 1, 0, 0 };\r\n\t\t\t\tmaterialEntry.insert( materialSID, mv );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tIH_values mv { 1, 1, 0 };\r\n\t\t\t\tmaterialEntry.insert( materialSID, mv );\r\n\t\t\t}\r\n\r\n\t\t\tm_itemsPresent[itemSID].insert( materialSID );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tQMap<QString, IH_values> matEntry;\r\n\t\tif ( m_startUp )\r\n\t\t{\r\n\t\t\tmatEntry.insert( materialSID, IH_values { 1, 0, 0 } );\r\n\t\t\tm_currentDay.dayData.data.insert( itemSID, matEntry );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tmatEntry.insert( materialSID, IH_values { 1, 1, 0 } );\r\n\t\t\tm_currentDay.dayData.data.insert( itemSID, matEntry );\r\n\t\t}\r\n\t\tQSet<QString> mats;\r\n\t\tmats.insert( materialSID );\r\n\t\tm_itemsPresent.insert( itemSID, mats );\r\n\t}\r\n}\r\n\r\nvoid ItemHistory::minusItem( QString itemSID, QString materialSID )\r\n{\r\n\tif ( m_currentDay.dayData.data.contains( itemSID ) )\r\n\t{\r\n\t\tauto& entry = m_currentDay.dayData.data[itemSID];\r\n\t\tif ( entry.contains( materialSID ) )\r\n\t\t{\r\n\t\t\tauto& counts = entry[materialSID];\r\n\t\t\tcounts.total = counts.total - 1;\r\n\t\t\tif ( !m_startUp )\r\n\t\t\t{\r\n\t\t\t\tcounts.minus = counts.minus + 1;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQMap<QString, QVector<IH_values>> ItemHistory::getHistory( QString itemSID )\r\n{\r\n\tQMap<QString, QVector<IH_values>> out;\r\n\r\n\tQSet<QString> mats = m_itemsPresent.value( itemSID );\r\n\tout.insert( \"all\", QVector<IH_values>() );\r\n\tfor ( auto mat : mats )\r\n\t{\r\n\t\tout.insert( mat, QVector<IH_values>() );\r\n\t}\r\n\r\n\tfor ( int i = 0; i < m_data.size(); ++i )\r\n\t{\r\n\t\tauto dayData = m_data[i];\r\n\t\tif ( dayData.dayData.data.contains( itemSID ) )\r\n\t\t{\r\n\t\t\tauto itemData = dayData.dayData.data[itemSID];\r\n\t\t\tIH_values allValues;\r\n\t\t\tfor ( auto mat : mats )\r\n\t\t\t{\r\n\t\t\t\tif ( itemData.contains( mat ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto data = itemData[mat];\r\n\t\t\t\t\tallValues.total += data.total;\r\n\t\t\t\t\tallValues.plus += data.plus;\r\n\t\t\t\t\tallValues.minus += data.minus;\r\n\t\t\t\t\tout[mat].push_back( data );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// item with that material doesn't exist yet, insert empty\r\n\t\t\t\t\tIH_values matValues;\r\n\t\t\t\t\tout[mat].push_back( matValues );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tout[\"all\"].push_back( allValues );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// item doesn't exist yet, insert empty for all materials\r\n\t\t\tIH_values matValues;\r\n\t\t\tfor ( auto key : out.keys() )\r\n\t\t\t{\r\n\t\t\t\tout[key].push_back( matValues );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t{\r\n\t\tauto dayData = m_currentDay;\r\n\t\tif ( dayData.dayData.data.contains( itemSID ) )\r\n\t\t{\r\n\t\t\tauto itemData = dayData.dayData.data[itemSID];\r\n\t\t\tIH_values allValues;\r\n\t\t\tfor ( auto mat : mats )\r\n\t\t\t{\r\n\t\t\t\tif ( itemData.contains( mat ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto data = itemData[mat];\r\n\t\t\t\t\tallValues.total += data.total;\r\n\t\t\t\t\tallValues.plus += data.plus;\r\n\t\t\t\t\tallValues.minus += data.minus;\r\n\t\t\t\t\tout[mat].push_back( data );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\t// item with that material doesn't exist yet, insert empty\r\n\t\t\t\t\tIH_values matValues;\r\n\t\t\t\t\tout[mat].push_back( matValues );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tout[\"all\"].push_back( allValues );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// item doesn't exist yet, insert empty for all materials\r\n\t\t\tIH_values matValues;\r\n\t\t\tfor ( auto key : out.keys() )\r\n\t\t\t{\r\n\t\t\t\tout[key].push_back( matValues );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQMap<QString, QVector<IH_values>> ItemHistory::getRandomHistory( QString itemSID )\r\n{\r\n\tQMap<QString, QVector<IH_values>> out;\r\n\r\n\tfor ( int k = 1; k < 8; ++k )\r\n\t{\r\n\t\tQVector<IH_values> vec;\r\n\r\n\t\tint total = 0;\r\n\t\tfor ( int i = 0; i < 20; ++i )\r\n\t\t{\r\n\t\t\tint plus  = rand() % 20;\r\n\t\t\tint minus = qMin( total, rand() % 20 );\r\n\t\t\ttotal += plus - minus;\r\n\r\n\t\t\tIH_values mv { total, plus, minus };\r\n\t\t\tvec.push_back( mv );\r\n\t\t}\r\n\r\n\t\tout.insert( \"material_\" + QString::number( k ), vec );\r\n\t}\r\n\r\n\treturn out;\r\n}"
  },
  {
    "path": "src/game/itemhistory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMap>\r\n#include <QObject>\r\n#include <QSet>\r\n\r\nstruct IH_values\r\n{\r\n\tint total = 0;\r\n\tint plus  = 0;\r\n\tint minus = 0;\r\n};\r\n\r\nstruct IH_dayData\r\n{\r\n\tQMap<QString, QMap<QString, IH_values>> data;\r\n};\r\n\r\nstruct IH_day\r\n{\r\n\tint day    = 1;\r\n\tint season = 1;\r\n\tint year   = 1;\r\n\r\n\tIH_dayData dayData;\r\n};\r\n\r\nclass ItemHistory : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( ItemHistory )\r\npublic:\r\n\tItemHistory( QObject* parent = nullptr );\r\n\t~ItemHistory();\r\n\r\n\tvoid serialize( QVariantMap& out );\r\n\tvoid deserialize( const QVariantMap& in );\r\n\r\n\tvoid reset();\r\n\tvoid init();\r\n\tvoid onTick( bool dayChanged );\r\n\tvoid plusItem( QString itemSID, QString materialSID );\r\n\tvoid minusItem( QString itemSID, QString materialSID );\r\n\r\n\tvoid finishStart()\r\n\t{\r\n\t\tm_startUp = false;\r\n\t}\r\n\r\n\tQMap<QString, QSet<QString>> allItems()\r\n\t{\r\n\t\treturn m_itemsPresent;\r\n\t}\r\n\r\n\tQMap<QString, QVector<IH_values>> getHistory( QString itemSID );\r\n\r\n\tQMap<QString, QVector<IH_values>> getRandomHistory( QString itemSID );\r\n\r\nprivate:\r\n\tvoid newDay();\r\n\r\n\tQList<IH_day> m_data;\r\n\tIH_day m_currentDay;\r\n\r\n\tQMap<QString, QSet<QString>> m_itemsPresent;\r\n\r\n\tbool m_startUp = true;\r\n};\r\n"
  },
  {
    "path": "src/game/job.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"job.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n\r\n#include <QDebug>\r\n\r\nJob::Job()\r\n{\r\n\tm_id = GameState::createID();\r\n}\r\n\r\nJob::Job( QVariantMap in )\r\n{\r\n\tm_id            = in.value( \"ID\" ).toUInt();\r\n\tm_type          = in.value( \"Type\" ).toString();\r\n\tm_requiredSkill = in.value( \"RequiredSkill\" ).toString();\r\n\tm_description   = in.value( \"Description\" ).toString();\r\n\tm_rotation      = in.value( \"Rotation\" ).value<quint8>();\r\n\tm_noJobSprite   = in.value( \"NoJobSprite\" ).toBool();\r\n\tm_priority      = in.value( \"Priority\" ).value<quint8>();\r\n\r\n\tm_canceled         = in.value( \"Canceled\" ).toBool();\r\n\tm_aborted          = in.value( \"Aborted\" ).toBool();\r\n\tm_componentMissing = in.value( \"ComponentMissing\" ).toBool();\r\n\tm_mayTrap          = in.value( \"MayTrap\" ).toBool();\r\n\tm_destroyOnAbort   = in.value( \"DestroyOnAbort\" ).toBool();\r\n\r\n\tm_jobIsWorked = in.value( \"JobIsWorked\" ).toBool();\r\n\tm_workedBy    = in.value( \"JobWorkedBy\" ).toUInt();\r\n\r\n\tm_requiredTool.type  = in.value( \"RequiredTool\" ).toString();\r\n\tm_requiredTool.level = in.value( \"RequiredToolLevel\" ).toInt();\r\n\r\n\tauto ril = in.value( \"RequiredItems\" ).toList();\r\n\tfor ( auto vri : ril )\r\n\t{\r\n\t\tauto rim = vri.toMap();\r\n\t\tRequiredItem ri;\r\n\t\tri.count               = rim.value( \"Count\" ).toInt();\r\n\t\tri.itemSID             = rim.value( \"ItemSID\" ).toString();\r\n\t\tri.materialSID         = rim.value( \"MaterialSID\" ).toString();\r\n\t\tri.materialRestriction = rim.value( \"MaterialRestriction\" ).toStringList();\r\n\t\tri.requireSame         = rim.value( \"RequireSame\" ).toBool();\r\n\t\tm_requiredItems.append( ri );\r\n\t}\r\n\r\n\tm_position              = in.value( \"Position\" );\r\n\tm_posItemInput          = in.value( \"PositionItemInput\" );\r\n\tm_posItemOutput         = in.value( \"PositionItemOutput\" );\r\n\tm_toolPosition          = in.value( \"ToolPosition\" );\r\n\tm_workPosition          = in.value( \"WorkPosition\" );\r\n\tm_possibleWorkPositions = Global::util->variantList2Position( in.value( \"PossibleWorkPositions\" ).toList() );\r\n\tm_origWorkPosOffsets    = Global::util->variantList2Position( in.value( \"OriginalWorkPositions\" ).toList() );\r\n\r\n\tm_amount             = in.value( \"Amount\" ).toInt();\r\n\tm_item               = in.value( \"Item\" ).toString();\r\n\tm_material           = in.value( \"Material\" ).toString();\r\n\tm_craftID            = in.value( \"CraftID\" ).toString();\r\n\tm_craftJobID            = in.value( \"CraftJobID\" ).toUInt();\r\n\tm_craft              = in.value( \"CraftMap\" ).toMap();\r\n\tm_conversionMaterial = in.value( \"ConversionMaterial\" ).toString();\r\n\r\n\tm_stockpile = in.value( \"Stockpile\" ).toUInt();\r\n\tm_animal    = in.value( \"Animal\" ).toUInt();\r\n\tm_automaton = in.value( \"Automaton\" ).toUInt();\r\n\tm_mechanism = in.value( \"Mechanism\" ).toUInt();\r\n\r\n\tm_itemsToHaul = Global::util->variantList2UInt( in.value( \"ItemsToHaul\" ).toList() );\r\n\tm_spell       = in.value( \"Spell\" ).toString();\r\n}\r\n\r\nQVariant Job::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"ID\", m_id );\r\n\tout.insert( \"Type\", m_type );\r\n\tout.insert( \"RequiredSkill\", m_requiredSkill );\r\n\tout.insert( \"Description\", m_description );\r\n\tout.insert( \"Rotation\", m_rotation );\r\n\tout.insert( \"NoJobSprite\", m_noJobSprite );\r\n\tout.insert( \"Priority\", m_priority );\r\n\r\n\tout.insert( \"Canceled\", m_canceled );\r\n\tout.insert( \"Aborted\", m_aborted );\r\n\tout.insert( \"ComponentMissing\", m_componentMissing );\r\n\tout.insert( \"MayTrap\", m_mayTrap );\r\n\tout.insert( \"DestroyOnAbort\", m_destroyOnAbort );\r\n\r\n\tout.insert( \"JobIsWorked\", m_jobIsWorked );\r\n\tout.insert( \"JobWorkedBy\", m_workedBy );\r\n\r\n\tout.insert( \"RequiredTool\", m_requiredTool.type );       // QString tool\r\n\tout.insert( \"RequiredToolLevel\", m_requiredTool.level ); // int level\r\n\r\n\tQVariantList ril;\r\n\tfor ( const auto& ri : m_requiredItems )\r\n\t{\r\n\t\tQVariantMap rim;\r\n\t\trim.insert( \"Count\", ri.count );\r\n\t\trim.insert( \"ItemSID\", ri.itemSID );\r\n\t\trim.insert( \"MaterialSID\", ri.materialSID );\r\n\t\trim.insert( \"MaterialRestriction\", ri.materialRestriction );\r\n\t\trim.insert( \"RequireSame\", ri.requireSame );\r\n\t\tril.append( rim );\r\n\t}\r\n\tout.insert( \"RequiredItems\", ril );\r\n\r\n\tout.insert( \"Position\", m_position.toString() );\r\n\tout.insert( \"PositionItemInput\", m_posItemInput.toString() );\r\n\tout.insert( \"PositionItemOutput\", m_posItemOutput.toString() );\r\n\tout.insert( \"ToolPosition\", m_toolPosition.toString() );\r\n\tout.insert( \"WorkPosition\", m_workPosition.toString() );\r\n\tout.insert( \"PossibleWorkPositions\", Global::util->positionList2Variant( m_possibleWorkPositions ) );\r\n\tout.insert( \"OriginalWorkPositions\", Global::util->positionList2Variant( m_origWorkPosOffsets ) );\r\n\r\n\tout.insert( \"Amount\", m_amount );\r\n\tout.insert( \"Item\", m_item );\r\n\tout.insert( \"Material\", m_material );\r\n\tout.insert( \"CraftID\", m_craftID );\r\n\tout.insert( \"CraftJobID\", m_craftJobID );\r\n\tout.insert( \"CraftMap\", m_craft );\r\n\tout.insert( \"ConversionMaterial\", m_conversionMaterial );\r\n\r\n\tout.insert( \"Stockpile\", m_stockpile );\r\n\tout.insert( \"Automaton\", m_automaton );\r\n\tout.insert( \"Mechanism\", m_mechanism );\r\n\tout.insert( \"Animal\", m_animal );\r\n\r\n\tout.insert( \"ItemsToHaul\", Global::util->uintList2Variant( m_itemsToHaul ) );\r\n\tout.insert( \"Spell\", m_spell );\r\n\r\n\treturn out;\r\n}\r\n\r\n/*\r\nJob::Job( const Job& other )\r\n{\r\n\tm_id            = other.m_id;\r\n\tm_type          = other.m_type;\r\n\tm_requiredSkill = other.m_requiredSkill;\r\n\tm_description   = other.m_description;\r\n\tm_rotation      = other.m_rotation;\r\n\tm_noJobSprite   = other.m_noJobSprite;\r\n\tm_priority      = other.m_priority;\r\n\r\n\tm_canceled         = other.m_canceled;\r\n\tm_aborted          = other.m_aborted;\r\n\tm_componentMissing = other.m_componentMissing;\r\n\tm_mayTrap          = other.m_mayTrap;\r\n\tm_destroyOnAbort   = other.m_destroyOnAbort;\r\n\r\n\tm_jobIsWorked = other.m_jobIsWorked;\r\n\tm_workedBy    = other.m_workedBy;\r\n\r\n\tm_requiredTool  = other.m_requiredTool;\r\n\tm_requiredItems = other.m_requiredItems;\r\n\r\n\tm_position              = other.m_position;\r\n\tm_posItemInput          = other.m_posItemInput;\r\n\tm_posItemOutput         = other.m_posItemOutput;\r\n\tm_toolPosition          = other.m_toolPosition;\r\n\tm_workPosition          = other.m_workPosition;\r\n\tm_possibleWorkPositions = other.m_possibleWorkPositions;\r\n\tm_origWorkPosOffsets    = other.m_origWorkPosOffsets;\r\n\r\n\tm_amount             = other.m_amount;\r\n\tm_item               = other.m_item;\r\n\tm_material           = other.m_material;\r\n\tm_craftID            = other.m_craftID;\r\n\tm_craft              = other.m_craft;\r\n\tm_conversionMaterial = other.m_conversionMaterial;\r\n\r\n\tm_stockpile = other.m_stockpile;\r\n\tm_animal    = other.m_animal;\r\n\tm_automaton = other.m_automaton;\r\n\r\n\tm_itemsToHaul = other.m_itemsToHaul;\r\n\tm_spell       = other.m_spell;\r\n}\r\n*/\r\n\r\nJob::~Job()\r\n{\r\n}\r\n\r\nunsigned int Job::id() const\r\n{\r\n\treturn m_id;\r\n}\r\n\r\nQString Job::type() const\r\n{\r\n\treturn m_type;\r\n}\r\nvoid Job::setType( QString type )\r\n{\r\n\tm_type = type;\r\n}\r\n\r\nQString Job::requiredSkill() const\r\n{\r\n\treturn m_requiredSkill;\r\n}\r\nvoid Job::setRequiredSkill( QString skill )\r\n{\r\n\tm_requiredSkill = skill;\r\n}\r\n\r\nvoid Job::setDescription( QString desc )\r\n{\r\n\tm_description = desc;\r\n}\r\nQString Job::description() const\r\n{\r\n\treturn m_description;\r\n}\r\n\r\nPosition Job::pos() const\r\n{\r\n\treturn m_position;\r\n}\r\nvoid Job::setPos( const Position& pos )\r\n{\r\n\tm_position = pos;\r\n}\r\n\r\nPosition Job::posItemInput() const\r\n{\r\n\treturn m_posItemInput;\r\n}\r\nvoid Job::setPosItemInput( const Position& pos )\r\n{\r\n\tm_posItemInput = pos;\r\n}\r\n\r\nPosition Job::posItemOutput() const\r\n{\r\n\treturn m_posItemOutput;\r\n}\r\nvoid Job::setPosItemOutput( const Position& pos )\r\n{\r\n\tm_posItemOutput = pos;\r\n}\r\n\r\nPosition Job::toolPosition() const\r\n{\r\n\treturn m_toolPosition;\r\n}\r\nvoid Job::setToolPosition( const Position& pos )\r\n{\r\n\tm_toolPosition = pos;\r\n}\r\n\r\nPosition Job::workPos() const\r\n{\r\n\treturn m_workPosition;\r\n}\r\nvoid Job::setWorkPos( const Position& pos )\r\n{\r\n\tm_workPosition = pos;\r\n}\r\n\r\nQList<Position> Job::possibleWorkPositions()\r\n{\r\n\treturn m_possibleWorkPositions;\r\n}\r\n\r\nvoid Job::addPossibleWorkPosition( const Position& wp )\r\n{\r\n\tm_possibleWorkPositions.append( wp );\r\n}\r\nvoid Job::clearPossibleWorkPositions()\r\n{\r\n\tm_possibleWorkPositions.clear();\r\n}\r\n\r\nQList<Position> Job::origWorkPosOffsets()\r\n{\r\n\treturn m_origWorkPosOffsets;\r\n}\r\n\r\nvoid Job::setOrigWorkPosOffsets( QString offsets )\r\n{\r\n\tauto wps = offsets.split( \"|\" );\r\n\tfor ( auto wp : wps )\r\n\t{\r\n\t\tm_origWorkPosOffsets.append( Position( wp ) );\r\n\t}\r\n}\r\n\r\nvoid Job::setOrigWorkPosOffsets( QList<Position> pl )\r\n{\r\n\tm_origWorkPosOffsets = pl;\r\n}\r\n\r\n\r\nbool Job::isWorked() const\r\n{\r\n\treturn m_jobIsWorked;\r\n}\r\nvoid Job::setIsWorked( bool v )\r\n{\r\n\tm_jobIsWorked = v;\r\n}\r\n\r\nunsigned char Job::rotation() const\r\n{\r\n\treturn m_rotation;\r\n}\r\nvoid Job::setRotation( unsigned char rot )\r\n{\r\n\tm_rotation = rot;\r\n}\r\n\r\nQList<unsigned int> Job::itemsToHaul() const\r\n{\r\n\treturn m_itemsToHaul;\r\n}\r\n\r\nvoid Job::addItemToHaul( unsigned int item )\r\n{\r\n\tm_itemsToHaul.append( item );\r\n}\r\n\r\nQString Job::item() const\r\n{\r\n\treturn m_item;\r\n}\r\nvoid Job::setItem( QString item )\r\n{\r\n\tm_item = item;\r\n}\r\n\r\nunsigned int Job::stockpile() const\r\n{\r\n\treturn m_stockpile;\r\n}\r\nvoid Job::setStockpile( unsigned int sp )\r\n{\r\n\tm_stockpile = sp;\r\n}\r\n\r\nint Job::distanceSquare( Position& pos, int zWeight ) const\r\n{\r\n\treturn pos.distSquare( pos, zWeight );\r\n}\r\n\r\nQString Job::material() const\r\n{\r\n\treturn m_material;\r\n}\r\nvoid Job::setMaterial( QString material )\r\n{\r\n\tm_material = material;\r\n}\r\n\r\nbool Job::noJobSprite() const\r\n{\r\n\treturn m_noJobSprite;\r\n}\r\nvoid Job::setNoJobSprite( bool v )\r\n{\r\n\tm_noJobSprite = v;\r\n}\r\n\r\nvoid Job::setComponentMissing( bool v )\r\n{\r\n\tm_componentMissing = v;\r\n}\r\nbool Job::componentMissing() const\r\n{\r\n\treturn m_componentMissing;\r\n}\r\n\r\nQList<RequiredItem> Job::requiredItems() const\r\n{\r\n\treturn m_requiredItems;\r\n}\r\n\r\nvoid Job::addRequiredItem( int count, QString item, QString material, QStringList materialRestriction, bool requireSame )\r\n{\r\n\tRequiredItem ri;\r\n\r\n\tri.count               = count;\r\n\tri.itemSID             = item;\r\n\tri.materialSID         = material;\r\n\tri.materialRestriction = materialRestriction;\r\n\tri.requireSame         = requireSame;\r\n\r\n\tm_requiredItems.append( ri );\r\n}\r\n\r\nQVariantMap Job::craft() const\r\n{\r\n\treturn m_craft;\r\n}\r\n\r\nvoid Job::setCraft( QVariantMap craft )\r\n{\r\n\tm_craft = craft;\r\n}\r\n\r\nvoid Job::setCanceled()\r\n{\r\n\tm_canceled = true;\r\n}\r\n\r\nbool Job::isCanceled() const\r\n{\r\n\treturn m_canceled;\r\n}\r\n\r\nvoid Job::setAborted( bool v )\r\n{\r\n\tm_aborted = v;\r\n}\r\n\r\nbool Job::isAborted() const\r\n{\r\n\treturn m_aborted;\r\n}\r\n\r\nvoid Job::setWorkedBy( unsigned int gnomeID )\r\n{\r\n\tm_workedBy = gnomeID;\r\n}\r\n\r\nunsigned int Job::workedBy() const\r\n{\r\n\treturn m_workedBy;\r\n}\r\n\r\nRequiredTool Job::requiredTool() const\r\n{\r\n\treturn m_requiredTool;\r\n}\r\n\r\nvoid Job::setRequiredTool( QString toolID, quint8 level )\r\n{\r\n\tm_requiredTool.type  = toolID;\r\n\tm_requiredTool.level = level;\r\n\r\n\tif ( toolID.isEmpty() )\r\n\t{\r\n\t\tm_requiredTool.available = true;\r\n\t}\r\n}\r\n\r\nvoid Job::setRequiredToolAvailable( bool avail )\r\n{\r\n\tm_requiredTool.available = avail;\r\n}\r\n\r\nvoid Job::setConversionMaterial( QString material )\r\n{\r\n\tm_conversionMaterial = material;\r\n}\r\n\r\nQString Job::conversionMaterial() const\r\n{\r\n\treturn m_conversionMaterial;\r\n}\r\n\r\nvoid Job::setAmount( int amount )\r\n{\r\n\tm_amount = amount;\r\n}\r\n\r\nint Job::amount() const\r\n{\r\n\treturn m_amount;\r\n}\r\n\r\nunsigned int Job::animal() const\r\n{\r\n\treturn m_animal;\r\n}\r\n\r\nvoid Job::setAnimal( unsigned int animal )\r\n{\r\n\tm_animal = animal;\r\n}\r\n\r\nunsigned int Job::automaton() const\r\n{\r\n\treturn m_automaton;\r\n}\r\n\r\nvoid Job::setAutomaton( unsigned int automaton )\r\n{\r\n\tm_automaton = automaton;\r\n}\r\n\r\nunsigned int Job::mechanism() const\r\n{\r\n\treturn m_mechanism;\r\n}\r\n\r\nvoid Job::setMechanism( unsigned int mechanism )\r\n{\r\n\tm_mechanism = mechanism;\r\n}\r\n\r\nvoid Job::setSpell( QString spell )\r\n{\r\n\tm_spell = spell;\r\n}\r\n\r\nQString Job::spell() const\r\n{\r\n\treturn m_spell;\r\n}\r\n\r\nvoid Job::setMayTrap( bool value )\r\n{\r\n\tm_mayTrap = value;\r\n}\r\n\r\nbool Job::mayTrap() const\r\n{\r\n\treturn m_mayTrap;\r\n}\r\n\r\nvoid Job::raisePrio()\r\n{\r\n\tm_priority = qMin( 9, m_priority + 1 );\r\n}\r\n\r\nvoid Job::lowerPrio()\r\n{\r\n\tm_priority = qMax( 0, m_priority - 1 );\r\n}\r\n\r\nint Job::priority() const\r\n{\r\n\treturn m_priority;\r\n}\r\n\r\nvoid Job::setCraftID( QString craftID )\r\n{\r\n\tm_craftID = craftID;\r\n}\r\n\r\nQString Job::craftID() const\r\n{\r\n\treturn m_craftID;\r\n}\r\n\r\nvoid Job::setCraftJobID( unsigned int craftJobID )\r\n{\r\n\tm_craftJobID = craftJobID;\r\n}\r\n\t\r\nunsigned int Job::craftJobID() const\r\n{\r\n\treturn m_craftJobID;\r\n}\r\n\r\nvoid Job::setDestroyOnAbort( bool value )\r\n{\r\n\tm_destroyOnAbort = value;\r\n}\r\n\r\nbool Job::destroyOnAbort() const\r\n{\r\n\treturn m_destroyOnAbort;\r\n}\r\n\r\nvoid Job::setPrio( int prio )\r\n{\r\n\tm_priority = qMin( 9, qMax( 0, prio ) );\r\n}"
  },
  {
    "path": "src/game/job.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QList>\r\n#include <QString>\r\n#include <QVariant>\r\n#include <QVariantList>\r\n#include <QVariantMap>\r\n\r\nstruct Position;\r\n\r\nstruct RequiredItem\r\n{\r\n\tint count = 0;\r\n\tQString itemSID;\r\n\tQString materialSID;\r\n\tQStringList materialRestriction;\r\n\tbool requireSame = false;\r\n\r\n\t// only reset when 'requiredItemsExist()' is called\r\n\t// only used for GUI info display\r\n\tbool available = false;\r\n};\r\n\r\nstruct RequiredTool\r\n{\r\n\tQString type;\r\n\tquint8 level = 0;\r\n\r\n\t// only used for GUI info display\r\n\tbool available = false;\r\n};\r\n\r\nclass Job\r\n{\r\n\tQ_DISABLE_COPY_MOVE( Job )\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tQString m_type;\r\n\tQString m_requiredSkill;\r\n\tQString m_description;\r\n\tquint8 m_rotation  = 0;\r\n\tbool m_noJobSprite = false;\r\n\tquint8 m_priority  = 0;\r\n\r\n\tbool m_canceled = false;\r\n\tbool m_aborted  = false;\r\n\t// is used in various places to reset job status\r\n\tbool m_componentMissing = false;\r\n\tbool m_mayTrap          = false;\r\n\tbool m_destroyOnAbort   = false;\r\n\r\n\tbool m_jobIsWorked      = false;\r\n\tunsigned int m_workedBy = 0;\r\n\r\n\tRequiredTool m_requiredTool;\r\n\tQList<RequiredItem> m_requiredItems;\r\n\r\n\tPosition m_position;\r\n\tPosition m_posItemInput;\r\n\tPosition m_posItemOutput;\r\n\tPosition m_toolPosition;\r\n\tPosition m_workPosition;\r\n\tQList<Position> m_possibleWorkPositions;\r\n\tQList<Position> m_origWorkPosOffsets;\r\n\r\n\tint m_amount = 1;\r\n\tQString m_item;\r\n\tQString m_material;\r\n\tQString m_craftID;\r\n\tQVariantMap m_craft;\r\n\tQString m_conversionMaterial;\r\n\tunsigned int m_craftJobID = 0;\r\n\r\n\tunsigned int m_stockpile = 0;\r\n\tunsigned int m_animal    = 0;\r\n\tunsigned int m_automaton = 0;\r\n\tunsigned int m_mechanism = 0;\r\n\r\n\tQList<unsigned int> m_itemsToHaul;\r\n\tQString m_spell;\r\n\r\npublic:\r\n\tJob();\r\n\tJob( QVariantMap in );\r\n\r\n\t//Job( const Job& other );\r\n\r\n\t~Job();\r\n\r\n\tQVariant serialize() const;\r\n\r\n\tunsigned int id() const;\r\n\r\n\tQString type() const;\r\n\tvoid setType( QString type );\r\n\r\n\tQString requiredSkill() const;\r\n\tvoid setRequiredSkill( QString skill );\r\n\r\n\tvoid setDescription( QString desc );\r\n\tQString description() const;\r\n\r\n\t// position of the tile being worked\r\n\tPosition pos() const;\r\n\tvoid setPos( const Position& pos );\r\n\r\n\tPosition posItemInput() const;\r\n\tvoid setPosItemInput( const Position& pos );\r\n\r\n\tPosition posItemOutput() const;\r\n\tvoid setPosItemOutput( const Position& pos );\r\n\r\n\tPosition toolPosition() const;\r\n\tvoid setToolPosition( const Position& pos );\r\n\r\n\tQList<Position> possibleWorkPositions();\r\n\tvoid addPossibleWorkPosition( const Position& stage );\r\n\r\n\tPosition workPos() const;\r\n\tvoid setWorkPos( const Position& pos );\r\n\r\n\tvoid clearPossibleWorkPositions();\r\n\r\n\tQList<Position> origWorkPosOffsets();\r\n\tvoid setOrigWorkPosOffsets( QString offsets );\r\n\tvoid setOrigWorkPosOffsets( QList<Position> );\r\n\r\n\tbool isWorked() const;\r\n\tvoid setIsWorked( bool v );\r\n\r\n\tunsigned char rotation() const;\r\n\tvoid setRotation( unsigned char rot );\r\n\r\n\tQList<unsigned int> itemsToHaul() const;\r\n\tvoid addItemToHaul( unsigned int );\r\n\r\n\tQString item() const;\r\n\tvoid setItem( QString item );\r\n\r\n\tunsigned int stockpile() const;\r\n\tvoid setStockpile( unsigned int sp );\r\n\r\n\tunsigned int animal() const;\r\n\tvoid setAnimal( unsigned int animal );\r\n\r\n\tunsigned int automaton() const;\r\n\tvoid setAutomaton( unsigned int automaton );\r\n\r\n\tunsigned int mechanism() const;\r\n\tvoid setMechanism( unsigned int animal );\r\n\r\n\tQString material() const;\r\n\tvoid setMaterial( QString material );\r\n\r\n\tvoid setComponentMissing( bool v );\r\n\tbool componentMissing() const;\r\n\r\n\tQList<RequiredItem> requiredItems() const;\r\n\tvoid addRequiredItem( int count, QString item, QString material, QStringList materialRestriction, bool requireSame = false );\r\n\r\n\tint distanceSquare( Position& pos, int zWeight = 1 ) const;\r\n\r\n\tbool noJobSprite() const;\r\n\tvoid setNoJobSprite( bool v );\r\n\r\n\tQVariantMap craft() const;\r\n\tvoid setCraft( QVariantMap craft );\r\n\r\n\tvoid setCanceled();\r\n\tbool isCanceled() const;\r\n\r\n\tvoid setAborted( bool v );\r\n\tbool isAborted() const;\r\n\r\n\tvoid setWorkedBy( unsigned int gnomeID );\r\n\tunsigned int workedBy() const;\r\n\r\n\tRequiredTool requiredTool() const;\r\n\tvoid setRequiredTool( QString toolID, quint8 level );\r\n\tvoid setRequiredToolAvailable( bool avail );\r\n\r\n\tvoid setConversionMaterial( QString material );\r\n\tQString conversionMaterial() const;\r\n\r\n\tvoid setAmount( int amount );\r\n\tint amount() const;\r\n\r\n\tvoid setSpell( QString spell );\r\n\tQString spell() const;\r\n\r\n\tvoid setMayTrap( bool value );\r\n\tbool mayTrap() const;\r\n\r\n\tvoid setDestroyOnAbort( bool value );\r\n\tbool destroyOnAbort() const;\r\n\r\n\tvoid setCraftID( QString craftID );\r\n\tQString craftID() const;\r\n\r\n\tvoid setCraftJobID( unsigned int craftJobID );\r\n\tunsigned int craftJobID() const;\r\n\r\n\tvoid raisePrio();\r\n\tvoid lowerPrio();\r\n\tint priority() const;\r\n\tvoid setPrio( int prio );\r\n};\r\n"
  },
  {
    "path": "src/game/jobmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"jobmanager.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/enums.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QVariantMap>\r\n\r\nJobManager::JobManager( Game* parent ) :\r\n\tm_startIndex( 0 ),\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tfor ( auto job : DB::jobIds() )\r\n\t{\r\n\t\tm_jobsPerType.insert( job, QMultiHash<int, unsigned int>() );\r\n\t}\r\n\r\n\tm_skillToInt.insert( \"Mining\", SK_Mining );\r\n\tm_skillToInt.insert( \"Masonry\", SK_Masonry );\r\n\tm_skillToInt.insert( \"Stonecarving\", SK_Stonecarving );\r\n\tm_skillToInt.insert( \"Woodcutting\", SK_Woodcutting );\r\n\tm_skillToInt.insert( \"Carpentry\", SK_Carpentry );\r\n\tm_skillToInt.insert( \"Woodcarving\", SK_Woodcarving );\r\n\tm_skillToInt.insert( \"Smelting\", SK_Smelting );\r\n\tm_skillToInt.insert( \"Blacksmithing\", SK_Blacksmithing );\r\n\tm_skillToInt.insert( \"Metalworking\", SK_Metalworking );\r\n\tm_skillToInt.insert( \"WeaponCrafting\", SK_WeaponCrafting );\r\n\tm_skillToInt.insert( \"ArmorCrafting\", SK_ArmorCrafting );\r\n\tm_skillToInt.insert( \"Gemcutting\", SK_Gemcutting );\r\n\tm_skillToInt.insert( \"JewelryMaking\", SK_JewelryMaking );\r\n\tm_skillToInt.insert( \"Weaving\", SK_Weaving );\r\n\tm_skillToInt.insert( \"Tailoring\", SK_Tailoring );\r\n\tm_skillToInt.insert( \"Dyeing\", SK_Dyeing );\r\n\tm_skillToInt.insert( \"Pottery\", SK_Pottery );\r\n\tm_skillToInt.insert( \"Leatherworking\", SK_Leatherworking );\r\n\tm_skillToInt.insert( \"Bonecarving\", SK_Bonecarving );\r\n\tm_skillToInt.insert( \"Prospecting\", SK_Prospecting );\r\n\tm_skillToInt.insert( \"Tinkering\", SK_Tinkering );\r\n\tm_skillToInt.insert( \"Machining\", SK_Machining );\r\n\tm_skillToInt.insert( \"Engineering\", SK_Engineering );\r\n\tm_skillToInt.insert( \"Mechanic\", SK_Mechanic );\r\n\tm_skillToInt.insert( \"AnimalHusbandry\", SK_AnimalHusbandry );\r\n\tm_skillToInt.insert( \"Butchery\", SK_Butchery );\r\n\tm_skillToInt.insert( \"Fishing\", SK_Fishing );\r\n\tm_skillToInt.insert( \"Horticulture\", SK_Horticulture );\r\n\tm_skillToInt.insert( \"Farming\", SK_Farming );\r\n\tm_skillToInt.insert( \"Cooking\", SK_Cooking );\r\n\tm_skillToInt.insert( \"Brewing\", SK_Brewing );\r\n\tm_skillToInt.insert( \"Construction\", SK_Construction );\r\n\tm_skillToInt.insert( \"Hauling\", SK_Hauling );\r\n\tm_skillToInt.insert( \"Unarmed\", SK_Unarmed );\r\n\tm_skillToInt.insert( \"Melee\", SK_Melee );\r\n\tm_skillToInt.insert( \"Ranged\", SK_Ranged );\r\n\tm_skillToInt.insert( \"Thrown\", SK_Thrown );\r\n\tm_skillToInt.insert( \"Dodge\", SK_Dodge );\r\n\tm_skillToInt.insert( \"Block\", SK_Block );\r\n\tm_skillToInt.insert( \"Armor\", SK_Armor );\r\n\tm_skillToInt.insert( \"Crossbow\", SK_Crossbow );\r\n\tm_skillToInt.insert( \"Gun\", SK_Gun );\r\n\tm_skillToInt.insert( \"Medic\", SK_Medic );\r\n\tm_skillToInt.insert( \"Caretaking\", SK_Caretaking );\r\n\tm_skillToInt.insert( \"MagicNature\", SK_MagicNature );\r\n\tm_skillToInt.insert( \"MagicGeomancy\", SK_MagicGeomancy );\r\n\r\n\tfor ( auto skillID : DB::ids( \"Skills\" ) )\r\n\t{\r\n\t\tQStringList jobs;\r\n\t\tfor( auto jobID : DB::jobIds() )\r\n\t\t{\r\n\t\t\tauto dbjob = DB::job( jobID );\r\n\t\t\tif( dbjob->SkillID == skillID )\r\n\t\t\t{\r\n\t\t\t\tjobs.append( jobID );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_jobIDs.insert( skillID, jobs );\r\n\t}\r\n\r\n\tauto skillList = DB::execQuery2( \"SELECT DISTINCT \\\"SkillID\\\" FROM Crafts\" );\r\n\tfor( auto skill : skillList )\r\n\t{\r\n\t\tm_workshopSkills.insert( skill.toString() );\r\n\t}\r\n}\r\n\r\nJobManager::~JobManager()\r\n{\r\n\tm_jobList.clear();\r\n}\r\n\r\nvoid JobManager::onTick()\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\tunsigned int jobID = 0;\r\n\r\n\tint queueSize = m_returnedJobQueue.size();\r\n\r\n\tQQueue<unsigned int> skippedJobs;\r\n\r\n\twhile ( !m_returnedJobQueue.empty() )\r\n\t{\r\n\t\tjobID = m_returnedJobQueue.dequeue();\r\n\t\t--queueSize;\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\r\n\t\tif( job )\r\n\t\t{\r\n\t\t\tif ( workPositionWalkable( job->id() ) && requiredToolExists( job->id() ) )\r\n\t\t\t{\r\n\t\t\t\tif ( requiredItemsAvail( jobID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_jobsPerType[job->type()].insert( job->priority(), job->id() );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tskippedJobs.enqueue( jobID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tskippedJobs.enqueue( jobID );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( timer.elapsed() > 3 )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tm_returnedJobQueue += skippedJobs;\r\n}\r\n\r\n// In order to cache the missing required items we iterate over all every time\r\n// which prevents us from breaking the loop ASAP.\r\n// Not sure if another approach would work better and still allow GUI to access\r\n// information without querying the game state\r\nbool JobManager::requiredItemsAvail( unsigned int jobID )\r\n{\r\n\tQSharedPointer<Job> job       = m_jobList.value( jobID );\r\n\tbool found_all = true;\r\n\tfor ( auto rim : job->requiredItems() )\r\n\t{\r\n\t\tbool found = false;\r\n\t\tfor ( auto pos : job->possibleWorkPositions() )\r\n\t\t{\r\n\t\t\tif ( g->inv()->checkReachableItems( pos, true, rim.count, rim.itemSID, rim.materialSID ) )\r\n\t\t\t{\r\n\t\t\t\tfound         = true;\r\n\t\t\t\trim.available = 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{\r\n\t\t\tfound_all     = false;\r\n\t\t\trim.available = false;\r\n\r\n\t\t\t//is item craftable?\r\n\t\t\tif ( Global::craftable.contains( rim.itemSID ) )\r\n\t\t\t{\r\n\t\t\t\t// create craft job\r\n\t\t\t\tg->wsm()->autoGenCraftJob( rim.itemSID, rim.materialSID, rim.count );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn found_all;\r\n}\r\n\r\nbool JobManager::workPositionWalkable( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job     = m_jobList.value( jobID );\r\n\t\tPosition pos = job->pos();\r\n\r\n\t\tjob->clearPossibleWorkPositions();\r\n\t\t// jobs on same tile\r\n\t\tauto wpl = job->origWorkPosOffsets();\r\n\t\tfor ( const auto& offset : wpl )\r\n\t\t{\r\n\t\t\tPosition testPos( pos + offset );\r\n\t\t\tif ( g->w()->isWalkableGnome( testPos ) )\r\n\t\t\t{\r\n\t\t\t\tjob->addPossibleWorkPosition( testPos );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn job->possibleWorkPositions().size() > 0;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool JobManager::requiredToolExists( unsigned int jobID )\r\n{\r\n\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\tauto rt  = job->requiredTool();\r\n\r\n\t// need to figure out how to check rt 'inuse' & 'reachable'\r\n\tjob->setRequiredToolAvailable( true );\r\n\r\n\tif ( rt.type.isEmpty() )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\r\n\tQMap<QString, int> mc = g->inv()->materialCountsForItem( rt.type, false );\r\n\tQStringList keys      = mc.keys();\r\n\r\n\tfor ( auto key : keys )\r\n\t{\r\n\t\tif ( mc[key] > 0 )\r\n\t\t{\r\n\t\t\tif ( rt.level == 0 )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\tint tl = DBH::materialToolLevel( key );\r\n\t\t\tif ( tl >= rt.level )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tjob->setRequiredToolAvailable( false );\r\n\treturn false;\r\n}\r\n\r\nbool JobManager::insertIntoPositionHash( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\t\tif ( m_jobPositions.contains( job->pos() ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_jobPositions.insert( job->pos(), job->id() );\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nvoid JobManager::removeFromPositionHash( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\t\tif ( m_jobPositions.contains( job->pos() ) )\r\n\t\t{\r\n\t\t\tm_jobPositions.remove( job->pos() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid JobManager::addLoadedJob( QVariant vals )\r\n{\r\n\tQSharedPointer<Job> job( new Job( vals.toMap() ) );\r\n\r\n\tm_jobList.insert( job->id(), job );\r\n\r\n\tif ( !insertIntoPositionHash( job->id() ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( isReachable( job->id(), 0 ) )\r\n\t{\r\n\t\tm_jobsPerType[job->type()].insert( job->priority(), job->id() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_returnedJobQueue.enqueue( job->id() );\r\n\t}\r\n\r\n\tsetJobSprites( job->id(), job->isWorked(), false );\r\n}\r\n\r\nunsigned int JobManager::addJob( QString type, Position pos, int rotation, bool noJobSprite )\r\n{\r\n\tif ( g->w()->hasJob( pos ) || m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\tQSharedPointer<Job> job( new Job );\r\n\tjob->setType( type );\r\n\tjob->setPos( pos );\r\n\tjob->setRotation( rotation );\r\n\tjob->setNoJobSprite( noJobSprite );\r\n\t\t\r\n\tjob->setRequiredSkill( Global::util->requiredSkill( type ) );\r\n\tjob->setRequiredTool( Global::util->requiredTool( type ), Global::util->requiredToolLevel( type, pos ) );\r\n\r\n\tauto dbjb = DB::job( type );\r\n\tif( dbjb )\r\n\t{\r\n\t\tjob->setMayTrap( dbjb->MayTrapGnome );\r\n\t\tjob->setOrigWorkPosOffsets( dbjb->WorkPositions );\r\n\t}\r\n\r\n\tm_jobList.insert( job->id(), job );\r\n\r\n\tinsertIntoPositionHash( job->id() );\r\n\r\n\tm_returnedJobQueue.enqueue( job->id() );\r\n\r\n\tsetJobSprites( job->id(), false, false );\r\n\r\n\treturn job->id();\r\n}\r\n\r\nunsigned int JobManager::addJob( QString type, Position pos, QString item, QList<QString> materials, int rotation, bool noJobSprite )\r\n{\r\n\t//qDebug() << \"JobManager::addJob \" << type << item << materials << pos.toString();\r\n\r\n\tif ( m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tQSharedPointer<Job> job( new Job );\r\n\tjob->setType( type );\r\n\tjob->setRequiredSkill( Global::util->requiredSkill( type ) );\r\n\tjob->setPos( pos );\r\n\tjob->setItem( item );\r\n\tjob->setMaterial( materials.first() );\r\n\tjob->setRotation( rotation );\r\n\tjob->setNoJobSprite( noJobSprite );\r\n\tQString constructionID;\r\n\tauto dbjb = DB::job( type );\r\n\tif( dbjb )\r\n\t{\r\n\t\tjob->setOrigWorkPosOffsets( dbjb->WorkPositions );\r\n\t\tconstructionID = dbjb->ConstructionType; \r\n\t}\r\n\r\n\tif ( !constructionID.isEmpty() )\r\n\t{\r\n\t\tQList<QVariantMap> components;\r\n\t\tif ( constructionID == \"Workshop\" )\r\n\t\t{\r\n\t\t\tcomponents = DB::selectRows( \"Workshops_Components\", \"ID\", item );\r\n\t\t}\r\n\t\telse if ( constructionID == \"Item\" )\r\n\t\t{\r\n\t\t\t// items that exist as different base items before being constructed i.e. VerticleAxle is an Axle\r\n\t\t\tif ( DB::select( \"Type\", \"Constructions\", item ).toString() == \"Item\" )\r\n\t\t\t{\r\n\t\t\t\tcomponents = DB::selectRows( \"Constructions_Components\", \"ID\", item );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tQVariantMap comp;\r\n\t\t\t\tcomp.insert( \"ItemID\", item );\r\n\t\t\t\tcomp.insert( \"Type\", constructionID );\r\n\t\t\t\tcomponents.push_back( comp );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tcomponents = DB::selectRows( \"Constructions_Components\", \"ID\", item );\r\n\t\t}\r\n\r\n\t\tint cID = 0;\r\n\t\tfor ( auto comp : components )\r\n\t\t{\r\n\t\t\tQString itemID = comp.value( \"ItemID\" ).toString();\r\n\t\t\tif ( !itemID.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tint amount = comp.value( \"Amount\" ).toInt();\r\n\t\t\t\tif ( amount == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tamount = 1;\r\n\t\t\t\t}\r\n\t\t\t\t//if( itemID.startsWith( \"$\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// not used right now\r\n\t\t\t\t}\r\n\t\t\t\t//qDebug() << \"require item \" << itemID << materials[cID];\r\n\t\t\t\tint itemCount = g->inv()->itemCount( itemID, materials[cID] );\r\n\t\t\t\tif ( itemCount - amount < 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\t//qDebug() << \"require \" << amount << \" items \" << itemID << materials[cID] << \" there are \" << itemCount << \" in the world\";\r\n\t\t\t\t\tg->wsm()->autoGenCraftJob( itemID, materials[cID], amount - itemCount );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tjob->addRequiredItem( amount, itemID, materials[cID], comp.value( \"MaterialTypes\" ).toStringList() );\r\n\t\t\t\tjob->setComponentMissing( true );\r\n\t\t\t\t++cID;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\telse if ( type == \"PlantTree\" )\r\n\t{\r\n\t\tQVariantMap row = DB::selectRow( \"Plants\", item );\r\n\t\t//qDebug() << row.value(\"SeedItemID\").toString() << row.value(\"Material\").toString();\r\n\t\tjob->addRequiredItem( 1, row.value( \"SeedItemID\" ).toString(), row.value( \"Material\" ).toString(), QStringList() );\r\n\t\tjob->setComponentMissing( true );\r\n\t}\r\n\r\n\tm_jobList.insert( job->id(), job );\r\n\r\n\tinsertIntoPositionHash( job->id() );\r\n\r\n\tm_returnedJobQueue.enqueue( job->id() );\r\n\r\n\tsetJobSprites( job->id(), false, false );\r\n\treturn job->id();\r\n}\r\n\r\nvoid JobManager::setJobAvailable( unsigned int jobID )\r\n{\r\n\tsetJobSprites( jobID, false, false );\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\t\tjob->setIsWorked( false );\r\n\t}\r\n}\r\n\r\nvoid JobManager::setJobBeingWorked( unsigned int jobID, bool hasNeededTool )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\r\n\t\tif ( !job->noJobSprite() )\r\n\t\t{\r\n\t\t\tif ( hasNeededTool )\r\n\t\t\t{\r\n\t\t\t\tsetJobSprites( jobID, true, false );\r\n\t\t\t}\r\n\t\t}\r\n\t\tjob->setIsWorked( true );\r\n\t}\r\n}\r\n\r\nunsigned int JobManager::getJob( QStringList skills, unsigned int gnomeID, Position& gnomePos )\r\n{\r\n\tfor ( auto skillID : skills )\r\n\t{\r\n\t\tunsigned int jobID = 0;\r\n\r\n\t\tint skillInt = m_skillToInt.value( skillID );\r\n\r\n\t\tswitch ( skillInt )\r\n\t\t{\r\n\t\t\tcase SK_Hauling:\r\n\t\t\t{\r\n\t\t\t\tjobID = g->spm()->getJob();\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( jobID )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn jobID;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tQElapsedTimer et;\r\n\t\tet.start();\r\n\r\n\t\tauto possibleJobIDs = m_jobIDs.value( skillID );\r\n\t\tif( m_workshopSkills.contains( skillID ) )\r\n\t\t{\r\n\t\t\tpossibleJobIDs.push_front( \"CraftAtWorkshop\" );\r\n\t\t}\r\n\t\tunsigned int regionID = g->w()->regionMap().regionID( gnomePos );\r\n\t\tfor ( int prio = 9; prio >= 0; --prio )\r\n\t\t{\r\n\t\t\tfor ( auto jobID : possibleJobIDs )\r\n\t\t\t{\r\n\t\t\t\tif ( m_jobsPerType.contains( jobID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tQList<unsigned int> jobs = m_jobsPerType[jobID].values( prio );\r\n\t\t\t\t\tPriorityQueue<unsigned int, int> pq;\r\n\r\n\t\t\t\t\tif ( jobID == \"RemoveFloor\" || jobID == \"BuildWall\" || jobID == \"DigHole\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint walkableNeighbors = 0;\r\n\t\t\t\t\t\tfor ( int i = 0; i < jobs.size(); ++i )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\twalkableNeighbors = g->w()->walkableNeighbors( m_jobList[jobs[i]]->pos() );\r\n\t\t\t\t\t\t\tpq.put( jobs[i], walkableNeighbors );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\twhile ( !pq.empty() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tQSharedPointer<Job> job = m_jobList[pq.get()];\r\n\t\t\t\t\t\t\tif ( !job->isWorked() && !job->isCanceled() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( requiredItemsAvail( job->id() ) && requiredToolExists( job->id() ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( isReachable( job->id(), regionID ) && !isEnclosedBySameType( job->id() ) )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t//qDebug() << \"getJob \" <<  j->id();\r\n\t\t\t\t\t\t\t\t\t\treturn job->id();\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\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tfor ( auto& type : m_jobsPerType )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\ttype.remove( prio, job->id() );\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tm_returnedJobQueue.enqueue( job->id() );\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}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint dist = 0;\r\n\t\t\t\t\t\tfor ( int i = 0; i < jobs.size(); ++i )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( jobID == \"CraftAtWorkshop\" && m_jobList[jobs[i]]->requiredSkill() != skillID )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tdist = m_jobList[jobs[i]]->distanceSquare( gnomePos, 10 );\r\n\r\n\t\t\t\t\t\t\tif ( dist == 1 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tQSharedPointer<Job> job = m_jobList[jobs[i]];\r\n\t\t\t\t\t\t\t\tif ( !job->isWorked() && !job->isCanceled() )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( requiredItemsAvail( job->id() ) && requiredToolExists( job->id() ) )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tif ( isReachable( job->id(), 0 ) )\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\t//qDebug() << \"getJob \" <<  j.id();\r\n\t\t\t\t\t\t\t\t\t\t\treturn job->id();\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tfor ( auto& type : m_jobsPerType )\r\n\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\ttype.remove( prio, job->id() );\r\n\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\tm_returnedJobQueue.enqueue( job->id() );\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\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tpq.put( jobs[i], dist );\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\twhile ( !pq.empty() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tQSharedPointer<Job> job = m_jobList[pq.get()];\r\n\t\t\t\t\t\t\tif ( !job->isWorked() && !job->isCanceled() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( requiredItemsAvail( job->id() ) && requiredToolExists( job->id() ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( isReachable( job->id(), regionID ) )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t//qDebug() << \"getJob \" <<  j->id();\r\n\t\t\t\t\t\t\t\t\t\treturn job->id();\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\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tfor ( auto& type : m_jobsPerType )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\ttype.remove( prio, job->id() );\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tm_returnedJobQueue.enqueue( job->id() );\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}\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\treturn 0;\r\n}\r\n\r\nQSharedPointer<Job> JobManager::getJob( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\treturn m_jobList.value( jobID );\r\n\t}\r\n\tif ( g->spm()->hasJobID( jobID ) )\r\n\t{\r\n\t\treturn g->spm()->getJob( jobID );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQSharedPointer<Job> JobManager::getJobAtPos( Position pos )\r\n{\r\n\tif ( m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\tunsigned jobID = m_jobPositions.value( pos );\r\n\t\treturn m_jobList.value( jobID );\r\n\t}\r\n\r\n\treturn nullptr;\r\n}\r\n\r\nbool JobManager::isEnclosedBySameType( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job     = m_jobList.value( jobID );\r\n\t\tPosition pos = job->pos();\r\n\t\tQString type = job->type();\r\n\t\tif ( m_jobPositions.contains( pos.northOf() ) )\r\n\t\t{\r\n\t\t\tif ( m_jobPositions.contains( pos.southOf() ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_jobPositions.contains( pos.eastOf() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_jobPositions.contains( pos.westOf() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( m_jobList[m_jobPositions[pos.northOf()]]->type() == type )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( m_jobList[m_jobPositions[pos.southOf()]]->type() == type )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( m_jobList[m_jobPositions[pos.eastOf()]]->type() == type )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( m_jobList[m_jobPositions[pos.westOf()]]->type() == type )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\treturn true;\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}\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\treturn false;\r\n}\r\n\r\nbool JobManager::isReachable( unsigned int jobID, unsigned int regionID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job     = m_jobList.value( jobID );\r\n\t\tPosition pos = job->pos();\r\n\t\tjob->clearPossibleWorkPositions();\r\n\t\t// jobs on same tile\r\n\t\tauto wpl = job->origWorkPosOffsets();\r\n\t\t//qDebug() << \"### get staging for \" << pos.toString();\r\n\t\tfor ( const auto& offset : wpl )\r\n\t\t{\r\n\t\t\tPosition testPos( pos + offset );\r\n\t\t\tif ( g->w()->isWalkable( testPos ) )\r\n\t\t\t{\r\n\t\t\t\tif ( regionID == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tjob->addPossibleWorkPosition( testPos );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int workRegionID = g->w()->regionMap().regionID( testPos );\r\n\t\t\t\t\tif ( g->w()->regionMap().checkConnectedRegions( regionID, workRegionID ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob->addPossibleWorkPosition( testPos );\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\t//if ( job.possibleWorkPositions().empty() ) qDebug() << \"not reachable\";\r\n\t\treturn job->possibleWorkPositions().size() > 0;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid JobManager::finishJob( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\r\n\t\tQString type = job->type();\r\n\t\tsetJobSprites( jobID, false, true );\r\n\r\n\t\tstd::vector<Position> neighs;\r\n\t\tPosition pos = job->pos();\r\n\r\n\t\tneighs.push_back( pos.northOf() );\r\n\t\tneighs.push_back( pos.eastOf() );\r\n\t\tneighs.push_back( pos.southOf() );\r\n\t\tneighs.push_back( pos.westOf() );\r\n\t\tneighs.push_back( pos.aboveOf() );\r\n\t\tneighs.push_back( pos.belowOf() );\r\n\r\n\t\tfor ( auto p : neighs )\r\n\t\t{\r\n\t\t\tif ( m_jobPositions.contains( p ) )\r\n\t\t\t{\r\n\t\t\t\tunsigned int j = m_jobPositions.value( p );\r\n\r\n\t\t\t\tif ( isReachable( j, 0 ) && !m_jobList[j]->componentMissing() )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_jobsPerType[m_jobList[j]->type()].insert( m_jobList[j]->priority(), j );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tremoveFromPositionHash( jobID );\r\n\r\n\t\tfor ( auto& mtype : m_jobsPerType )\r\n\t\t{\r\n\t\t\tmtype.remove( job->priority(), jobID );\r\n\t\t}\r\n\t\tm_jobList.remove( jobID );\r\n\t}\r\n\r\n\tif ( g->spm()->finishJob( jobID ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n}\r\n\r\nvoid JobManager::setJobSprites( unsigned int jobID, bool busy, bool remove )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job     = m_jobList.value( jobID );\r\n\t\tif( !job || job->noJobSprite() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tQString type = job->type();\r\n\t\tint rotation = job->rotation();\r\n\t\tQList<QPair<Sprite*, Position>> sprites;\r\n\t\tQList<QPair<Sprite*, Position>> spritesInv;\r\n\r\n\t\tif ( type == \"BuildWall\" || type == \"BuildFloor\" || type == \"BuildRamp\" || type == \"BuildRampCorner\" || type == \"BuildWorkshop\" || type == \"BuildItem\" || type == \"BuildStairs\" )\r\n\t\t{\r\n\t\t\tQList<QVariantMap> components;\r\n\t\t\tif ( type == \"BuildWall\" || type == \"BuildFloor\" || type == \"BuildRamp\" || type == \"BuildRampCorner\" || type == \"BuildStairs\" )\r\n\t\t\t{\r\n\t\t\t\tcomponents = DB::selectRows( \"Constructions_Sprites\", \"ID\", job->item() );\r\n\t\t\t}\r\n\t\t\telse if ( type == \"BuildWorkshop\" )\r\n\t\t\t{\r\n\t\t\t\tcomponents = DB::selectRows( \"Workshops_Components\", \"ID\", job->item() );\r\n\t\t\t}\r\n\t\t\telse if ( type == \"BuildItem\" )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap sprite;\r\n\t\t\t\tsprite.insert( \"SpriteID\", DBH::spriteID( job->item() ) );\r\n\t\t\t\tsprite.insert( \"Offset\", \"0 0 0\" );\r\n\t\t\t\tsprite.insert( \"Type\", \"Item\" );\r\n\t\t\t\tcomponents.push_back( sprite );\r\n\t\t\t}\r\n\t\t\tfor ( auto component : components )\r\n\t\t\t{\r\n\t\t\t\tauto cm = component;\r\n\t\t\t\tPosition offset( cm.value( \"Offset\" ).toString() );\r\n\t\t\t\tint rotX = offset.x;\r\n\t\t\t\tint rotY = offset.y;\r\n\t\t\t\tswitch ( rotation )\r\n\t\t\t\t{\r\n\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\toffset.x = -1 * rotY;\r\n\t\t\t\t\t\toffset.y = rotX;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\toffset.x = -1 * rotX;\r\n\t\t\t\t\t\toffset.y = -1 * rotY;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\toffset.x = rotY;\r\n\t\t\t\t\t\toffset.y = -1 * rotX;\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( !cm.value( \"SpriteID\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString mat = job->material();\r\n\t\t\t\t\tif ( mat == \"any\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmat = \"None\";\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( !cm.value( \"SpriteIDOverride\" ).toString().isEmpty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcm.insert( \"SpriteID\", cm.value( \"SpriteIDOverride\" ).toString() );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tSprite* sprite  = g->sf()->createSprite( cm[\"SpriteID\"].toString(), { mat } );\r\n\t\t\t\t\tsprite->opacity = 0.5;\r\n\r\n\t\t\t\t\tbool isFloor = false;\r\n\t\t\t\t\tif ( cm.contains( \"Type\" ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( cm[\"Type\"].toString() == \"Floor\" || cm[\"Type\"].toString() == \"StairsTop\" )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tisFloor = true;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tunsigned int spriteUID = sprite->uID;\r\n\t\t\t\t\t/*\r\n\t\t\t\t\tif( sprite->anim )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tspriteUID += 2048;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t*/\r\n\t\t\t\t\tif ( isFloor )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( remove )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->w()->clearJobSprite( job->pos() + offset, true );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->w()->setJobSprite( job->pos() + offset, spriteUID, rotation, isFloor, jobID, busy );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQString rots = cm[\"WallRotation\"].toString();\r\n\t\t\t\t\t\tint rot      = 0;\r\n\t\t\t\t\t\tif ( rots == \"FL\" )\r\n\t\t\t\t\t\t\trot = 1;\r\n\t\t\t\t\t\telse if ( rots == \"BL\" )\r\n\t\t\t\t\t\t\trot = 2;\r\n\t\t\t\t\t\telse if ( rots == \"BR\" )\r\n\t\t\t\t\t\t\trot = 3;\r\n\t\t\t\t\t\tif ( remove )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->w()->clearJobSprite( job->pos() + offset, false );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->w()->setJobSprite( job->pos() + offset, spriteUID, ( rotation + rot ) % 4, isFloor, jobID, busy );\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\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tSprite* sprite  = g->sf()->createSprite( \"SolidSelectionFloor\", { \"None\" } );\r\n\t\t\t\t\tsprite->opacity = 0.5;\r\n\t\t\t\t\tif ( remove )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->w()->clearJobSprite( job->pos() + offset, true );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->w()->setJobSprite( job->pos() + offset, sprite->uID, rotation, true, jobID, busy );\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\telse\r\n\t\t{\r\n\r\n\t\t\tQList<QVariantMap> spriteIds = DB::selectRows( \"Jobs_SpriteID\", \"ID\", type );\r\n\r\n\t\t\tif ( !spriteIds.empty() )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& entry : spriteIds )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !entry.value( \"SpriteID\" ).toString().isEmpty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQString spriteID = entry[\"SpriteID\"].toString();\r\n\t\t\t\t\t\tSprite* sprite   = g->sf()->createSprite( spriteID, { \"None\" } );\r\n\t\t\t\t\t\tsprite->opacity  = 0.5;\r\n\t\t\t\t\t\tPosition offset( 0, 0, 0 );\r\n\t\t\t\t\t\tif ( entry.contains( \"Offset\" ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\toffset = Position( entry[\"Offset\"].toString() );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbool floor = false;\r\n\t\t\t\t\t\tif ( entry.contains( \"Type\" ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( entry[\"Type\"].toString() == \"Floor\" )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tfloor = true;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tunsigned int spriteUID = sprite->uID;\r\n\t\t\t\t\t\t/*\r\n\t\t\t\t\t\tif( sprite->anim )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tspriteUID += 2048;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t*/\r\n\t\t\t\t\t\tif ( remove )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->w()->clearJobSprite( job->pos() + offset, floor );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->w()->setJobSprite( job->pos() + offset, spriteUID, rotation, floor, jobID, busy );\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\r\nvoid JobManager::giveBackJob( unsigned int jobID )\r\n{\r\n\tif ( m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\r\n\t\tif ( job->isCanceled() || job->destroyOnAbort() )\r\n\t\t{\r\n\t\t\tjob->setIsWorked( false );\r\n\t\t\tcancelJob( job->pos() );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif( job->type() == \"LeadAnimalToPasture\" || job->type() == \"ButcherAnimal\" || job->type() == \"HarvestAnimal\" )\r\n\t\t{\r\n\t\t\tif( job->animal() == 0 )\r\n\t\t\t{\r\n\t\t\t\tjob->setIsWorked( false );\r\n\t\t\t\tcancelJob( job->pos() );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t//TODO clear stockpile reserve\r\n\t\tjob->setIsWorked( false );\r\n\t\tjob->setWorkedBy( 0 );\r\n\t\tjob->clearPossibleWorkPositions();\r\n\t\tjob->setComponentMissing( true );\r\n\r\n\t\tfor ( auto& type : m_jobsPerType )\r\n\t\t{\r\n\t\t\ttype.remove( job->priority(), jobID );\r\n\t\t}\r\n\t\tsetJobSprites( jobID, false, false );\r\n\r\n\t\tm_returnedJobQueue.enqueue( jobID );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( g->spm()->giveBackJob( jobID ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n}\r\n\r\nvoid JobManager::cancelJob( const Position& pos )\r\n{\r\n\tunsigned int jobID = 0;\r\n\tif ( m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\tjobID = m_jobPositions.value( pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tjobID = g->w()->jobSprite( pos ).value( \"JobID\" ).toUInt();\r\n\t}\r\n\r\n\tif ( jobID != 0 && m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tif ( m_jobList.value( jobID )->isWorked() )\r\n\t\t{\r\n\t\t\tm_jobList.value( jobID )->setCanceled();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\r\n\t\t\tif ( job->type() == \"SoundAlarm\" )\r\n\t\t\t{\r\n\t\t\t\tGameState::alarm       = 0;\r\n\t\t\t\tGameState::alarmRoomID = 0;\r\n\t\t\t}\r\n\r\n\t\t\tsetJobSprites( jobID, false, true );\r\n\r\n\t\t\tremoveFromPositionHash( jobID );\r\n\t\t\tfor ( auto& type : m_jobsPerType )\r\n\t\t\t{\r\n\t\t\t\ttype.remove( job->priority(), jobID );\r\n\t\t\t}\r\n\t\t\tm_jobList.remove( jobID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid JobManager::deleteJob( unsigned int jobID )\r\n{\r\n\tif ( jobID != 0 && m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tif ( m_jobList.value( jobID )->isWorked() )\r\n\t\t{\r\n\t\t\tm_jobList.value( jobID )->setCanceled();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\r\n\t\t\tif ( job->type() == \"SoundAlarm\" )\r\n\t\t\t{\r\n\t\t\t\tGameState::alarm       = 0;\r\n\t\t\t\tGameState::alarmRoomID = 0;\r\n\t\t\t}\r\n\r\n\t\t\tsetJobSprites( jobID, false, true );\r\n\r\n\t\t\tremoveFromPositionHash( jobID );\r\n\t\t\tfor ( auto& type : m_jobsPerType )\r\n\t\t\t{\r\n\t\t\t\ttype.remove( job->priority(), jobID );\r\n\t\t\t}\r\n\t\t\tm_jobList.remove( jobID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid JobManager::deleteJobAt( const Position& pos )\r\n{\r\n\tunsigned int jobID = 0;\r\n\tif ( m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\tjobID = m_jobPositions.value( pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tjobID = g->w()->jobSprite( pos ).value( \"JobID\" ).toUInt();\r\n\t}\r\n\r\n\tif ( jobID != 0 && m_jobList.contains( jobID ) )\r\n\t{\r\n\t\tdeleteJob( jobID );\r\n\t}\r\n}\r\n\r\nQString JobManager::jobManagerInfo()\r\n{\r\n\tQString out;\r\n\r\n\tout += QString::number( m_jobList.size() );\r\n\treturn out;\r\n}\r\n\r\nvoid JobManager::raisePrio( Position& pos )\r\n{\r\n\tunsigned int jobID = 0;\r\n\tif ( m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\tjobID = m_jobPositions.value( pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tjobID = g->w()->jobSprite( pos ).value( \"JobID\" ).toUInt();\r\n\t}\r\n\r\n\tif ( jobID != 0 )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\t\tif ( job->priority() < 9 )\r\n\t\t{\r\n\t\t\tif ( m_jobsPerType[job->type()].count( job->priority(), job->id() ) )\r\n\t\t\t{\r\n\t\t\t\t//job is in m_jobsPerType so move it\r\n\t\t\t\tm_jobsPerType[job->type()].remove( job->priority(), job->id() );\r\n\t\t\t\tm_jobsPerType[job->type()].insert( job->priority() + 1, job->id() );\r\n\t\t\t}\r\n\t\t\tjob->raisePrio();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid JobManager::lowerPrio( Position& pos )\r\n{\r\n\tunsigned int jobID = 0;\r\n\tif ( m_jobPositions.contains( pos ) )\r\n\t{\r\n\t\tjobID = m_jobPositions.value( pos );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tjobID = g->w()->jobSprite( pos ).value( \"JobID\" ).toUInt();\r\n\t}\r\n\r\n\tif ( jobID != 0 )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobList.value( jobID );\r\n\t\tif ( job->priority() > 0 )\r\n\t\t{\r\n\t\t\tif ( m_jobsPerType[job->type()].count( job->priority(), job->id() ) )\r\n\t\t\t{\r\n\t\t\t\t//job is in m_jobsPerType so move it\r\n\t\t\t\tm_jobsPerType[job->type()].remove( job->priority(), job->id() );\r\n\t\t\t\tm_jobsPerType[job->type()].insert( job->priority() - 1, job->id() );\r\n\t\t\t}\r\n\t\t\tjob->lowerPrio();\r\n\t\t}\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/game/jobmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/priorityqueue.h\"\r\n#include \"../game/job.h\"\r\n\r\n#include <QColor>\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QQueue>\r\n#include <QString>\r\n\r\nclass Game;\r\n\r\nclass JobManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( JobManager )\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQHash<unsigned int, QSharedPointer<Job>> m_jobList;\r\n\tQHash<QString, QMultiHash<int, unsigned int>> m_jobsPerType;\r\n\r\n\tQHash<QString, int> m_skillToInt;\r\n\r\n\tQHash<Position, unsigned int> m_jobPositions;\r\n\r\n\tQQueue<unsigned int> m_returnedJobQueue;\r\n\r\n\tQHash<QString, QStringList> m_jobIDs;\r\n\r\n\tQSet<QString> m_workshopSkills;\r\n\r\n\tint m_startIndex;\r\n\r\n\tbool workPositionWalkable( unsigned int jobID );\r\n\tbool isReachable( unsigned int jobID, unsigned int regionID );\r\n\r\n\tbool isEnclosedBySameType( unsigned int jobID );\r\n\r\n\tbool requiredToolExists( unsigned int jobID );\r\n\tbool requiredItemsAvail( unsigned int jobID );\r\n\r\n\tbool insertIntoPositionHash( unsigned int jobID );\r\n\tvoid removeFromPositionHash( unsigned int jobID );\r\n\r\npublic:\r\n\tJobManager() = delete;\r\n\tJobManager( Game* parent );\r\n\t~JobManager();\r\n\r\n\tvoid onTick();\r\n\r\n\tQString jobManagerInfo();\r\n\r\n\t//QSharedPointer<Job> getJob( QVariantList& profs, Position& pos );\r\n\t//QSharedPointer<Job> getJob( unsigned int jobID );\r\n\r\n\tunsigned int getJob( QStringList profs, unsigned int gnomeID, Position& pos );\r\n\tQSharedPointer<Job> getJob( unsigned int jobID );\r\n\tQSharedPointer<Job> getJobAtPos( Position pos );\r\n\r\n\tvoid giveBackJob( unsigned int jobID );\r\n\r\n\tunsigned int addJob( QString type, Position pos, int rotation, bool noJobSprite = false );\r\n\tunsigned int addJob( QString type, Position pos, QString item, QList<QString> materials, int rotation, bool noJobSprite = false );\r\n\r\n\tvoid setJobAvailable( unsigned int jobID );\r\n\tvoid setJobBeingWorked( unsigned int jobID, bool hasNeededTool = false );\r\n\tvoid finishJob( unsigned int jobID );\r\n\r\n\tvoid setJobSprites( unsigned int jobID, bool busy, bool remove );\r\n\r\n\tvoid addLoadedJob( QVariant vals );\r\n\r\n\tconst QHash<unsigned int, QSharedPointer<Job>>& allJobs()\r\n\t{\r\n\t\treturn m_jobList;\r\n\t}\r\n\r\n\tvoid cancelJob( const Position& pos );\r\n\tvoid deleteJob( unsigned int jobID );\r\n\tvoid deleteJobAt( const Position& pos );\r\n\tvoid raisePrio( Position& pos );\r\n\tvoid lowerPrio( Position& pos );\r\n};\r\n"
  },
  {
    "path": "src/game/mechanismmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"mechanismmanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/fluidmanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QQueue>\r\n\r\nQVariantMap MechanismData::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Type\", type );\r\n\tout.insert( \"ItemID\", itemID );\r\n\tout.insert( \"Pos\", pos.toString() );\r\n\tout.insert( \"Rot\", rot );\r\n\tout.insert( \"Gui\", gui );\r\n\tout.insert( \"Active\", active );\r\n\tout.insert( \"HasPower\", hasPower );\r\n\tout.insert( \"ChangeActive\", changeActive );\r\n\tout.insert( \"Produce\", producePower );\r\n\tout.insert( \"Consume\", consumePower );\r\n\tout.insert( \"Fuel\", fuel );\r\n\tout.insert( \"MaxFuel\", maxFuel );\r\n\tout.insert( \"RFThreshold\", refuelThreshold );\r\n\tout.insert( \"ConnectsTo\", Global::util->positionList2Variant( connectsTo ) );\r\n\tout.insert( \"IsInvertable\", isInvertable );\r\n\tout.insert( \"Inverted\", inverted );\r\n\tout.insert( \"ChangeInverted\", changeInverted );\r\n\tout.insert( \"Anim\", anim );\r\n\treturn out;\r\n}\r\n\r\nvoid MechanismData::deserialize( QVariantMap in )\r\n{\r\n\ttype            = (MechanismType)in.value( \"Type\" ).toInt();\r\n\titemID          = in.value( \"ItemID\" ).toUInt();\r\n\tpos             = Position( in.value( \"Pos\" ) );\r\n\trot             = in.value( \"Rot\" ).toInt();\r\n\tgui             = in.value( \"Gui\" ).toString();\r\n\tactive          = in.value( \"Active\" ).toBool();\r\n\thasPower        = in.value( \"HasPower\" ).toBool();\r\n\tchangeActive    = in.value( \"ChangeActive\" ).toBool();\r\n\tproducePower    = in.value( \"Produce\" ).toInt();\r\n\tconsumePower    = in.value( \"Consume\" ).toInt();\r\n\tfuel            = in.value( \"Fuel\" ).toInt();\r\n\tmaxFuel         = in.value( \"MaxFuel\" ).toInt();\r\n\trefuelThreshold = in.value( \"RFThreshold\" ).toInt();\r\n\tconnectsTo      = Global::util->variantList2Position( in.value( \"ConnectsTo\" ).toList() );\r\n\tisInvertable    = in.value( \"IsInvertable\" ).toBool();\r\n\tinverted        = in.value( \"Inverted\" ).toBool();\r\n\tchangeInverted  = in.value( \"ChangeInverted\" ).toBool();\r\n\tanim\t\t\t= in.value( \"Anim\" ).toBool();\r\n}\r\n\r\nMechanismManager::MechanismManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tm_string2Type.insert( \"None\", MT_NONE );\r\n\tm_string2Type.insert( \"Axle\", MT_AXLE );\r\n\tm_string2Type.insert( \"Lever\", MT_LEVER );\r\n\tm_string2Type.insert( \"VerticalAxle\", MT_VERTICALAXLE );\r\n\tm_string2Type.insert( \"GearBox\", MT_GEARBOX );\r\n\tm_string2Type.insert( \"SteamEngine\", MT_ENGINE );\r\n\tm_string2Type.insert( \"Pump\", MT_PUMP );\r\n\tm_string2Type.insert( \"MechanicalWall\", MT_WALL );\r\n\tm_string2Type.insert( \"PressurePlate\", MT_PRESSUREPLATE );\r\n}\r\n\r\nMechanismManager::~MechanismManager()\r\n{\r\n}\r\n\r\nvoid MechanismManager::loadMechanisms( QVariantList data )\r\n{\r\n\tfor ( auto vdata : data )\r\n\t{\r\n\t\tMechanismData md;\r\n\t\tauto vmd = vdata.toMap();\r\n\r\n\t\tmd.deserialize( vmd );\r\n\r\n\t\tinstallItem( md );\r\n\t}\r\n\tupdateNetWorks();\r\n}\r\n\r\nvoid MechanismManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tint tickDiff = 1;\r\n\tif ( m_lastTick != 0 )\r\n\t{\r\n\t\ttickDiff = tickNumber - m_lastTick;\r\n\t}\r\n\tm_lastTick = tickNumber;\r\n\r\n\tif ( m_needNetworkUpdate )\r\n\t{\r\n\t\tupdateNetWorks();\r\n\t}\r\n\r\n\tfor ( auto& network : m_networks )\r\n\t{\r\n\t\tnetwork.produce = 0;\r\n\t\tnetwork.consume = 0;\r\n\t\tfor ( auto itemID : network.producers )\r\n\t\t{\r\n\t\t\tif ( m_mechanisms.contains( itemID ) )\r\n\t\t\t{\r\n\t\t\t\tauto& md = m_mechanisms[itemID];\r\n\t\t\t\tif ( md.active && md.fuel > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tmd.fuel -= tickDiff;\r\n\t\t\t\t\tif ( md.fuel > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tnetwork.produce += md.producePower;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->m_world->setWallSpriteAnim( m_mechanisms[itemID].pos, false );\r\n\t\t\t\t\t\tm_needNetworkUpdate = 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\tfor ( auto itemID : network.consumers )\r\n\t\t{\r\n\t\t\tif ( m_mechanisms.contains( itemID ) )\r\n\t\t\t{\r\n\t\t\t\tauto& md = m_mechanisms[itemID];\r\n\t\t\t\tif ( md.active )\r\n\t\t\t\t{\r\n\t\t\t\t\tnetwork.consume += md.consumePower;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbool enoughPower = ( network.produce >= network.consume );\r\n\t\t//qDebug() << \"Network power consume/produce\" << network.consume << network.produce;\r\n\t\tfor ( auto itemID : network.consumers )\r\n\t\t{\r\n\t\t\tif ( m_mechanisms.contains( itemID ) )\r\n\t\t\t{\r\n\t\t\t\tauto& md = m_mechanisms[itemID];\r\n\t\t\t\tif ( md.hasPower != enoughPower )\r\n\t\t\t\t{\r\n\t\t\t\t\tmd.hasPower = enoughPower;\r\n\r\n\t\t\t\t\tupdateSpritesAndFlags( md, md.active && enoughPower );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor( auto& md : m_mechanisms )\r\n\t{\r\n\t\tif( !md.job )\r\n\t\t{\r\n\t\t\tif( md.changeActive )\r\n\t\t\t{\r\n\t\t\t\tauto jobID = g->jm()->addJob( \"SwitchMechanism\", md.pos, 0, false );\r\n\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\tif( job )\r\n\t\t\t\t{\r\n\t\t\t\t\tjob->setMechanism( md.itemID );\r\n\t\t\t\t\tmd.job = job;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if( md.changeInverted )\r\n\t\t\t{\r\n\t\t\t\tauto jobID = g->jm()->addJob( \"InvertMechanism\", md.pos, 0, false );\r\n\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\tif( job )\r\n\t\t\t\t{\r\n\t\t\t\t\tjob->setMechanism( md.itemID );\r\n\t\t\t\t\tmd.job = job;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( md.active && md.fuel < ( md.maxFuel * md.refuelThreshold / 100 ) )\r\n\t\t\t{\r\n\t\t\t\tauto jobID = g->jm()->addJob( \"Refuel\", md.pos, 0, false );\r\n\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\tif( job )\r\n\t\t\t\t{\r\n\t\t\t\t\tjob->setMechanism( md.itemID );\r\n\t\t\t\t\tjob->addRequiredItem( 1, \"RawCoal\", \"any\", {} );\r\n\t\t\t\t\tmd.job = job;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool MechanismManager::axlesChanged()\r\n{\r\n\tbool out       = m_axlesChanged;\r\n\tm_axlesChanged = false;\r\n\treturn out;\r\n}\r\n\r\nQHash<unsigned int, AxleData> MechanismManager::axleData()\r\n{\r\n\treturn m_axleData;\r\n}\r\n\r\nbool MechanismManager::hasMechanism( Position pos )\r\n{\r\n\treturn m_floorPositions.contains( pos.toInt() ) || m_wallPositions.contains( pos.toInt() );\r\n}\r\n\r\nbool MechanismManager::hasGearBox( Position pos )\r\n{\r\n\tif ( m_floorPositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto itemID = m_floorPositions[pos.toInt()];\r\n\t\treturn ( g->m_inv->itemSID( itemID ) == \"GearBox\" );\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool MechanismManager::hasPower( Position pos )\r\n{\r\n\tif ( m_wallPositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto itemID = m_wallPositions[pos.toInt()];\r\n\t\tif ( m_mechanisms.contains( itemID ) )\r\n\t\t{\r\n\t\t\treturn m_mechanisms[itemID].hasPower;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQString MechanismManager::mechanismName( Position pos )\r\n{\r\n\tunsigned itemID = mechanismID( pos );\r\n\tif ( itemID )\r\n\t{\r\n\t\treturn S::s( \"$ItemName_\" + g->m_inv->itemSID( itemID ) );\r\n\t}\r\n\treturn \"No mechanism\";\r\n}\r\n\r\nunsigned int MechanismManager::mechanismID( Position pos )\r\n{\r\n\tif ( m_wallPositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto itemID = m_wallPositions[pos.toInt()];\r\n\t\treturn itemID;\r\n\t}\r\n\telse if ( m_floorPositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto itemID = m_floorPositions[pos.toInt()];\r\n\t\treturn itemID;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool MechanismManager::hasGUI( unsigned int itemID )\r\n{\r\n\tQString itemSID = g->m_inv->itemSID( itemID );\r\n\tauto row        = DB::selectRow( \"Mechanism\", itemSID );\r\n\tif ( !row.value( \"GUI\" ).toString().isEmpty() )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool MechanismManager::hasGUI( Position pos )\r\n{\r\n\tunsigned itemID = mechanismID( pos );\r\n\tif ( itemID )\r\n\t{\r\n\t\tQString itemSID = g->m_inv->itemSID( itemID );\r\n\t\tauto row        = DB::selectRow( \"Mechanism\", itemSID );\r\n\t\tif ( !row.value( \"GUI\" ).toString().isEmpty() )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQString MechanismManager::gui( unsigned int itemID )\r\n{\r\n\tQString itemSID = g->m_inv->itemSID( itemID );\r\n\tauto row        = DB::selectRow( \"Mechanism\", itemSID );\r\n\treturn row.value( \"GUI\" ).toString();\r\n}\r\n\r\nvoid MechanismManager::installItem( MechanismData md )\r\n{\r\n\tQString itemSID = g->m_inv->itemSID( md.itemID );\r\n\tif ( itemSID == \"Axle\" )\r\n\t{\r\n\t\tm_floorPositions.insert( md.pos.toInt(), md.itemID );\r\n\r\n\t\tAxleData ad;\r\n\t\tad.itemID   = md.itemID;\r\n\t\tad.anim     = false;\r\n\t\tad.localRot = md.rot;\r\n\t\tad.pos      = md.pos;\r\n\t\tad.spriteID = g->m_inv->spriteID( md.itemID );\r\n\r\n\t\tm_axleData.insert( md.pos.toInt(), ad );\r\n\t}\r\n\telse if ( itemSID == \"GearBox\" )\r\n\t{\r\n\t\tm_floorPositions.insert( md.pos.toInt(), md.itemID );\r\n\t}\r\n\telse if ( itemSID == \"SteamEngine\" )\r\n\t{\r\n\t\tm_wallPositions.insert( md.pos.toInt(), md.itemID );\r\n\t\tg->m_world->setWallSpriteAnim( md.pos, md.active );\r\n\t}\r\n\telse if ( itemSID == \"Lever\" )\r\n\t{\r\n\t\tm_wallPositions.insert( md.pos.toInt(), md.itemID );\r\n\t}\r\n\telse if ( itemSID == \"PressurePlate\" )\r\n\t{\r\n\t\tm_floorPositions.insert( md.pos.toInt(), md.itemID );\r\n\t}\r\n\telse if ( itemSID == \"VerticalAxle\" )\r\n\t{\r\n\t\tm_wallPositions.insert( md.pos.toInt(), md.itemID );\r\n\r\n\t\tAxleData ad;\r\n\t\tad.itemID     = md.itemID;\r\n\t\tad.anim       = false;\r\n\t\tad.localRot   = md.rot;\r\n\t\tad.pos        = md.pos;\r\n\t\tad.isVertical = true;\r\n\t\tad.spriteID   = g->m_inv->spriteID( md.itemID );\r\n\r\n\t\tm_axleData.insert( md.pos.toInt(), ad );\r\n\t}\r\n\telse if ( itemSID == \"MechanicalWall\" )\r\n\t{\r\n\t\tm_wallPositions.insert( md.pos.toInt(), md.itemID );\r\n\t}\r\n\telse if ( itemSID == \"Pump\" )\r\n\t{\r\n\t\tm_wallPositions.insert( md.pos.toInt(), md.itemID );\r\n\t\tg->flm()->addInput( md.pos, md.itemID );\r\n\t}\r\n\r\n\tm_mechanisms.insert( md.itemID, md );\r\n}\r\n\r\nvoid MechanismManager::installItem( unsigned int itemID, Position pos, int rot )\r\n{\r\n\tQString itemSID = g->m_inv->itemSID( itemID );\r\n\r\n\tMechanismData md;\r\n\tmd.itemID = itemID;\r\n\tmd.pos    = pos;\r\n\tmd.rot    = rot;\r\n\r\n\tauto row = DB::selectRow( \"Mechanism\", itemSID );\r\n\tmd.gui   = row.value( \"GUI\" ).toString();\r\n\r\n\tmd.fuel         = 0;\r\n\tmd.producePower = row.value( \"ProducePower\" ).toInt();\r\n\tmd.maxFuel      = row.value( \"MaxFuel\" ).toInt();\r\n\tmd.consumePower = row.value( \"ConsumePower\" ).toInt();\r\n\r\n\tmd.anim = row.value( \"Anim\" ).toBool();\r\n\r\n\tmd.type = m_string2Type.value( itemSID );\r\n\r\n\tswitch ( md.type )\r\n\t{\r\n\t\tcase MT_AXLE:\r\n\t\t{\r\n\t\t\tif ( rot == 0 || rot == 2 )\r\n\t\t\t{\r\n\t\t\t\tmd.connectsTo.append( pos.eastOf() );\r\n\t\t\t\tmd.connectsTo.append( pos.westOf() );\r\n\t\t\t}\r\n\t\t\telse if ( rot == 1 || rot == 3 )\r\n\t\t\t{\r\n\t\t\t\tmd.connectsTo.append( pos.northOf() );\r\n\t\t\t\tmd.connectsTo.append( pos.southOf() );\r\n\t\t\t}\r\n\r\n\t\t\tm_floorPositions.insert( pos.toInt(), itemID );\r\n\r\n\t\t\tAxleData ad;\r\n\t\t\tad.itemID   = itemID;\r\n\t\t\tad.anim     = false;\r\n\t\t\tad.localRot = rot;\r\n\t\t\tad.pos      = pos;\r\n\t\t\tad.spriteID = g->m_inv->spriteID( itemID );\r\n\r\n\t\t\tm_axleData.insert( pos.toInt(), ad );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_GEARBOX:\r\n\t\t{\r\n\t\t\tmd.connectsTo.append( pos.eastOf() );\r\n\t\t\tmd.connectsTo.append( pos.westOf() );\r\n\t\t\tmd.connectsTo.append( pos.northOf() );\r\n\t\t\tmd.connectsTo.append( pos.southOf() );\r\n\t\t\tmd.connectsTo.append( pos.belowOf() );\r\n\t\t\tmd.connectsTo.append( pos );\r\n\r\n\t\t\tm_floorPositions.insert( pos.toInt(), itemID );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_ENGINE:\r\n\t\t{\r\n\t\t\tmd.connectsTo.append( pos.eastOf() );\r\n\t\t\tmd.connectsTo.append( pos.westOf() );\r\n\t\t\tmd.connectsTo.append( pos.northOf() );\r\n\t\t\tmd.connectsTo.append( pos.southOf() );\r\n\r\n\t\t\tm_wallPositions.insert( pos.toInt(), itemID );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_LEVER:\r\n\t\t{\r\n\t\t\tmd.active = false;\r\n\r\n\t\t\tm_wallPositions.insert( pos.toInt(), itemID );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_PRESSUREPLATE:\r\n\t\t{\r\n\t\t\tmd.active       = true;\r\n\t\t\tmd.isInvertable = true;\r\n\r\n\t\t\tm_floorPositions.insert( pos.toInt(), itemID );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_PUMP:\r\n\t\t{\r\n\t\t\tg->flm()->addInput( pos, itemID );\r\n\t\t\tm_wallPositions.insert( pos.toInt(), itemID );\r\n\r\n\t\t\tmd.connectsTo.append( md.pos.eastOf() );\r\n\t\t\tmd.connectsTo.append( md.pos.westOf() );\r\n\t\t\tmd.connectsTo.append( md.pos.northOf() );\r\n\t\t\tmd.connectsTo.append( md.pos.southOf() );\r\n\t\t\tmd.active = true;\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_VERTICALAXLE:\r\n\t\t{\r\n\t\t\tmd.connectsTo.append( pos );\r\n\t\t\tmd.connectsTo.append( pos.aboveOf() );\r\n\r\n\t\t\tm_wallPositions.insert( pos.toInt(), itemID );\r\n\r\n\t\t\tAxleData ad;\r\n\t\t\tad.itemID     = itemID;\r\n\t\t\tad.anim       = false;\r\n\t\t\tad.localRot   = rot;\r\n\t\t\tad.pos        = pos;\r\n\t\t\tad.isVertical = true;\r\n\t\t\tad.spriteID   = g->m_inv->spriteID( itemID );\r\n\r\n\t\t\tm_axleData.insert( pos.toInt(), ad );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase MT_WALL:\r\n\t\t{\r\n\t\t\tmd.connectsTo.append( pos.eastOf() );\r\n\t\t\tmd.connectsTo.append( pos.westOf() );\r\n\t\t\tmd.connectsTo.append( pos.northOf() );\r\n\t\t\tmd.connectsTo.append( pos.southOf() );\r\n\t\t\tmd.active       = true;\r\n\t\t\tmd.isInvertable = true;\r\n\t\t\tm_wallPositions.insert( pos.toInt(), itemID );\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\tm_mechanisms.insert( itemID, md );\r\n\r\n\tg->m_world->setWallSpriteAnim( md.pos, false );\r\n\r\n\tm_needNetworkUpdate = true;\r\n}\r\n\r\nvoid MechanismManager::uninstallItem( unsigned int itemID )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tauto md = m_mechanisms[itemID];\r\n\r\n\t\tunsigned int posID = md.pos.toInt();\r\n\t\tm_wallPositions.remove( posID );\r\n\t\tm_floorPositions.remove( posID );\r\n\t\tm_axleData.remove( posID );\r\n\r\n\t\tm_mechanisms.remove( itemID );\r\n\r\n\t\tswitch ( md.type )\r\n\t\t{\r\n\t\t\tcase MT_WALL:\r\n\t\t\t{\r\n\t\t\t\tg->m_world->setWalkable( md.pos, true );\r\n\t\t\t\tTile& tile    = g->m_world->getTile( md.pos );\r\n\t\t\t\ttile.wallType = WT_NOWALL;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tm_needNetworkUpdate = true;\r\n\t}\r\n}\r\n\r\nMechanismData MechanismManager::mechanismData( unsigned int itemID )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\treturn m_mechanisms[itemID];\r\n\t}\r\n\treturn MechanismData();\r\n}\r\n\r\nbool MechanismManager::changeActive( unsigned int itemID )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tbool out                          = !m_mechanisms[itemID].changeActive;\r\n\t\tm_mechanisms[itemID].changeActive = out;\r\n\t\treturn out;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid MechanismManager::setActive( unsigned int itemID, bool active )\r\n{\r\n\tqDebug() << \"setActive\";\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tauto& md = m_mechanisms[itemID];\r\n\r\n\t\tmd.active = active;\r\n\r\n\t\tsetConnectsTo( md );\r\n\r\n\t\tif( md.maxFuel > 0 )\r\n\t\t{\r\n\t\t\tupdateSpritesAndFlags( md, md.active && ( md.fuel > 0 ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tupdateSpritesAndFlags( md, md.active );\r\n\t\t}\r\n\r\n\t\tm_needNetworkUpdate = true;\r\n\t}\r\n}\r\n\r\nbool MechanismManager::changeInverted( unsigned int itemID )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tbool out                            = !m_mechanisms[itemID].changeInverted;\r\n\t\tm_mechanisms[itemID].changeInverted = out;\r\n\t\treturn out;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid MechanismManager::setInverted( unsigned int itemID, bool inv )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tauto& md = m_mechanisms[itemID];\r\n\r\n\t\tmd.inverted = inv;\r\n\r\n\t\tsetConnectsTo( md );\r\n\r\n\t\tm_needNetworkUpdate = true;\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::setConnectsTo( MechanismData& md )\r\n{\r\n\tswitch( md.type )\r\n\t{\r\n\t\tcase MT_LEVER:\r\n\t\tcase MT_PRESSUREPLATE:\r\n\t\tmd.connectsTo.clear();\r\n\t\t\tif ( md.inverted )\r\n\t\t\t{\r\n\t\t\t\tif ( !md.active )\r\n\t\t\t\t{\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.eastOf() );\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.westOf() );\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.northOf() );\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.southOf() );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( md.active )\r\n\t\t\t\t{\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.eastOf() );\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.westOf() );\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.northOf() );\r\n\t\t\t\t\tmd.connectsTo.append( md.pos.southOf() );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::toggleActive( unsigned int itemID )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tauto& md = m_mechanisms[itemID];\r\n\t\tsetActive( itemID, !md.active );\r\n\t\tmd.changeActive = false;\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::toggleInvert( unsigned int itemID )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tauto& md = m_mechanisms[itemID];\r\n\t\tsetInverted( itemID, !md.inverted );\r\n\t\tmd.changeInverted = false;\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::refuel( unsigned int itemID, int burnValue )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tint currentFuel = m_mechanisms[itemID].fuel;\r\n\r\n\t\tint newFuel = qMin( m_mechanisms[itemID].maxFuel, currentFuel + burnValue );\r\n\r\n\t\tm_mechanisms[itemID].fuel = newFuel;\r\n\r\n\t\tif ( currentFuel == 0 )\r\n\t\t{\r\n\t\t\tm_needNetworkUpdate = true;\r\n\r\n\t\t\tif ( newFuel > 0 )\r\n\t\t\t{\r\n\t\t\t\tg->m_world->setWallSpriteAnim( m_mechanisms[itemID].pos, m_mechanisms[itemID].active && ( m_mechanisms[itemID].fuel > 0 ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::setRefuelThreshold( unsigned int itemID, int percent )\r\n{\r\n\tif ( m_mechanisms.contains( itemID ) )\r\n\t{\r\n\t\tm_mechanisms[itemID].refuelThreshold = percent;\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::updateNetWorks()\r\n{\r\n\tQQueue<MechanismData> workQueue;\r\n\tm_networks.clear();\r\n\r\n\tfor ( auto& md : m_mechanisms )\r\n\t{\r\n\t\tmd.networkID = 0;\r\n\t\tmd.hasPower  = false;\r\n\r\n\t\tif ( md.consumePower > 0 )\r\n\t\t{\r\n\t\t\tupdateSpritesAndFlags( md, false );\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto md : m_mechanisms )\r\n\t{\r\n\t\tif ( md.producePower > 0 && md.networkID == 0 )\r\n\t\t{\r\n\t\t\tmd.networkID = md.itemID;\r\n\t\t\tworkQueue.enqueue( md );\r\n\r\n\t\t\tMechanismNetwork mn;\r\n\t\t\tmn.id = md.itemID;\r\n\t\t\twhile ( !workQueue.empty() )\r\n\t\t\t{\r\n\t\t\t\tauto md2 = workQueue.dequeue();\r\n\t\t\t\tif ( md2.active && md2.fuel > 0 && md2.producePower > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tmn.produce += md2.producePower;\r\n\t\t\t\t\tmn.producers.insert( md2.itemID );\r\n\t\t\t\t}\r\n\t\t\t\tif ( md2.active && md2.consumePower > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tmn.consume += md2.consumePower;\r\n\t\t\t\t\tmn.consumers.insert( md2.itemID );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( auto toPos : md2.connectsTo )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_floorPositions.contains( toPos.toInt() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto& neighbormd = m_mechanisms[m_floorPositions[toPos.toInt()]];\r\n\t\t\t\t\t\tif ( neighbormd.networkID == 0 && neighbormd.connectsTo.contains( md2.pos ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tneighbormd.networkID = md2.networkID;\r\n\t\t\t\t\t\t\tworkQueue.enqueue( neighbormd );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( m_wallPositions.contains( toPos.toInt() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto& neighbormd = m_mechanisms[m_wallPositions[toPos.toInt()]];\r\n\t\t\t\t\t\tif ( neighbormd.networkID == 0 && neighbormd.connectsTo.contains( md2.pos ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tneighbormd.networkID = md2.networkID;\r\n\t\t\t\t\t\t\tworkQueue.enqueue( neighbormd );\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\tm_networks.insert( mn.id, mn );\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto& ad : m_axleData )\r\n\t{\r\n\t\tunsigned int networkID = m_mechanisms[ad.itemID].networkID;\r\n\t\tif ( m_networks[networkID].produce > 0 && m_networks[networkID].produce >= m_networks[networkID].consume )\r\n\t\t{\r\n\t\t\tad.anim = true;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tad.anim = false;\r\n\t\t}\r\n\r\n\t\tif ( ad.isVertical )\r\n\t\t{\r\n\t\t\tg->m_world->setWallSpriteAnim( ad.pos, ad.anim );\r\n\t\t}\r\n\t}\r\n\r\n\tm_axlesChanged      = true;\r\n\tm_needNetworkUpdate = false;\r\n}\r\n\r\nvoid MechanismManager::updateSpritesAndFlags( MechanismData& md, bool isOn )\r\n{\r\n\tQString itemSID = g->inv()->itemSID( md.itemID );\r\n\tauto row        = DB::selectRow( \"Mechanism\", itemSID );\r\n\tif( md.inverted )\r\n\t{\r\n\t\tisOn  = !isOn;\r\n\t}\r\n\r\n\tif ( md.anim )\r\n\t{\r\n\t\tg->m_world->setWallSpriteAnim( md.pos, isOn );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( md.anim )\r\n\t\t{\r\n\t\t\tg->m_world->setWallSpriteAnim( md.pos, isOn );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( isOn )\r\n\t\t\t{\r\n\t\t\t\tQString wallSpriteOn  = row.value( \"WallSpriteOn\" ).toString();\r\n\t\t\t\tQString floorSpriteOn = row.value( \"FloorSpriteOn\" ).toString();\r\n\t\t\t\tif ( !wallSpriteOn.isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->m_world->setWallSprite( md.pos, g->m_sf->createSprite( wallSpriteOn, { g->m_inv->materialSID( md.itemID ) } )->uID );\r\n\t\t\t\t\tg->m_world->addToUpdateList( md.pos );\r\n\t\t\t\t}\r\n\t\t\t\tif ( !floorSpriteOn.isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->m_world->setFloorSprite( md.pos, g->m_sf->createSprite( floorSpriteOn, { g->m_inv->materialSID( md.itemID ) } )->uID );\r\n\t\t\t\t\tg->m_world->addToUpdateList( md.pos );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tQString wallSpriteOff  = row.value( \"WallSpriteOff\" ).toString();\r\n\t\t\t\tQString floorSpriteOff = row.value( \"FloorSpriteOff\" ).toString();\r\n\r\n\t\t\t\tif ( !wallSpriteOff.isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->m_world->setWallSprite( md.pos, g->m_sf->createSprite( wallSpriteOff, { g->m_inv->materialSID( md.itemID ) } )->uID );\r\n\t\t\t\t\tg->m_world->addToUpdateList( md.pos );\r\n\t\t\t\t}\r\n\t\t\t\tif ( !floorSpriteOff.isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->m_world->setFloorSprite( md.pos, g->m_sf->createSprite( floorSpriteOff, { g->m_inv->materialSID( md.itemID ) } )->uID );\r\n\t\t\t\t\tg->m_world->addToUpdateList( md.pos );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tQString effectOn  = row.value( \"EffectOn\" ).toString();\r\n\tQString effectOff = row.value( \"EffectOff\" ).toString();\r\n\r\n\tif ( isOn )\r\n\t{\r\n\t\tremoveEffect( md.pos, effectOff );\r\n\t\taddEffect( md.pos, effectOn );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tremoveEffect( md.pos, effectOn );\r\n\t\taddEffect( md.pos, effectOff );\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::addEffect( Position pos, QString effect )\r\n{\r\n\tif ( effect == \"Wall\" )\r\n\t{\r\n\t\tg->m_world->setWalkable( pos, false );\r\n\t\tTile& tile    = g->m_world->getTile( pos );\r\n\t\ttile.wallType = WT_SOLIDWALL;\r\n\r\n\t\t// TODO if floor above crush tile inhabitants\r\n\t}\r\n\telse if ( effect == \"Floor\" )\r\n\t{\r\n\t\tg->m_world->setWalkable( pos, true );\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::removeEffect( Position pos, QString effect )\r\n{\r\n\tif ( effect == \"Wall\" )\r\n\t{\r\n\t\tg->m_world->setWalkable( pos, true );\r\n\t\tTile& tile    = g->m_world->getTile( pos );\r\n\t\ttile.wallType = WT_NOWALL;\r\n\t}\r\n\telse if ( effect == \"Floor\" )\r\n\t{\r\n\t\tg->m_world->setWalkable( pos, false );\r\n\t}\r\n}\r\n\r\nvoid MechanismManager::updateCreaturesAtPos( Position pos, int numCreatures )\r\n{\r\n\tunsigned int id = mechanismID( pos );\r\n\tif ( id )\r\n\t{\r\n\t\tauto& md = m_mechanisms[id];\r\n\t\tif ( md.type == MT_PRESSUREPLATE )\r\n\t\t{\r\n\t\t\tif ( numCreatures > 0 )\r\n\t\t\t{\r\n\t\t\t\tsetActive( id, true );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tsetActive( id, false );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/game/mechanismmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/position.h\"\r\n#include \"../base/tile.h\"\r\n#include \"../game/job.h\"\r\n\r\nclass Game;\r\n\r\nenum MechanismType\r\n{\r\n\tMT_NONE = 0,\r\n\tMT_AXLE,\r\n\tMT_VERTICALAXLE,\r\n\tMT_GEARBOX,\r\n\tMT_LEVER,\r\n\tMT_ENGINE,\r\n\tMT_PUMP,\r\n\tMT_WALL,\r\n\tMT_PRESSUREPLATE\r\n};\r\n\r\nstruct MechanismData\r\n{\r\n\tMechanismType type = MT_NONE;\r\n\r\n\tunsigned int itemID    = 0;\r\n\tunsigned int networkID = 0;\r\n\tPosition pos;\r\n\tunsigned char rot = 0;\r\n\r\n\tQString gui;\r\n\tQString name;\r\n\r\n\tbool active       = false;\r\n\tbool changeActive = false;\r\n\r\n\tint producePower = 0;\r\n\r\n\tint fuel            = 0;\r\n\tint maxFuel         = 0;\r\n\tint refuelThreshold = 50;\r\n\tint consumePower    = 0;\r\n\tbool hasPower       = false;\r\n\r\n\tbool anim = false;\r\n\r\n\tbool isInvertable   = false;\r\n\tbool inverted       = false;\r\n\tbool changeInverted = false;\r\n\r\n\tQList<Position> connectsTo;\r\n\r\n\tQVariantMap serialize() const;\r\n\tvoid deserialize( QVariantMap in );\r\n\r\n\tQWeakPointer<Job> job;\r\n};\r\n\r\nstruct MechanismNetwork\r\n{\r\n\tunsigned int id      = 0;\r\n\tunsigned int produce = 0;\r\n\tunsigned int consume = 0;\r\n\r\n\tQSet<unsigned int> producers;\r\n\tQSet<unsigned int> consumers;\r\n};\r\n\r\nclass MechanismManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( MechanismManager )\r\npublic:\r\n\tMechanismManager() = delete;\r\n\tMechanismManager( Game* parent );\r\n\t~MechanismManager();\r\n\r\n\tQHash<unsigned int, MechanismData>& mechanisms()\r\n\t{\r\n\t\treturn m_mechanisms;\r\n\t};\r\n\tvoid loadMechanisms( QVariantList data );\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tbool hasMechanism( Position pos );\r\n\tbool hasGearBox( Position pos );\r\n\r\n\tQString mechanismName( Position pos );\r\n\tunsigned int mechanismID( Position pos );\r\n\r\n\tbool hasGUI( unsigned int itemID );\r\n\tbool hasGUI( Position pos );\r\n\tQString gui( unsigned int itemID );\r\n\r\n\tbool hasPower( Position pos );\r\n\r\n\tvoid installItem( unsigned int itemID, Position pos, int rotation );\r\n\tvoid uninstallItem( unsigned int itemID );\r\n\r\n\tbool axlesChanged();\r\n\tQHash<unsigned int, AxleData> axleData();\r\n\r\n\tMechanismData mechanismData( unsigned int itemID );\r\n\r\n\tbool changeActive( unsigned int itemID );\r\n\tvoid toggleActive( unsigned int itemID );\r\n\r\n\tbool changeInverted( unsigned int itemID );\r\n\tvoid toggleInvert( unsigned int itemID );\r\n\r\n\tvoid setRefuelThreshold( unsigned int itemID, int percent );\r\n\r\n\tvoid refuel( unsigned int itemID, int burnValue );\r\n\r\n\tvoid updateCreaturesAtPos( Position pos, int numCreatures );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tvoid installItem( MechanismData md );\r\n\r\n\tvoid updateNetWorks();\r\n\r\n\tvoid updateSpritesAndFlags( MechanismData& md, bool isON );\r\n\tvoid addEffect( Position pos, QString effect );\r\n\tvoid removeEffect( Position pos, QString effect );\r\n\r\n\tvoid setActive( unsigned int itemID, bool active );\r\n\tvoid setInverted( unsigned int itemID, bool inv );\r\n\tvoid setConnectsTo( MechanismData& md );\r\n\r\n\tquint64 m_lastTick       = 0;\r\n\tbool m_needNetworkUpdate = false;\r\n\r\n\tQHash<unsigned int, MechanismData> m_mechanisms;\r\n\r\n\tQHash<unsigned int, unsigned int> m_floorPositions;\r\n\tQHash<unsigned int, unsigned int> m_wallPositions;\r\n\r\n\tQHash<unsigned int, AxleData> m_axleData;\r\n\r\n\tbool m_axlesChanged = false;\r\n\r\n\tQHash<unsigned int, MechanismNetwork> m_networks;\r\n\r\n\tQHash<QString, MechanismType> m_string2Type;\r\n};\r\n"
  },
  {
    "path": "src/game/militarymanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"militarymanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/io.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/gnome.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/inventory.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QJsonDocument>\r\n#include <QJsonObject>\r\n#include <QStandardPaths>\r\n\r\nQVariantMap UniformItem::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Type\", type );\r\n\tout.insert( \"Item\", item );\r\n\tout.insert( \"Material\", material );\r\n\tout.insert( \"Quality\", (int)quality );\r\n\r\n\treturn out;\r\n}\r\n\r\nUniformItem::UniformItem( const QVariantMap& in )\r\n{\r\n\ttype     = in.value( \"Type\" ).toString();\r\n\titem     = in.value( \"Item\" ).toString();\r\n\tmaterial = in.value( \"Material\" ).toString();\r\n\tquality  = (UniformItemQuality)in.value( \"Quality\" ).toInt();\r\n}\r\n\r\nQVariantMap Uniform::serialize()\r\n{\r\n\tQVariantMap vUni;\r\n\tvUni.insert( \"Name\", name );\r\n\tvUni.insert( \"ID\", id );\r\n\tQVariantMap items;\r\n\r\n\tfor( const auto& key : parts.keys() )\r\n\t{\r\n\t\titems.insert( key, parts[key].serialize() );\r\n\t}\r\n\tvUni.insert( \"Items\", items );\r\n\r\n\treturn vUni;\r\n}\r\n\r\nUniform::Uniform( const QVariantMap& in )\r\n{\r\n\tname          = in.value( \"Name\" ).toString();\r\n\tid            = in.value( \"ID\" ).toUInt();\r\n\tauto vmItems  = in.value( \"Items\" ).toMap();\r\n\r\n\tparts.insert( \"HeadArmor\", UniformItem( vmItems.value( \"HeadArmor\" ).toMap() ) );\r\n\tparts.insert( \"ChestArmor\", UniformItem( vmItems.value( \"ChestArmor\" ).toMap() ) );\r\n\tparts.insert( \"ArmArmor\", UniformItem( vmItems.value( \"ArmArmor\" ).toMap() ) );\r\n\tparts.insert( \"HandArmor\", UniformItem( vmItems.value( \"HandArmor\" ).toMap() ) );\r\n\tparts.insert( \"LegArmor\", UniformItem( vmItems.value( \"LegArmor\" ).toMap() ) );\r\n\tparts.insert( \"FootArmor\", UniformItem( vmItems.value( \"FootArmor\" ).toMap() ) );\r\n\tparts.insert( \"LeftHandHeld\", UniformItem( vmItems.value( \"LeftHandHeld\" ).toMap() ) );\r\n\tparts.insert( \"RightHandHeld\", UniformItem( vmItems.value( \"RightHandHeld\" ).toMap() ) );\r\n\tparts.insert( \"Back\", UniformItem( vmItems.value( \"Back\" ).toMap() ) );\r\n}\r\n\r\nUniform::Uniform()\r\n{\r\n\tparts.insert( \"HeadArmor\", UniformItem() );\r\n\tparts.insert( \"ChestArmor\", UniformItem() );\r\n\tparts.insert( \"ArmArmor\", UniformItem() );\r\n\tparts.insert( \"HandArmor\", UniformItem() );\r\n\tparts.insert( \"LegArmor\", UniformItem( ) );\r\n\tparts.insert( \"FootArmor\", UniformItem() );\r\n\tparts.insert( \"LeftHandHeld\", UniformItem() );\r\n\tparts.insert( \"RightHandHeld\", UniformItem() );\r\n\tparts.insert( \"Back\", UniformItem() );\r\n}\r\n\r\n\r\nQVariantMap MilitaryRole::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Name\", name );\r\n\tout.insert( \"ID\", id );\r\n\tout.insert( \"Uniform\", uniform.serialize() );\r\n\tout.insert( \"MaintainDist\", maintainDist );\r\n\tout.insert( \"RetreatBleeding\", retreatBleeding );\r\n\tout.insert( \"IsCivilian\", isCivilian );\r\n\r\n\treturn out;\r\n}\r\n\r\nMilitaryRole::MilitaryRole( const QVariantMap& in )\r\n{\r\n\tname            = in.value( \"Name\" ).toString();\r\n\tid              = in.value( \"ID\" ).toUInt();\r\n\tuniform         = Uniform( in.value( \"Uniform\" ).toMap() );\r\n\tisCivilian      = in.value( \"IsCivilian\" ).toBool();\r\n\tmaintainDist    = in.value( \"MaintainDist\" ).toBool();\r\n\tretreatBleeding = in.value( \"RetreatBleeding\" ).toBool();\r\n}\r\n\r\nQVariantMap Squad::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tout.insert( \"Name\", name );\r\n\tout.insert( \"ID\", id );\r\n\tout.insert( \"Gnomes\", Global::util->uintList2Variant( gnomes ) );\r\n\r\n\tQVariantList vl;\r\n\tfor( auto prio : priorities )\r\n\t{\r\n\t\tQVariantMap vm;\r\n\t\tvm.insert( \"Type\", prio.type );\r\n\t\tvm.insert( \"Attitude\", (int)prio.attitude );\r\n\t\tvl.append( vm );\r\n\t}\r\n\tout.insert( \"Priorities\", vl );\r\n\r\n\treturn out;\r\n}\r\n\r\nSquad::Squad( QList<QString> tps, const QVariantMap& in ) :\r\n\ttypes( tps )\r\n{\r\n\tname       = in.value( \"Name\" ).toString();\r\n\tid         = in.value( \"ID\" ).toUInt();\r\n\tgnomes     = Global::util->variantList2UInt( in.value( \"Gnomes\" ).toList() );\r\n\r\n\tif( in.contains( \"Priorities\" ) )\r\n\t{\r\n\t\tQSet<QString> typeSet;\r\n\t\tauto vl = in.value( \"Priorities\" ).toList();\r\n\t\tfor( auto vEntry : vl )\r\n\t\t{\r\n\t\t\tauto vm = vEntry.toMap();\r\n\t\t\tauto type = vm.value( \"Type\" ).toString();\r\n\t\t\ttypeSet.insert( type );\r\n\t\t\tTargetPriority tp { type, (MilAttitude)vm.value( \"Attitude\" ).toInt() };\r\n\t\t\tpriorities.append( tp );\r\n\t\t}\r\n\t\tfor( auto type : types )\r\n\t\t{\r\n\t\t\tif( !typeSet.contains( type ) )\r\n\t\t\t{\r\n\t\t\t\tTargetPriority tp { type, MilAttitude::FLEE };\r\n\t\t\t\tpriorities.append( tp );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( auto type : types )\r\n\t\t{\r\n\t\t\tTargetPriority tp { type, MilAttitude::FLEE };\r\n\t\t\tpriorities.append( tp );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nMilitaryManager::MilitaryManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n}\r\nMilitaryManager::~MilitaryManager()\r\n{\r\n}\r\n\r\nvoid MilitaryManager::init()\r\n{\r\n\tauto mm = GameState::military;\r\n\tQVariantList pl;\r\n\tif ( mm.contains( \"Roles\" ) )\r\n\t{\r\n\t\tpl = mm.value( \"Roles\" ).toList();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//load from file\r\n\t\tQJsonDocument jd;\r\n\t\tIO::loadFile( IO::getDataFolder() + \"/settings/military.json\", jd );\r\n\t\tQVariantMap vm = jd.toVariant().toMap();\r\n\t\tif ( vm.contains( \"Roles\" ) )\r\n\t\t{\r\n\t\t\tpl = vm.value( \"Roles\" ).toList();\r\n\t\t}\r\n\t}\r\n\tfor ( auto entry : pl )\r\n\t{\r\n\t\tMilitaryRole pos( entry.toMap() );\r\n\t\tm_roles.insert( pos.id, pos );\r\n\t}\r\n\tif ( m_roles.empty() )\r\n\t{\r\n\t\taddRole();\r\n\t}\r\n\r\n\t\r\n\tif ( mm.contains( \"Squads\" ) )\r\n\t{\r\n\t\tauto sl = mm.value( \"Squads\" ).toList();\r\n\t\tfor ( auto entry : sl )\r\n\t\t{\r\n\t\t\tSquad squad( g->m_creatureManager->types(), entry.toMap() );\r\n\t\t\tm_squads.insert( squad.id, squad );\r\n\r\n\t\t\tfor( auto gnome : squad.gnomes )\r\n\t\t\t{\r\n\t\t\t\tm_gnome2Squad.insert( gnome, squad.id );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( m_squads.empty() )\r\n\t{\r\n\t\taddSquad();\r\n\t}\r\n}\r\n\r\nvoid MilitaryManager::save()\r\n{\r\n\tauto vm = serialize();\r\n\tvm.remove( \"Squads\" );\r\n\tQJsonObject jo = QJsonObject::fromVariantMap( vm );\r\n\tIO::saveFile( IO::getDataFolder() + \"/settings/military.json\", jo );\r\n}\r\n\r\nQVariantMap MilitaryManager::serialize()\r\n{\r\n\tQVariantMap military;\r\n\r\n\tQVariantList vRoles;\r\n\tfor ( auto pos : m_roles )\r\n\t{\r\n\t\tvRoles.append( pos.serialize() );\r\n\t}\r\n\tmilitary.insert( \"Roles\", vRoles );\r\n\r\n\tQVariantList vSquads;\r\n\tfor ( auto squad : m_squads )\r\n\t{\r\n\t\tvSquads.append( squad.serialize() );\r\n\t}\r\n\tGameState::squads = vSquads;\r\n\tmilitary.insert( \"Squads\", vSquads );\r\n\treturn military;\r\n}\r\n\r\nvoid MilitaryManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n}\r\n\r\nunsigned int MilitaryManager::addRole()\r\n{\r\n\tMilitaryRole pos;\r\n\r\n\t\r\n\r\n\tm_roles.insert( pos.id, pos );\r\n\r\n\treturn pos.id;\r\n}\r\n\r\nbool MilitaryManager::removeRole( unsigned int id )\r\n{\r\n\tif ( m_roles.contains( id ) )\r\n\t{\r\n\t\tm_roles.remove( id );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n\r\nvoid MilitaryManager::renameRole( unsigned int id, QString text )\r\n{\r\n\tif ( m_roles.contains( id ) )\r\n\t{\r\n\t\tm_roles[id].name = text;\r\n\t}\r\n}\r\n\r\nMilitaryRole* MilitaryManager::role( unsigned int id )\r\n{\r\n\tif ( m_roles.contains( id ) )\r\n\t{\r\n\t\treturn &m_roles[id];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQString MilitaryManager::roleName( unsigned int id )\r\n{\r\n\tif ( m_roles.contains( id ) )\r\n\t{\r\n\t\treturn m_roles[id].name;\r\n\t}\r\n\treturn \"Position doesn't exist.\";\r\n}\r\n\r\nvoid MilitaryManager::setArmorType( unsigned int roleID, QString slot, QString type, QString material )\r\n{\r\n\tif ( m_roles.contains( roleID ) )\r\n\t{\r\n\t\tauto& item = m_roles[roleID].uniform.parts[slot];\r\n\t\titem.type = type;\r\n\t\titem.item = DB::select3( \"ItemID\", \"Uniform_Slots\", \"ID\", slot, \"Type\", type ).toString();\r\n\t\titem.material = material;\r\n\t}\r\n}\r\n\r\nUniform* MilitaryManager::uniform( unsigned int roleID )\r\n{\r\n\tif ( m_roles.contains( roleID ) )\r\n\t{\r\n\t\treturn &m_roles[roleID].uniform;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nUniform MilitaryManager::uniformCopy( unsigned int roleID )\r\n{\r\n\tif ( m_roles.contains( roleID ) )\r\n\t{\r\n\t\treturn m_roles[roleID].uniform;\r\n\t}\r\n\treturn Uniform();\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nSquad* MilitaryManager::squad( unsigned int id )\r\n{\r\n\tfor( int i = 0; i < m_squads.size(); ++i )\r\n\t{\r\n\t\tif( m_squads[i].id == id )\r\n\t\t{\r\n\t\t\treturn &m_squads[i];\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nunsigned int MilitaryManager::addSquad()\r\n{\r\n\tSquad squad( g->m_creatureManager->types() );\r\n\r\n\tauto types = g->m_creatureManager->types();\r\n\tfor( auto type : types )\r\n\t{\r\n\t\tTargetPriority tp { type, MilAttitude::DEFEND };\r\n\t\tsquad.priorities.append( tp );\r\n\t}\r\n\r\n\tm_squads.insert( squad.id, squad );\r\n\treturn squad.id;\r\n}\r\n\r\nbool MilitaryManager::removeSquad( unsigned int id )\r\n{\r\n\tfor( int i = 0; i < m_squads.size(); ++i )\r\n\t{\r\n\t\tif( m_squads[i].id == id )\r\n\t\t{\r\n\t\t\tm_squads.removeAt( i );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid MilitaryManager::moveSquadUp( unsigned int id )\r\n{\r\n\tfor( int i = 1; i < m_squads.size(); ++i )\r\n\t{\r\n\t\tif( m_squads[i].id == id )\r\n\t\t{\r\n\t\t\tm_squads.move( i, i - 1 );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MilitaryManager::moveSquadDown( unsigned int id )\r\n{\r\n\tfor( int i = 0; i < m_squads.size() - 1; ++i )\r\n\t{\r\n\t\tif( m_squads[i].id == id )\r\n\t\t{\r\n\t\t\tm_squads.move( i, i + 1 );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MilitaryManager::removeGnomeFromOtherSquad( unsigned int squadID, unsigned int gnomeID )\r\n{\r\n\tif ( gnomeID )\r\n\t{\r\n\t\tfor ( auto& squad : m_squads )\r\n\t\t{\r\n\t\t\tif ( squad.id != squadID )\r\n\t\t\t{\r\n\t\t\t\tsquad.gnomes.removeAll( gnomeID );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MilitaryManager::renameSquad( unsigned int id, QString text )\r\n{\r\n\tfor( int i = 0; i < m_squads.size(); ++i )\r\n\t{\r\n\t\tif( m_squads[i].id == id )\r\n\t\t{\r\n\t\t\tm_squads[i].name = text;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MilitaryManager::addSquadTarget( unsigned int squadID, unsigned int target )\r\n{\r\n\t/*\r\n\tif ( m_squads.contains( squadID ) )\r\n\t{\r\n\t\tSquad& squad = m_squads[squadID];\r\n\t\tsquad.targetList.insert( target );\r\n\r\n\t\tauto targets = squad.targetList.values();\r\n\r\n\t}\r\n\t*/\r\n}\r\n\r\nvoid MilitaryManager::removeSquadTarget( unsigned int squadID, unsigned int target )\r\n{\r\n\t/*\r\n\tif ( m_squads.contains( squadID ) )\r\n\t{\r\n\t\tSquad& squad = m_squads[squadID];\r\n\t\tsquad.targetList.remove( target );\r\n\r\n\t\tauto targets = squad.targetList.values();\r\n\r\n\t}\r\n\t*/\r\n}\r\n\r\nQList<unsigned int> MilitaryManager::squadTargets( unsigned int id )\r\n{\r\n\t/*\r\n\tif ( m_squads.contains( id ) )\r\n\t{\r\n\t\treturn m_squads[id].targetList.values();\r\n\t}\r\n\t*/\r\n\treturn QList<unsigned int>();\r\n}\r\n\r\nSquad* MilitaryManager::getSquadForGnome( unsigned int gnomeID )\r\n{\r\n\tif ( m_gnome2Squad.contains( gnomeID ) )\r\n\t{\r\n\t\tunsigned int squadID = m_gnome2Squad.value( gnomeID );\r\n\t\tfor( int i = 0; i < m_squads.size(); ++i )\r\n\t\t{\r\n\t\t\tif( m_squads[i].id == squadID )\r\n\t\t\t{\r\n\t\t\t\treturn &m_squads[i];\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nUniform* MilitaryManager::getGnomeUniform( unsigned int gnomeID, Squad& squad )\r\n{\r\n\t\r\n\treturn nullptr;\r\n}\r\n\r\nUniform* MilitaryManager::getGnomeUniform( unsigned int gnomeID )\r\n{\r\n\tfor ( auto& squad : m_squads )\r\n\t{\r\n\t\tauto uni = getGnomeUniform( gnomeID, squad );\r\n\t\tif ( uni )\r\n\t\t{\r\n\t\t\treturn uni;\r\n\t\t}\r\n\t}\r\n\r\n\treturn nullptr;\r\n}\r\n\r\nvoid MilitaryManager::updateGnome( unsigned int gnomeID )\r\n{\r\n\t\r\n}\r\n\r\nvoid MilitaryManager::onGnomeDeath( unsigned int id )\r\n{\r\n}\r\n\r\nvoid MilitaryManager::onMonsterDeath( unsigned int id )\r\n{\r\n}\r\n\r\nvoid MilitaryManager::onAnimalDeath( unsigned int id )\r\n{\r\n}\r\n\r\nbool MilitaryManager::removeGnome( unsigned int gnomeID )\r\n{\r\n\tauto squad = getSquadForGnome( gnomeID );\r\n\tif( squad )\r\n\t{\r\n\t\tsquad->gnomes.removeAll( gnomeID );\r\n\t\tm_gnome2Squad.remove( gnomeID );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\t\r\nbool MilitaryManager::moveGnomeUp( unsigned int gnomeID )\r\n{\r\n\tauto squad = getSquadForGnome( gnomeID );\r\n\tif( squad )\r\n\t{\r\n\t\tfor( int i = 1; i < m_squads.size(); ++i )\r\n\t\t{\r\n\t\t\tif( m_squads[i].id == squad->id )\r\n\t\t\t{\r\n\t\t\t\tm_squads[i].gnomes.removeAll( gnomeID );\r\n\t\t\t\tm_squads[i-1].gnomes.append( gnomeID );\r\n\t\t\t\tm_gnome2Squad.insert( gnomeID, m_squads[i-1].id );\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 MilitaryManager::moveGnomeDown( unsigned int gnomeID )\r\n{\r\n\tauto squad = getSquadForGnome( gnomeID );\r\n\tif( squad )\r\n\t{\r\n\t\tfor( int i = 0; i < m_squads.size()-1; ++i )\r\n\t\t{\r\n\t\t\tif( m_squads[i].id == squad->id )\r\n\t\t\t{\r\n\t\t\t\tm_squads[i].gnomes.removeAll( gnomeID );\r\n\t\t\t\tm_squads[i+1].gnomes.append( gnomeID );\r\n\t\t\t\tm_gnome2Squad.insert( gnomeID, m_squads[i+1].id );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( m_squads.size() )\r\n\t{\r\n\t\tm_squads[0].gnomes.append( gnomeID );\r\n\t\tm_gnome2Squad.insert( gnomeID, m_squads[0].id );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid MilitaryManager::onSetAttitude( unsigned int squadID, QString type, MilAttitude attitude )\r\n{\r\n\tfor( auto& squad : m_squads )\r\n\t{\r\n\t\tif( squad.id == squadID )\r\n\t\t{\r\n\t\t\tfor( auto& prio : squad.priorities )\r\n\t\t\t{\r\n\t\t\t\tif( prio.type == type )\r\n\t\t\t\t{\r\n\t\t\t\t\tprio.attitude = attitude;\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\nbool MilitaryManager::movePrioUp( unsigned int squadID, QString type )\r\n{\r\n\tfor( auto& squad : m_squads )\r\n\t{\r\n\t\tif( squad.id == squadID )\r\n\t\t{\r\n\t\t\tfor( int i = 1; i < squad.priorities.size(); ++i )\r\n\t\t\t{\r\n\t\t\t\tif( squad.priorities[i].type == type )\r\n\t\t\t\t{\r\n\t\t\t\t\tsquad.priorities.move( i, i - 1 );\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\treturn false;\r\n}\r\n\r\nbool MilitaryManager::movePrioDown( unsigned int squadID, QString type )\r\n{\r\n\tfor( auto& squad : m_squads )\r\n\t{\r\n\t\tif( squad.id == squadID )\r\n\t\t{\r\n\t\t\tfor( int i = 0; i < squad.priorities.size() - 1; ++i )\r\n\t\t\t{\r\n\t\t\t\tif( squad.priorities[i].type == type )\r\n\t\t\t\t{\r\n\t\t\t\t\tsquad.priorities.move( i, i + 1 );\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\treturn false;\r\n}\r\n\r\nvoid MilitaryManager::setRoleCivilian( unsigned int roleID, bool value )\r\n{\r\n\tif ( m_roles.contains( roleID ) )\r\n\t{\r\n\t\tm_roles[roleID].isCivilian = value;\r\n\t}\r\n}\r\n\r\nbool MilitaryManager::roleIsCivilian( unsigned int roleID )\r\n{\r\n\tif ( m_roles.contains( roleID ) )\r\n\t{\r\n\t\treturn m_roles[roleID].isCivilian;\r\n\t}\r\n\treturn false;\r\n}\r\n"
  },
  {
    "path": "src/game/militarymanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/gamestate.h\"\r\n\r\n#include <QObject>\r\n#include <QRandomGenerator>\r\n#include <QSet>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\n\r\nenum class UniformItemQuality : unsigned char\r\n{\r\n\tANY,\r\n\tLOWEST,\r\n\tBEST\r\n};\r\n\r\nstruct UniformItem\r\n{\r\n\tQString type               = \"none\";\r\n\tQString item               = \"none\";\r\n\tQString material           = \"any\";\r\n\tUniformItemQuality quality = UniformItemQuality::ANY;\r\n\r\n\tQVariantMap serialize();\r\n\tUniformItem( const QVariantMap& in );\r\n\r\n\tUniformItem() {};\r\n};\r\n\r\nstruct Uniform\r\n{\r\n\tQString name = \"new uniform\";\r\n\tquint32 id   = GameState::createID();\r\n\r\n\tQMap<QString, UniformItem> parts;\r\n\r\n\tQVariantMap serialize();\r\n\tUniform( const QVariantMap& in );\r\n\tUniform();\r\n};\r\n\r\nstruct MilitaryRole\r\n{\r\n\tQString name = \"new role\";\r\n\tquint32 id   = GameState::createID();\r\n\r\n\tUniform uniform;\r\n\r\n\tbool isCivilian = false;\r\n\r\n\tbool maintainDist    = false;\r\n\tbool retreatBleeding = false;\r\n\r\n\tQVariantMap serialize();\r\n\tMilitaryRole( const QVariantMap& in );\r\n\r\n\tMilitaryRole() {};\r\n};\r\n\r\nenum class MilAttitude {\r\n\tFLEE,\r\n\tDEFEND,\r\n\tATTACK,\r\n\tHUNT\r\n};\r\nQ_DECLARE_METATYPE( MilAttitude )\r\n\r\nstruct TargetPriority {\r\n\tQString type;\r\n\tMilAttitude attitude;\r\n};\r\n\r\nstruct Squad\r\n{\r\n\tQString name = \"new squad\";\r\n\tquint32 id   = GameState::createID();\r\n\tQList<QString> types;\r\n\r\n\tQList<unsigned int> gnomes;\r\n\r\n\tQVariantMap serialize();\r\n\tSquad( QList<QString> tps, const QVariantMap& in );\r\n\r\n\tQList<TargetPriority> priorities;\r\n\r\n\tSquad( QList<QString> tps ) : types( tps ) {};\r\n\tSquad() {};\r\n};\r\nQ_DECLARE_METATYPE( Squad )\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nclass MilitaryManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( MilitaryManager )\r\npublic:\r\n\tMilitaryManager() = delete;\r\n\tMilitaryManager( Game* parent );\r\n\t~MilitaryManager();\r\n\r\n\tvoid init();\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tQVariantMap serialize();\r\n\r\n\tUniform* uniform( unsigned int roleID );\r\n\tUniform uniformCopy( unsigned int roleID );\r\n\r\n\tMilitaryRole* role( unsigned int id );\r\n\r\n\tSquad* squad( unsigned int id );\r\n\tSquad* getSquadForGnome( unsigned int gnomeID );\r\n\r\n\tQHash<unsigned int, MilitaryRole>& roles()\r\n\t{\r\n\t\treturn m_roles;\r\n\t}\r\n\tconst QList<Squad>& squads()\r\n\t{\r\n\t\treturn m_squads;\r\n\t}\r\n\r\n\tQString roleName( unsigned int id );\r\n\r\n\tUniform* getGnomeUniform( unsigned int gnomeID );\r\n\tUniform* getGnomeUniform( unsigned int gnomeID, Squad& squad );\r\n\r\n\tvoid updateGnome( unsigned int gnomeID );\r\n\r\n\tvoid save();\r\n\r\n\tbool roleIsCivilian( unsigned int roleID );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tint m_startIndex = 0;\r\n\r\n\tQHash<unsigned int, MilitaryRole> m_roles;\r\n\tQList<Squad> m_squads;\r\n\r\n\tQHash<unsigned int, unsigned int> m_gnome2Squad;\r\n\r\n\tvoid removeGnomeFromOtherSquad( unsigned int squadID, unsigned int gnomeID );\r\n\r\nsignals:\r\n\tvoid sendOverlayMessage( int id, QString text );\r\n\r\npublic slots:\r\n\tunsigned int addRole();\r\n\tbool removeRole( unsigned int id );\r\n\tvoid renameRole( unsigned int id, QString text );\r\n\r\n\tvoid setArmorType( unsigned int roleID, QString slot, QString type, QString material );\r\n\r\n\r\n\tunsigned int addSquad();\r\n\tbool removeSquad( unsigned int id );\r\n\tvoid renameSquad( unsigned int id, QString text );\r\n\tvoid addSquadTarget( unsigned int squadID, unsigned int target );\r\n\tvoid removeSquadTarget( unsigned int squadID, unsigned int target );\r\n\tQList<unsigned int> squadTargets( unsigned int squadID );\r\n\tvoid moveSquadUp( unsigned int id );\r\n\tvoid moveSquadDown( unsigned int id );\r\n\r\n\tbool removeGnome( unsigned int gnomeID );\r\n\tbool moveGnomeUp( unsigned int gnomeID );\r\n\tbool moveGnomeDown( unsigned int gnomeID );\r\n\r\n\r\n\tvoid onGnomeDeath( unsigned int id );\r\n\tvoid onMonsterDeath( unsigned int id );\r\n\tvoid onAnimalDeath( unsigned int id );\r\n\r\n\tvoid onSetAttitude( unsigned int squadID, QString type, MilAttitude attitude );\r\n\r\n\tbool movePrioUp( unsigned int squadID, QString type );\r\n\tbool movePrioDown( unsigned int squadID, QString type );\r\n\r\n\tvoid setRoleCivilian( unsigned int roleID, bool value );\r\n};\r\n"
  },
  {
    "path": "src/game/monster.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"monster.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/logger.h\"\r\n#include \"../base/priorityqueue.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nMonster::Monster( QString species, int level, Position& pos, Gender gender, Game* game ) :\r\n\tCreature( pos, species, gender, species, game )\r\n{\r\n\tm_type    = CreatureType::MONSTER;\r\n\r\n\tQVariantMap mvm = DB::selectRow( \"Monsters\", species );\r\n\r\n\tm_btName = mvm.value( \"BehaviorTree\" ).toString();\r\n\r\n\tupdateSprite();\r\n\r\n\tm_anatomy.init( \"Humanoid\", false );\r\n}\r\n\r\nMonster::Monster( QVariantMap in, Game* game ) :\r\n\tCreature( in, game ),\r\n\tm_level( in.value( \"Level\" ).toInt() )\r\n{\r\n\tm_type = CreatureType::MONSTER;\r\n\r\n\tupdateSprite();\r\n}\r\n\r\nvoid Monster::serialize( QVariantMap& out )\r\n{\r\n\t// animal\r\n\tout.insert( \"Level\", m_level );\r\n\tCreature::serialize( out );\r\n}\r\n\r\nMonster::~Monster()\r\n{\r\n}\r\n\r\nvoid Monster::init()\r\n{\r\n\tg->w()->insertCreatureAtPosition( m_position, m_id );\r\n\r\n\tinitTaskMap();\r\n\tloadBehaviorTree( m_btName );\r\n\tgenerateAggroList();\r\n\r\n\tif ( m_btBlackBoard.contains( \"State\" ) )\r\n\t{\r\n\t\tQVariantMap btm = m_btBlackBoard.value( \"State\" ).toMap();\r\n\t\tif ( m_behaviorTree )\r\n\t\t{\r\n\t\t\tm_behaviorTree->deserialize( btm );\r\n\t\t\tm_btBlackBoard.remove( \"State\" );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Monster::updateSprite()\r\n{\r\n\tauto parts = DB::selectRows( \"Creature_Parts\", m_species );\r\n\r\n\tQVariantMap ordered;\r\n\tfor ( auto pm : parts )\r\n\t{\r\n\t\tordered.insert( pm.value( \"Order\" ).toString(), pm );\r\n\t}\r\n\r\n\tQVariantMap randTemp;\r\n\r\n\tQVariantList def;\r\n\tfor ( auto vpm : ordered )\r\n\t{\r\n\t\tauto pm = vpm.toMap();\r\n\t\tif ( pm.value( \"BaseSprite\" ).toString().startsWith( \"#\" ) )\r\n\t\t{\r\n\t\t\tQString bsa = pm.value( \"BaseSprite\" ).toString();\r\n\t\t\tbsa.remove( 0, 1 );\r\n\t\t\tauto bsl = bsa.split( \"|\" );\r\n\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\t\tint rn = rand() % bsl.size();\r\n\t\t\trandTemp.insert( pm.value( \"Part\" ).toString() + \"Rand\", rn );\r\n\t\t\tpm.insert( \"BaseSprite\", bsl[rn] );\r\n\t\t}\r\n\t\tdef.append( pm );\r\n\t}\r\n\r\n\tauto partsBack = DB::selectRows( \"Creature_Parts\", m_species + \"Back\" );\r\n\r\n\tQVariantMap orderedBack;\r\n\tfor ( auto pm : partsBack )\r\n\t{\r\n\t\torderedBack.insert( pm.value( \"Order\" ).toString(), pm );\r\n\t}\r\n\r\n\tQVariantList defBack;\r\n\tfor ( auto vpm : orderedBack )\r\n\t{\r\n\t\tauto pm = vpm.toMap();\r\n\t\tif ( pm.value( \"BaseSprite\" ).toString().startsWith( \"#\" ) )\r\n\t\t{\r\n\t\t\tQString bsa = pm.value( \"BaseSprite\" ).toString();\r\n\t\t\tbsa.remove( 0, 1 );\r\n\t\t\tauto bsl = bsa.split( \"|\" );\r\n\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\t\tint rn = randTemp.value( pm.value( \"Part\" ).toString() + \"Rand\" ).toInt();\r\n\t\t\tpm.insert( \"BaseSprite\", bsl[rn] + \"Back\" );\r\n\t\t}\r\n\t\tdefBack.append( pm );\r\n\t}\r\n\r\n\tm_spriteID = g->sf()->setCreatureSprite( m_id, def, defBack, isDead() )->uID;\r\n}\r\n\r\nvoid Monster::updateMoveSpeed()\r\n{\r\n\t//TODO add monster values to movespeed table\r\n\t//int skill = getSkillLevel( \"Hauling\" );\r\n\tint speed   = 50; //DB::execQuery( \"SELECT Speed FROM MoveSpeed WHERE CREATURE = \\\"Gnome\\\" AND SkillLevel = \\\"\" + QString::number( skill ) + \"\\\"\" ).toInt();\r\n\tm_moveSpeed = qMax( 30, speed );\r\n}\r\n\r\nvoid Monster::initTaskMap()\r\n{\r\n\tusing namespace std::placeholders;\r\n\t//m_behaviors.insert( \"\", std::bind( &Monster::condition, this, _1 ) );\r\n\t//m_behaviors.insert( \"\", std::bind( &Monster::action, this, _1 ) );\r\n\tm_behaviors.insert( \"IsMale\", std::bind( &Monster::conditionIsMale, this, _1 ) );\r\n\tm_behaviors.insert( \"IsFemale\", std::bind( &Monster::conditionIsFemale, this, _1 ) );\r\n\tm_behaviors.insert( \"IsDay\", std::bind( &Monster::conditionIsDay, this, _1 ) );\r\n\tm_behaviors.insert( \"IsNight\", std::bind( &Monster::conditionIsNight, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"TargetAdjacent\", std::bind( &Monster::conditionTargetAdjacent, this, _1 ) );\r\n\r\n\tm_behaviors.insert( \"RandomMove\", std::bind( &Monster::actionRandomMove, this, _1 ) );\r\n\tm_behaviors.insert( \"Move\", std::bind( &Monster::actionMove, this, _1 ) );\r\n\tm_behaviors.insert( \"GetTarget\", std::bind( &Monster::actionGetTarget, this, _1 ) );\r\n\tm_behaviors.insert( \"AttackTarget\", std::bind( &Monster::actionAttackTarget, this, _1 ) );\r\n}\r\n\r\nvoid Monster::generateAggroList()\r\n{\r\n\tm_aggroList.clear();\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\tfor ( auto& gn : g->gm()->gnomes() )\r\n\t{\r\n\t\tif ( !gn->isOnMission() )\r\n\t\t{\r\n\t\t\tAggroEntry ae { rand() % 100, gn->id() };\r\n\t\t\tm_aggroList.append( ae );\r\n\t\t}\r\n\t}\r\n\tstd::sort( m_aggroList.begin(), m_aggroList.end() );\r\n}\r\n\r\nCreatureTickResult Monster::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tprocessCooldowns( tickNumber );\r\n\r\n\tm_anatomy.setFluidLevelonTile( g->w()->fluidLevel( m_position ) );\r\n\r\n\tif ( m_anatomy.statusChanged() )\r\n\t{\r\n\t\tauto status = m_anatomy.status();\r\n\t\tif ( status & AS_DEAD )\r\n\t\t{\r\n\t\t\tGlobal::logger().log( LogType::COMBAT, \"The \" + m_name + \" died. Bummer!\", m_id );\r\n\t\t\tdie();\r\n\t\t\t// TODO check for other statuses\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_toDestroy )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::TODESTROY;\r\n\t}\r\n\tif ( isDead() )\r\n\t{\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::DEAD;\r\n\t}\r\n\r\n\tPosition oldPos = m_position;\r\n\r\n\tif ( m_followID && !m_followPosition.isZero() && m_position != m_followPosition )\r\n\t{\r\n\t\tm_position = m_followPosition;\r\n\t\tmove( oldPos );\r\n\t\tm_lastOnTick = tickNumber;\r\n\t\treturn CreatureTickResult::OK;\r\n\t}\r\n\r\n\tsetThoughtBubble( \"\" );\r\n\r\n\tif ( m_aggroList.isEmpty() )\r\n\t{\r\n\t\tgenerateAggroList();\r\n\t}\r\n\r\n\tif ( m_behaviorTree )\r\n\t{\r\n\t\tm_behaviorTree->tick();\r\n\t}\r\n\r\n\tmove( oldPos );\r\n\r\n\tm_lastOnTick = tickNumber;\r\n\r\n\treturn CreatureTickResult::OK;\r\n}\r\n\r\nBT_RESULT Monster::actionMove( bool halt )\r\n{\r\n\tif ( halt )\r\n\t{\r\n\t\tm_currentPath.clear();\r\n\t\treturn BT_RESULT::IDLE;\r\n\t}\r\n\r\n\t// monster has a path, move on path and return\r\n\tif ( !m_currentPath.empty() )\r\n\t{\r\n\t\tif ( m_currentAttackTarget )\r\n\t\t{\r\n\t\t\tif ( conditionTargetAdjacent( false ) == BT_RESULT::SUCCESS )\r\n\t\t\t{\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t\t}\r\n\r\n\t\t\tif ( conditionTargetPositionValid( false ) == BT_RESULT::FAILURE )\r\n\t\t\t{\r\n\t\t\t\tm_currentPath.clear();\r\n\t\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !moveOnPath() )\r\n\t\t{\r\n\t\t\tm_currentPath.clear();\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\r\n\tPosition targetPos = currentTarget();\r\n\r\n\t// check if we are already on the tile\r\n\tif ( m_position == targetPos )\r\n\t{\r\n\t\treturn BT_RESULT::SUCCESS;\r\n\t}\r\n\r\n\tPathFinderResult pfr = g->pf()->getPath( m_id, m_position, targetPos, m_ignoreNoPass, m_currentPath );\r\n\tswitch ( pfr )\r\n\t{\r\n\t\tcase PathFinderResult::NoConnection:\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\tcase PathFinderResult::Running:\r\n\t\tcase PathFinderResult::FoundPath:\r\n\t\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\treturn BT_RESULT::RUNNING;\r\n}\r\n\r\nBT_RESULT Monster::actionAttackTarget( bool halt )\r\n{\r\n\tCreature* creature = g->gm()->gnome( m_currentAttackTarget );\r\n\tif ( creature && !creature->isDead() )\r\n\t{\r\n\t\tm_facing = getFacing( m_position, creature->getPos() );\r\n\r\n\t\tif ( m_rightHandCooldown <= 0 )\r\n\t\t{\r\n\t\t\tGlobal::logger().log( LogType::COMBAT, \"The goblin attacks \" + creature->name(), m_id );\r\n\t\t\tint skill    = getSkillLevel( \"Unarmed\" );\r\n\t\t\tint strength = attribute( \"Str\" );\r\n\t\t\tcreature->attack( DT_BLUNT, m_anatomy.randomAttackHeight(), skill, qMin( 5, strength ), m_position, m_id );\r\n\t\t\tm_rightHandCooldown = qMax( 5, 20 - m_rightHandAttackSkill );\r\n\t\t}\r\n\t\treturn BT_RESULT::RUNNING;\r\n\t}\r\n\tm_currentAttackTarget = 0;\r\n\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nBT_RESULT Monster::actionGetTarget( bool halt )\r\n{\r\n\tif ( m_aggroList.size() )\r\n\t{\r\n\t\tunsigned int minDistance = std::numeric_limits<unsigned int>::max();\r\n\t\tconst auto myPos         = getPos();\r\n\t\tconst Creature* selectedTarget = nullptr;\r\n\t\tfor ( auto it = m_aggroList.begin(); it != m_aggroList.end(); )\r\n\t\t{\r\n\t\t\tconst Creature* creature = g->gm()->gnome( it->id );\r\n\t\t\tif ( creature && !creature->isDead() )\r\n\t\t\t{\r\n\t\t\t\tauto otherPos = creature->getPos();\r\n\t\t\t\tif ( g->w()->regionMap().checkConnectedRegions( myPos, otherPos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst unsigned int dist = myPos.distSquare( otherPos );\r\n\t\t\t\t\tif ( dist < minDistance )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tselectedTarget = creature;\r\n\t\t\t\t\t\tminDistance    = dist;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t++it;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tit = m_aggroList.erase( it );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( selectedTarget )\r\n\t\t{\r\n\t\t\tm_currentAttackTarget = selectedTarget->id();\r\n\t\t\tsetCurrentTarget( selectedTarget->getPos() );\r\n\t\t\treturn BT_RESULT::SUCCESS;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\treturn BT_RESULT::FAILURE;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//TODO even though aggro list is empty, check for other threats around\r\n\t}\r\n\treturn BT_RESULT::FAILURE;\r\n}\r\n\r\nbool Monster::attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID )\r\n{\r\n\t// from which side is the attack coming\r\n\tAnatomySide ds = AS_CENTER;\r\n\tswitch ( m_facing )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\tif ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_FRONT;\r\n\t\t\telse if ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_BACK;\r\n\t\t\tif ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_RIGHT );\r\n\t\t\telse if ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_LEFT );\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\tif ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_LEFT;\r\n\t\t\telse if ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_RIGHT;\r\n\t\t\tif ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_FRONT );\r\n\t\t\telse if ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_BACK );\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tif ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_FRONT;\r\n\t\t\telse if ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_BACK;\r\n\t\t\tif ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_RIGHT );\r\n\t\t\telse if ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_LEFT );\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\tif ( m_position.x > sourcePos.x )\r\n\t\t\t\tds = AS_LEFT;\r\n\t\t\telse if ( m_position.x < sourcePos.x )\r\n\t\t\t\tds = AS_RIGHT;\r\n\t\t\tif ( m_position.y > sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_FRONT );\r\n\t\t\telse if ( m_position.y < sourcePos.y )\r\n\t\t\t\tds = AnatomySide( ds | AS_BACK );\r\n\t\t\tbreak;\r\n\t}\r\n\t// attacker skill vs our dodge or block chance\r\n\r\n\tint dodge = getSkillLevel( \"Dodge\" );\r\n\tif ( ds & AS_BACK )\r\n\t{\r\n\t\tskill *= 1.5;\r\n\t}\r\n\r\n\tbool hit = skill >= dodge;\r\n\tif ( dodge > skill )\r\n\t{\r\n\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\tint diff = dodge - skill;\r\n\t\tdiff     = qMax( 5, 20 - diff );\r\n\t\thit |= rand() % 100 > diff;\r\n\t}\r\n\r\n\tif ( hit )\r\n\t{\r\n\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" took \" + QString::number( strength ) + \" damage.\", m_id );\r\n\t\tm_anatomy.damage( &m_equipment, dt, da, ds, strength );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tGlobal::logger().log( LogType::COMBAT, m_name + \" dogded the attack. Skill:\" + QString::number( skill ) + \" Dodge: \" + QString::number( dodge ), m_id );\r\n\t}\r\n\r\n\tbool aeExists = false;\r\n\tfor ( auto& ae : m_aggroList )\r\n\t{\r\n\t\tif ( ae.id == attackerID )\r\n\t\t{\r\n\t\t\tae.aggro += strength;\r\n\t\t\taeExists = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( !aeExists )\r\n\t{\r\n\t\tAggroEntry newAE { strength, attackerID };\r\n\t\tm_aggroList.append( newAE );\r\n\t}\r\n\r\n\treturn true;\r\n}"
  },
  {
    "path": "src/game/monster.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/creature.h\"\r\n\r\nclass Monster : public Creature\r\n{\r\n\tfriend class MonsterWidget;\r\n\r\npublic:\r\n\tMonster( QString species, int level, Position& pos, Gender gender, Game* game );\r\n\tMonster( QVariantMap in, Game* game );\r\n\t~Monster();\r\n\r\n\tvirtual void init();\r\n\r\n\tvirtual void updateSprite();\r\n\r\n\tvirtual void serialize( QVariantMap& out );\r\n\r\n\tCreatureTickResult onTick( quint64 tick, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tvirtual void updateMoveSpeed();\r\n\r\n\tbool attack( DamageType dt, AnatomyHeight da, int skill, int strength, Position sourcePos, unsigned int attackerID );\r\n\r\nprivate:\r\n\tvoid initTaskMap();\r\n\r\n\tvoid generateAggroList();\r\n\r\n\tBT_RESULT actionMove( bool halt );\r\n\tBT_RESULT actionAttackTarget( bool halt );\r\n\tBT_RESULT actionGetTarget( bool halt );\r\n\r\n\t\r\n\tint m_level;\r\n};\r\n"
  },
  {
    "path": "src/game/neighbormanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"neighbormanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/eventmanager.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n\r\nNeighborManager::NeighborManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tm_kingdoms.clear();\r\n\r\n\tif ( GameState::peaceful )\r\n\t{\r\n\t\tfor ( int i = 0; i < 10; ++i )\r\n\t\t{\r\n\t\t\taddRandomKingdom( KingdomType::GNOME );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor ( int i = 0; i < 5; ++i )\r\n\t\t{\r\n\t\t\taddRandomKingdom( KingdomType::GNOME );\r\n\t\t}\r\n\r\n\t\tfor ( int i = 0; i < 5; ++i )\r\n\t\t{\r\n\t\t\taddRandomKingdom( KingdomType::GOBLIN );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nNeighborManager::~NeighborManager()\r\n{\r\n}\r\n\r\nQVariantMap NeighborKingdom::serialize()\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"ID\", id );\r\n\tout.insert( \"Discovered\", discovered );\r\n\tout.insert( \"DiscoverMission\", discoverMission );\r\n\tout.insert( \"Distance\", distance );\r\n\tout.insert( \"Name\", name );\r\n\tout.insert( \"Type\", (int)type );\r\n\tout.insert( \"Attitude\", attitude );\r\n\tout.insert( \"Wealth\", (int)wealth );\r\n\tout.insert( \"Economy\", (int)economy );\r\n\tout.insert( \"Military\", (int)military );\r\n\tout.insert( \"NextRaid\", nextRaid );\r\n\tout.insert( \"NextTrader\", nextTrader );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid NeighborKingdom::deserialize( QVariantMap in )\r\n{\r\n\tid              = in.value( \"ID\" ).toUInt();\r\n\tdiscovered      = in.value( \"Discovered\" ).toBool();\r\n\tdiscoverMission = in.value( \"DiscoverMission\" ).toBool();\r\n\tdistance        = in.value( \"Distance\" ).toInt();\r\n\tname            = in.value( \"Name\" ).toString();\r\n\ttype            = (KingdomType)in.value( \"Type\" ).toInt();\r\n\tattitude        = in.value( \"Attitude\" ).toFloat();\r\n\twealth          = (KingdomWealth)in.value( \"Wealth\" ).toInt();\r\n\teconomy         = (KingdomEconomy)in.value( \"Economy\" ).toInt();\r\n\tmilitary        = (KingdomMilitary)in.value( \"Military\" ).toInt();\r\n\tnextRaid        = in.value( \"NextRaid\" ).value<quint64>();\r\n\tnextTrader      = in.value( \"NextTrader\" ).value<quint64>();\r\n}\r\n\r\nQVariantList NeighborManager::serialize()\r\n{\r\n\tQVariantList out;\r\n\r\n\tfor ( auto neigh : m_kingdoms )\r\n\t{\r\n\t\tout.append( neigh.serialize() );\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid NeighborManager::deserialize( QVariantList in )\r\n{\r\n\tm_kingdoms.clear();\r\n\tfor ( auto vk : in )\r\n\t{\r\n\t\tNeighborKingdom nk;\r\n\t\tnk.deserialize( vk.toMap() );\r\n\t\tm_kingdoms.append( nk );\r\n\t}\r\n}\r\n\r\nvoid NeighborManager::addRandomKingdom( KingdomType type )\r\n{\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\tNeighborKingdom nk;\r\n\tnk.id = GameState::createID();\r\n\r\n\tnk.discovered = false;\r\n\tnk.name       = S::gi().randomKingdomName();\r\n\tnk.type       = type;\r\n\tnk.distance   = rand() % 180 + 72;\r\n\tnk.wealth     = ( KingdomWealth )( rand() % ( (int)KingdomWealth::VERYRICH + 1 ) );\r\n\tnk.economy    = ( KingdomEconomy )( rand() % ( (int)KingdomEconomy::ANIMALBREEDING + 1 ) );\r\n\tnk.military   = ( KingdomMilitary )( rand() % ( (int)KingdomMilitary::VERYSTRONG + 1 ) );\r\n\r\n\tnk.attitude = 0;\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase KingdomType::GNOME:\r\n\t\t\tnk.attitude = rand() % 100;\r\n\t\t\tbreak;\r\n\t\tcase KingdomType::GOBLIN:\r\n\t\t\tnk.attitude = -( rand() % 60 + 40 );\r\n\t\t\tnk.nextRaid = GameState::tick + 60 * Global::util->ticksPerDayRandomized( 10 );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tm_kingdoms.append( nk );\r\n}\r\n\r\nvoid NeighborManager::onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged )\r\n{\r\n\tfor ( auto& kingdom : m_kingdoms )\r\n\t{\r\n\t\tif ( kingdom.type == KingdomType::GOBLIN && GameState::tick >= kingdom.nextRaid )\r\n\t\t{\r\n\t\t\tg->m_eventManager->addRaidEvent( kingdom );\r\n\t\t\tkingdom.nextRaid = GameState::tick + Global::util->ticksPerDayRandomized( 10 ) * Global::util->daysPerSeason * 4;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQList<NeighborKingdom>& NeighborManager::kingdoms()\r\n{\r\n\treturn m_kingdoms;\r\n}\r\n\r\nint NeighborManager::countDiscovered()\r\n{\r\n\tint out = 0;\r\n\tfor ( auto k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.discovered )\r\n\t\t\t++out;\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nvoid NeighborManager::discoverKingdom( unsigned int id )\r\n{\r\n\tfor ( auto& k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.id == id )\r\n\t\t{\r\n\t\t\tk.discovered = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nint NeighborManager::distance( unsigned int kingdomID )\r\n{\r\n\tfor ( auto& k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.id == kingdomID )\r\n\t\t{\r\n\t\t\treturn k.distance;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid NeighborManager::spy( Mission* mission )\r\n{\r\n\tauto kingdomID = mission->target;\r\n\tfor ( auto& k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.id == kingdomID )\r\n\t\t{\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\t\t\tint chance   = 75;\r\n\t\t\tbool success = ( rand() % 100 ) < chance;\r\n\t\t\tif ( success )\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"spy success\";\r\n\t\t\t\tmission->result.insert( \"Success\", true );\r\n\t\t\t\tmission->result.insert( \"NextRaid\", k.nextRaid );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"spy failure\";\r\n\t\t\t\tmission->result.insert( \"Success\", false );\r\n\t\t\t\tk.attitude -= 10;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NeighborManager::sabotage( Mission* mission )\r\n{\r\n\tauto kingdomID = mission->target;\r\n\tfor ( auto& k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.id == kingdomID )\r\n\t\t{\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\t\t\tint chance = 50;\r\n\t\t\tchance += ( mission->gnomes.size() - 2 ) * 10;\r\n\t\t\tbool success = ( rand() % 100 ) < chance;\r\n\r\n\t\t\tif ( success )\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"sabotage success\";\r\n\t\t\t\tmission->result.insert( \"Success\", true );\r\n\t\t\t\tint delay = qMax( 2, rand() % 6 );\r\n\t\t\t\tmission->result.insert( \"Delay\", delay );\r\n\r\n\t\t\t\tk.nextRaid += delay * Global::util->ticksPerDay;\r\n\t\t\t\tk.attitude -= 20;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"sabotage failure\";\r\n\t\t\t\tmission->result.insert( \"Success\", false );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NeighborManager::raid( Mission* mission )\r\n{\r\n\tauto kingdomID = mission->target;\r\n\tfor ( auto& k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.id == kingdomID )\r\n\t\t{\r\n\t\t\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\t\t\tint chance = 50;\r\n\t\t\tchance += ( mission->gnomes.size() - 2 ) * 10;\r\n\t\t\tbool success = ( rand() % 100 ) < chance;\r\n\r\n\t\t\tif ( success )\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"raid success\";\r\n\t\t\t\tmission->result.insert( \"Success\", true );\r\n\r\n\t\t\t\tk.attitude -= 20;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tqDebug() << \"raid failure\";\r\n\t\t\t\tk.attitude -= 10;\r\n\t\t\t\tmission->result.insert( \"Success\", false );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NeighborManager::emissary( Mission* mission )\r\n{\r\n\tauto kingdomID = mission->target;\r\n\tfor ( auto& k : m_kingdoms )\r\n\t{\r\n\t\tif ( k.id == kingdomID )\r\n\t\t{\r\n\r\n\t\t\tswitch ( mission->action )\r\n\t\t\t{\r\n\t\t\t\tcase MissionAction::IMPROVE:\r\n\t\t\t\t\tk.attitude += 10;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase MissionAction::INSULT:\r\n\t\t\t\t\tk.attitude -= 20;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase MissionAction::INVITE_TRADER:\r\n\t\t\t\t\tk.nextTrader = GameState::tick + 2 * Global::util->ticksPerDayRandomized( 50 );\r\n\t\t\t\t\tg->m_eventManager->addTraderEvent( k );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase MissionAction::INVITE_AMBASSADOR:\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tmission->result.insert( \"Success\", true );\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/game/neighbormanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QMap>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\nstruct Mission;\r\n\r\nenum class KingdomType\r\n{\r\n\tNONE,\r\n\tGNOME,\r\n\tGOBLIN,\r\n\tOTHER\r\n};\r\n\r\nenum class KingdomWealth\r\n{\r\n\tVERYPOOR,\r\n\tPOOR,\r\n\tAVERAGE,\r\n\tRICH,\r\n\tVERYRICH\r\n};\r\n\r\nenum class KingdomEconomy\r\n{\r\n\tTRADING,\r\n\tFARMING,\r\n\tLOGGING,\r\n\tMINING,\r\n\tANIMALBREEDING\r\n};\r\n\r\nenum class KingdomMilitary\r\n{\r\n\tVERYWEAK,\r\n\tWEAK,\r\n\tAVERAGE,\r\n\tSTRONG,\r\n\tVERYSTRONG\r\n};\r\n\r\nstruct NeighborKingdom\r\n{\r\n\tunsigned int id          = 0;\r\n\tbool discovered          = false;\r\n\tbool discoverMission     = false;\r\n\tint distance             = 0; // travel time in hours\r\n\tQString name             = \"undiscovered\";\r\n\tKingdomType type         = KingdomType::NONE;\r\n\tfloat attitude           = 0;\r\n\tKingdomWealth wealth     = KingdomWealth::AVERAGE;\r\n\tKingdomEconomy economy   = KingdomEconomy::FARMING;\r\n\tKingdomMilitary military = KingdomMilitary::AVERAGE;\r\n\tquint64 nextRaid         = 0;\r\n\tquint64 nextTrader       = 0;\r\n\r\n\tQVariantMap serialize();\r\n\tvoid deserialize( QVariantMap in );\r\n};\r\n\r\nclass NeighborManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( NeighborManager )\r\npublic:\r\n\tNeighborManager( Game* parent );\r\n\t~NeighborManager();\r\n\r\n\tvoid addRandomKingdom( KingdomType type );\r\n\r\n\tQVariantList serialize();\r\n\tvoid deserialize( QVariantList in );\r\n\r\n\tvoid onTick( quint64 tickNumber, bool seasonChanged, bool dayChanged, bool hourChanged, bool minuteChanged );\r\n\r\n\tQList<NeighborKingdom>& kingdoms();\r\n\r\n\tint countDiscovered();\r\n\r\n\tvoid discoverKingdom( unsigned int id );\r\n\r\n\tint distance( unsigned int kingdomID );\r\n\r\n\tvoid spy( Mission* mission );\r\n\r\n\tvoid sabotage( Mission* mission );\r\n\r\n\tvoid raid( Mission* mission );\r\n\r\n\tvoid emissary( Mission* mission );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQList<NeighborKingdom> m_kingdoms;\r\n\r\nsignals:\r\n\r\npublic slots:\r\n};\r\n"
  },
  {
    "path": "src/game/newgamesettings.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"newgamesettings.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/io.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n#include <QStandardPaths>\r\n\r\n#include <random>\r\n\r\nNewGameSettings::NewGameSettings( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tloadEmbarkMap();\r\n\tloadPresets();\r\n\r\n\tsetRandomSeed();\r\n\tsetRandomName();\r\n}\r\n\r\nNewGameSettings::~NewGameSettings()\r\n{\r\n}\r\n\r\nvoid NewGameSettings::save()\r\n{\r\n\tQVariantMap embarkMap;\r\n\r\n\tembarkMap.insert( \"dimX\", m_worldSize );\r\n    embarkMap.insert( \"dimY\", m_worldSize );\r\n    embarkMap.insert( \"dimZ\", m_zLevels );\r\n    embarkMap.insert( \"flatness\", m_flatness );\r\n    embarkMap.insert( \"groundLevel\", m_ground );\r\n    //embarkMap.insert( \"hasOcean\", m_oc\r\n    embarkMap.insert( \"maxPerType\", m_maxPerType );\r\n    embarkMap.insert( \"numAnimals\", m_numWildAnimals );\r\n    embarkMap.insert( \"numGnomes\", m_numGnomes );\r\n    embarkMap.insert( \"oceanSize\", m_oceanSize );\r\n    embarkMap.insert( \"peaceful\", m_isPeaceful );\r\n    embarkMap.insert( \"plantDensity\", m_plantDensity );\r\n    embarkMap.insert( \"riverSize\", m_riverSize );\r\n    embarkMap.insert( \"rivers\", m_rivers );\r\n    embarkMap.insert( \"seed\", m_seed );\r\n\tembarkMap.insert( \"startingZone\", m_startZone );\r\n    embarkMap.insert( \"treeDensity\", m_treeDensity );\r\n\r\n\tQVariantMap allowedAnimals;\r\n\tQVariantMap allowedPlants;\r\n\tQVariantMap allowedTrees;\r\n\r\n\tfor( const auto& ci : m_checkableItems )\r\n\t{\r\n\t\tif( ci.type == \"Animal\" )\r\n\t\t{\r\n\t\t\tallowedAnimals.insert( ci.sid, ci.max );\r\n\t\t}\r\n\t\telse if( ci.type == \"Plant\" )\r\n\t\t{\r\n\t\t\tallowedPlants.insert( ci.sid, ci.isChecked );\r\n\t\t}\r\n\t\telse if( ci.type == \"Tree\" )\r\n\t\t{\r\n\t\t\tallowedTrees.insert( ci.sid, ci.isChecked );\r\n\t\t}\r\n\t}\r\n\tembarkMap.insert( \"allowedAnimals\", allowedAnimals );\r\n\tembarkMap.insert( \"allowedPlants\", allowedPlants );\r\n\tembarkMap.insert( \"allowedTrees\", allowedTrees );\r\n\r\n\r\n\tQVariantList startItems;\r\n\tcollectStartItems( startItems );\r\n\r\n\tembarkMap.insert( \"startingItems\", startItems );\r\n\r\n\tQJsonDocument sd = QJsonDocument::fromVariant( embarkMap );\r\n\tIO::saveFile( IO::getDataFolder() + \"/settings/newgame.json\", sd );\r\n\r\n\tsavePreset( startItems );\r\n}\r\n\r\nvoid NewGameSettings::collectStartItems( QVariantList& sil )\r\n{\r\n\tfor( const auto& si : m_startingItems )\r\n\t{\r\n\t\tQVariantMap sim;\r\n\t\tif( si.mat2.isEmpty() )\r\n\t\t{\r\n\t\t\tsim.insert( \"Amount\", si.amount );\r\n\t\t\tsim.insert( \"ItemID\", si.itemSID );\r\n\t\t\tsim.insert( \"MaterialID\", si.mat1 );\r\n\t\t\tsim.insert( \"Type\", \"Item\" );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Items_Components\", si.itemSID );\r\n\t\t\tif( rows.size() > 1 )\r\n\t\t\t{\r\n\t\t\t\tsim.insert( \"Amount\", si.amount );\r\n\t\t\t\tsim.insert( \"ItemID\", si.itemSID );\r\n\r\n\t\t\t\tQVariantList comps;\r\n\t\t\t\tQVariantMap cm1;\r\n\t\t\t\tQVariantMap cm2;\r\n\t\t\t\r\n\t\t\t\tcm1.insert( \"ItemID\", rows[0].value( \"ItemID\" ).toString() );\r\n\t\t\t\tcm1.insert( \"MaterialID\", si.mat1 );\r\n\t\t\t\tcm2.insert( \"ItemID\", rows[1].value( \"ItemID\" ).toString() );\r\n\t\t\t\tcm2.insert( \"MaterialID\", si.mat2 );\r\n\r\n\t\t\t\tcomps.append( cm1 );\r\n\t\t\t\tcomps.append( cm2 );\r\n\t\t\t\tsim.insert( \"Components\", comps );\r\n\t\t\t\tsim.insert( \"Type\", \"CombinedItem\" );\r\n\t\t\t}\r\n\t\t}\r\n\t\tsil.append( sim );\r\n\t}\r\n\tfor( const auto& si : m_startingAnimals )\r\n\t{\r\n\t\tQVariantMap sim;\r\n\t\tsim.insert( \"Amount\", si.amount );\r\n\t\tsim.insert( \"ItemID\", si.type );\r\n\t\tsim.insert( \"Gender\", si.gender );\r\n\t\tsim.insert( \"Type\", \"Animal\" );\r\n\t\tsil.append( sim );\r\n\t}\r\n}\r\n\r\nvoid NewGameSettings::loadEmbarkMap()\r\n{\r\n\tm_checkableItems.clear();\r\n\r\n\tQJsonDocument sd;\r\n\tif ( !IO::loadFile( IO::getDataFolder() + \"/settings/newgame.json\", sd ) )\r\n\t{\r\n\t\t// if it doesn't exist get from /content/JSON\r\n\t\tif ( IO::loadFile( Global::cfg->get( \"dataPath\" ).toString() + \"/JSON/newgame.json\", sd ) )\r\n\t\t{\r\n\t\t\tIO::saveFile( IO::getDataFolder() + \"/settings/newgame.json\", sd );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tqDebug() << \"Unable to find new game config!\";\r\n\t\t\tabort();\r\n\t\t}\r\n\t}\r\n\tauto embarkMap = sd.toVariant().toMap();\r\n\r\n\tQVariantList out;\r\n\tQStringList trees = DB::ids( \"Plants\", \"Type\", \"Tree\" );\r\n\r\n\tfor ( auto id : trees )\r\n\t{\r\n\t\tCheckableItem ci { id, S::s( \"$ItemName_\" + id ), \"Tree\", embarkMap.value( \"allowedTrees\" ).toMap().value( id ).toBool(), 0 };\r\n\t\tm_checkableItems.insert( id, ci );\r\n\t}\r\n\r\n\tQStringList allplants = DB::ids( \"Plants\", \"Type\", \"Plant\" );\r\n\tallplants.sort();\r\n\tfor ( auto id : allplants )\r\n\t{\r\n\t\tif ( DB::select( \"AllowInWild\", \"Plants\", id ).toBool() )\r\n\t\t{\r\n\t\t\tCheckableItem ci { id, S::s( \"$MaterialName_\" + id ), \"Plant\", embarkMap.value( \"allowedPlants\" ).toMap().value( id ).toBool(), 0 };\r\n\t\t\tm_checkableItems.insert( id, ci );\r\n\t\t}\r\n\t}\r\n\r\n\tQStringList allAnimals = DB::ids( \"Animals\" );\r\n\tallAnimals.sort();\r\n\tauto allowedAnimals = embarkMap.value( \"allowedAnimals\" ).toMap();\r\n\r\n\tfor ( auto id : allAnimals )\r\n\t{\r\n\t\tif ( DB::select( \"AllowInWild\", \"Animals\", id ).toBool() && DB::select( \"Biome\", \"Animals\", id ).toString().isEmpty() )\r\n\t\t{\r\n\t\t\tCheckableItem ci { id, S::s( \"$CreatureName_\" + id ), \"Animal\", allowedAnimals.value( id ).toBool(), allowedAnimals.value( id ).toInt() };\r\n\t\t\tm_checkableItems.insert( id, ci );\r\n\t\t}\r\n\t}\r\n\r\n\tauto sil = embarkMap.value( \"startingItems\" ).toList();\r\n\tsetStartingItems( sil );\r\n\r\n\t// QString m_kingdomName not in embark map, we want to change it on every embark\r\n\tm_seed = embarkMap.value( \"seed\" ).toString();\r\n\r\n\tm_worldSize    = embarkMap.value( \"dimX\" ).toInt();\r\n\tm_zLevels      = embarkMap.value( \"dimZ\" ).toInt();\r\n\tm_ground       = embarkMap.value( \"groundLevel\" ).toInt();\r\n\tm_flatness     = embarkMap.value( \"flatness\" ).toInt();\r\n\tm_oceanSize    = embarkMap.value( \"oceanSize\" ).toInt();\r\n\tm_rivers       = embarkMap.value( \"rivers\" ).toInt();\r\n\tm_riverSize    = embarkMap.value( \"riverSize\" ).toInt();\r\n\tm_numGnomes    = embarkMap.value( \"numGnomes\" ).toInt();\r\n\tm_startZone    = embarkMap.value( \"startingZone\" ).toInt();\r\n\tm_treeDensity  = embarkMap.value( \"treeDensity\" ).toInt();\r\n\tm_plantDensity = embarkMap.value( \"plantDensity\" ).toInt();\r\n\tm_isPeaceful   = embarkMap.value( \"peaceful\" ).toBool();\r\n\r\n\tm_maxPerType     = embarkMap.value( \"maxPerType\" ).toInt();\r\n\tm_numWildAnimals = embarkMap.value( \"numAnimals\" ).toInt();\r\n}\r\n\r\nvoid NewGameSettings::setRandomName()\r\n{\r\n\tm_kingdomName = S::gi().randomKingdomName();\r\n}\r\n\r\nvoid NewGameSettings::setRandomSeed()\r\n{\r\n\tstd::random_device rd;                                // only used once to initialise (seed) engine\r\n\tstd::mt19937 rng( rd() );                             // random-number engine used (Mersenne-Twister in this case)\r\n\tstd::uniform_int_distribution<int> uni( 0, INT_MAX ); // guaranteed unbiased\r\n\r\n\tauto random_integer = uni( rng );\r\n\r\n\tm_seed = QString::number( random_integer );\r\n}\r\n\r\nbool NewGameSettings::setKingdomName( QString value )\r\n{\r\n\tif ( m_kingdomName != value )\r\n\t{\r\n\t\tm_kingdomName = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setSeed( QString value )\r\n{\r\n\tif ( m_seed != value )\r\n\t{\r\n\t\tm_seed = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setWorldSize( int value )\r\n{\r\n\tif ( m_worldSize != value )\r\n\t{\r\n\t\tm_worldSize = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setZLevels( int value )\r\n{\r\n\tif ( m_zLevels != value )\r\n\t{\r\n\t\tm_zLevels = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setGround( int value )\r\n{\r\n\tif ( m_ground != value )\r\n\t{\r\n\t\tm_ground = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setFlatness( int value )\r\n{\r\n\tif ( m_flatness != value )\r\n\t{\r\n\t\tm_flatness = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setOceanSize( int value )\r\n{\r\n\tif ( m_oceanSize != value )\r\n\t{\r\n\t\tm_oceanSize = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setRivers( int value )\r\n{\r\n\tif ( m_rivers != value )\r\n\t{\r\n\t\tm_rivers = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setRiverSize( int value )\r\n{\r\n\tif ( m_riverSize != value )\r\n\t{\r\n\t\tm_riverSize = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\nbool NewGameSettings::setNumGnomes( int value )\r\n{\r\n\tif ( m_numGnomes != value )\r\n\t{\r\n\t\tm_numGnomes = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setStartZone( int value )\r\n{\r\n\tif ( m_startZone != value )\r\n\t{\r\n\t\tm_startZone = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setTreeDensity( int value )\r\n{\r\n\tif ( m_treeDensity != value )\r\n\t{\r\n\t\tm_treeDensity = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setPlantDensity( int value )\r\n{\r\n\tif ( m_plantDensity != value )\r\n\t{\r\n\t\tm_plantDensity = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid NewGameSettings::materialsForItem( QString item, QStringList& mats1, QStringList& mats2 )\r\n{\r\n\tQVariantMap row = DB::selectRow( \"Items\", item );\r\n\r\n\tif ( DB::numRows( \"Items_Components\", item ) )\r\n\t{\r\n\t\tauto comps = DB::selectRows( \"Items_Components\", item );\r\n\r\n\t\tfor ( auto mat : materials( comps.first().value( \"ItemID\" ).toString() ) )\r\n\t\t{\r\n\t\t\tmats1.append( mat );\r\n\t\t}\r\n\t\tfor ( auto mat : materials( comps.last().value( \"ItemID\" ).toString() ) )\r\n\t\t{\r\n\t\t\tmats2.append( mat );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor ( auto mat : materials( item ) )\r\n\t\t{\r\n\t\t\tmats1.append( mat );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQStringList NewGameSettings::materials( QString itemSID )\r\n{\r\n\tQVariantMap row = DB::selectRow( \"Items\", itemSID );\r\n\r\n\tQStringList out;\r\n\r\n\tif ( !row.value( \"AllowedMaterials\" ).toString().isEmpty() )\r\n\t{\r\n\t\tfor ( auto mat : row.value( \"AllowedMaterials\" ).toString().split( \"|\" ) )\r\n\t\t{\r\n\t\t\tout.append( mat );\r\n\t\t}\r\n\t}\r\n\tif ( !row.value( \"AllowedMaterialTypes\" ).toString().isEmpty() )\r\n\t{\r\n\t\tfor ( auto type : row.value( \"AllowedMaterialTypes\" ).toString().split( \"|\" ) )\r\n\t\t{\r\n\t\t\tfor ( auto mat : DB::select2( \"ID\", \"Materials\", \"Type\", type ) )\r\n\t\t\t{\r\n\t\t\t\tout.append( mat.toString() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nvoid NewGameSettings::addStartingItem( QString itemSID, QString mat1, QString mat2, int amount )\r\n{\r\n\tif ( amount <= 0 )\r\n\t{\r\n\t\tamount = 1;\r\n\t}\r\n\tfor ( auto& si : m_startingItems )\r\n\t{\r\n\t\tif ( itemSID == si.itemSID && mat1 == si.mat1 && mat2 == si.mat2 )\r\n\t\t{\r\n\t\t\tsi.amount += amount;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tStartingItem si { itemSID, mat1, mat2, amount };\r\n\tm_startingItems.append( si );\r\n}\r\n\r\nvoid NewGameSettings::removeStartingItem( QString tag )\r\n{\r\n\tauto tl = tag.split( \"_\" );\r\n\tQString itemSID;\r\n\tQString mat1;\r\n\tQString mat2;\r\n\tif ( tl.size() > 1 )\r\n\t{\r\n\t\titemSID = tl[0];\r\n\t\tmat1    = tl[1];\r\n\t}\r\n\tif ( tl.size() > 2 )\r\n\t{\r\n\t\tmat2 = tl[2];\r\n\t}\r\n\tfor ( int i = 0; i < m_startingItems.size(); ++i )\r\n\t{\r\n\t\tauto si = m_startingItems[i];\r\n\t\tif ( itemSID == si.itemSID && mat1 == si.mat1 && mat2 == si.mat2 )\r\n\t\t{\r\n\t\t\tm_startingItems.removeAt( i );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NewGameSettings::addStartingAnimal( QString type, QString gender, int amount )\r\n{\r\n\tif ( amount <= 0 )\r\n\t{\r\n\t\tamount = 1;\r\n\t}\r\n\tfor ( auto& sa : m_startingAnimals )\r\n\t{\r\n\t\tif ( type == sa.type && gender == sa.gender )\r\n\t\t{\r\n\t\t\tsa.amount += amount;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tStartingAnimal sa { type, gender, amount };\r\n\tm_startingAnimals.append( sa );\r\n}\r\n\r\nvoid NewGameSettings::removeStartingAnimal( QString tag )\r\n{\r\n\tauto tl = tag.split( \"_\" );\r\n\tQString type;\r\n\tQString gender;\r\n\r\n\tif ( tl.size() > 1 )\r\n\t{\r\n\t\ttype   = tl[0];\r\n\t\tgender = tl[1];\r\n\t}\r\n\tfor ( int i = 0; i < m_startingAnimals.size(); ++i )\r\n\t{\r\n\t\tauto sa = m_startingAnimals[i];\r\n\t\tif ( type == sa.type && gender == sa.gender )\r\n\t\t{\r\n\t\t\tm_startingAnimals.removeAt( i );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NewGameSettings::loadPresets()\r\n{\r\n\tQJsonDocument sd;\r\n\r\n\tQString exePath = QCoreApplication::applicationDirPath();\r\n\r\n\tbool ok = IO::loadFile( exePath + \"/content/JSON/embarkpresets.json\", sd );\r\n\tif ( ok )\r\n\t{\r\n\t\tm_standardPresets = sd.toVariant().toList();\r\n\t}\r\n\r\n\tok = IO::loadFile( IO::getDataFolder() + \"/settings/userpresets.json\", sd );\r\n\tif ( ok )\r\n\t{\r\n\t\tm_userPresets.clear();\r\n\t\tfor( auto vp : sd.toVariant().toList() )\r\n\t\t{\r\n\t\t\tm_userPresets.append( vp.toMap() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NewGameSettings::saveUserPresets()\r\n{\r\n\tQVariantList up;\r\n\tfor( auto pm : m_userPresets )\r\n\t{\r\n\t\tup.append( pm );\r\n\t}\r\n\tQJsonDocument sd = QJsonDocument::fromVariant( up );\r\n\tIO::saveFile( IO::getDataFolder() + \"/settings/userpresets.json\", sd );\r\n}\r\n\r\nvoid NewGameSettings::setPreset( QString name )\r\n{\r\n\tm_selectedPreset = name;\r\n\tfor ( auto p : m_standardPresets )\r\n\t{\r\n\t\tauto pm = p.toMap();\r\n\t\tif ( pm.value( \"Name\" ).toString() == name )\r\n\t\t{\r\n\t\t\tauto sil = pm.value( \"startingItems\" ).toList();\r\n\r\n\t\t\tsetStartingItems( sil );\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tfor ( auto pm : m_userPresets )\r\n\t{\r\n\t\tif ( pm.value( \"Name\" ).toString() == name )\r\n\t\t{\r\n\t\t\tauto sil = pm.value( \"startingItems\" ).toList();\r\n\r\n\t\t\tsetStartingItems( sil );\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQString NewGameSettings::addPreset()\r\n{\r\n\t// get next user name\r\n\tint index       = 1;\r\n\tQString newName = \"Custom \" + QString::number( index );\r\n\twhile ( true )\r\n\t{\r\n\t\tbool conflict = false;\r\n\t\tfor ( auto pm : m_userPresets )\r\n\t\t{\r\n\t\t\tauto name = pm.value( \"Name\" ).toString();\r\n\t\t\tif ( name == newName )\r\n\t\t\t{\r\n\t\t\t\tconflict = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( !conflict )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++index;\r\n\t\tnewName = \"Custom \" + QString::number( index );\r\n\t}\r\n\r\n\tif ( !m_selectedPreset.isEmpty() )\r\n\t{\r\n\t\tfor ( auto p : m_standardPresets )\r\n\t\t{\r\n\t\t\tauto pm = p.toMap();\r\n\t\t\tif ( pm.value( \"Name\" ).toString() == m_selectedPreset )\r\n\t\t\t{\r\n\t\t\t\tpm.insert( \"Name\", newName );\r\n\t\t\t\tm_userPresets.append( pm );\r\n\t\t\t\tsaveUserPresets();\r\n\t\t\t\treturn newName;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( auto pm : m_userPresets )\r\n\t\t{\r\n\t\t\tif ( pm.value( \"Name\" ).toString() == m_selectedPreset )\r\n\t\t\t{\r\n\t\t\t\tpm.insert( \"Name\", newName );\r\n\t\t\t\tm_userPresets.append( pm );\r\n\t\t\t\tsaveUserPresets();\r\n\t\t\t\treturn newName;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tQVariantMap pm;\r\n\t\tpm.insert( \"Name\", newName );\r\n\t\tpm.insert( \"startingItems\", QVariantList() );\r\n\t\tm_userPresets.append( pm );\r\n\t\tsaveUserPresets();\r\n\t\treturn newName;\r\n\t}\r\n\treturn \"\";\r\n}\r\n\r\nbool NewGameSettings::savePreset(  QVariantList items )\r\n{\r\n\tfor ( auto& pm : m_userPresets )\r\n\t{\r\n\t\tif ( pm.value( \"Name\" ).toString() == m_selectedPreset )\r\n\t\t{\r\n\t\t\tpm.insert( \"startingItems\", items );\r\n\t\t\r\n\t\t\tsaveUserPresets();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::onSavePreset()\r\n{\r\n\tQVariantList sil;\r\n\tcollectStartItems( sil );\r\n\treturn savePreset( sil );\r\n}\r\n\r\nbool NewGameSettings::removePreset( QString name )\r\n{\r\n\tfor ( int i = 0; i < m_userPresets.size(); ++i )\r\n\t{\r\n\t\tauto pm = m_userPresets[i];\r\n\t\tif ( pm.value( \"Name\" ).toString() == name )\r\n\t\t{\r\n\t\t\tm_selectedPreset = \"\";\r\n\t\t\tm_userPresets.removeAt( i );\r\n\t\t\tsaveUserPresets();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid NewGameSettings::setStartingItems( QVariantList sil )\r\n{\r\n\tm_startingItems.clear();\r\n\tm_startingAnimals.clear();\r\n\r\n\tfor ( auto vsi : sil )\r\n\t{\r\n\t\tauto sipm = vsi.toMap();\r\n\t\tif ( sipm.value( \"Type\" ).toString() == \"Item\" )\r\n\t\t{\r\n\t\t\tQString itemSID = sipm.value( \"ItemID\" ).toString();\r\n\t\t\tQString mat1    = sipm.value( \"MaterialID\" ).toString();\r\n\t\t\tint amount      = sipm.value( \"Amount\" ).toInt();\r\n\t\t\tStartingItem si { itemSID, mat1, \"\", amount };\r\n\t\t\tm_startingItems.append( si );\r\n\t\t}\r\n\t\telse if ( sipm.value( \"Type\" ).toString() == \"CombinedItem\" )\r\n\t\t{\r\n\t\t\tQString itemSID = sipm.value( \"ItemID\" ).toString();\r\n\t\t\tint amount      = sipm.value( \"Amount\" ).toInt();\r\n\t\t\tauto components = sipm.value( \"Components\" ).toList();\r\n\t\t\tif ( components.size() == 2 )\r\n\t\t\t{\r\n\t\t\t\tauto vmc1 = components[0].toMap();\r\n\t\t\t\tauto vmc2 = components[0].toMap();\r\n\r\n\t\t\t\tQString mat1 = vmc1.value( \"MaterialID\" ).toString();\r\n\t\t\t\tQString mat2 = vmc2.value( \"MaterialID\" ).toString();\r\n\r\n\t\t\t\tStartingItem si { itemSID, mat1, mat2, amount };\r\n\t\t\t\tm_startingItems.append( si );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( sipm.value( \"Type\" ).toString() == \"Animal\" )\r\n\t\t{\r\n\t\t\tQString type   = sipm.value( \"ItemID\" ).toString();\r\n\t\t\tQString gender = sipm.value( \"Gender\" ).toString();\r\n\t\t\tgender.replace( 0, 1, gender[0].toUpper() );\r\n\t\t\tint amount = sipm.value( \"Amount\" ).toInt();\r\n\t\t\tStartingAnimal si { type, gender, amount };\r\n\t\t\tm_startingAnimals.append( si );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQStringList NewGameSettings::presetNames()\r\n{\r\n\tQStringList out;\r\n\tfor ( auto p : m_standardPresets )\r\n\t{\r\n\t\tout.append( p.toMap().value( \"Name\" ).toString() );\r\n\t}\r\n\tfor ( auto pm : m_userPresets )\r\n\t{\r\n\t\tout.append( pm.value( \"Name\" ).toString() );\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQVariantList NewGameSettings::trees()\r\n{\r\n\tQVariantList out;\r\n\tfor ( auto ci : m_checkableItems )\r\n\t{\r\n\t\tif ( ci.type == \"Tree\" )\r\n\t\t{\r\n\t\t\tQVariantMap entry;\r\n\t\t\tentry.insert( \"ID\", ci.sid );\r\n\t\t\tentry.insert( \"Name\", ci.name );\r\n\t\t\tentry.insert( \"Allowed\", ci.isChecked );\r\n\t\t\tout.append( entry );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQVariantList NewGameSettings::plants()\r\n{\r\n\tQVariantList out;\r\n\tfor ( auto ci : m_checkableItems )\r\n\t{\r\n\t\tif ( ci.type == \"Plant\" )\r\n\t\t{\r\n\t\t\tQVariantMap entry;\r\n\t\t\tentry.insert( \"ID\", ci.sid );\r\n\t\t\tentry.insert( \"Name\", ci.name );\r\n\t\t\tentry.insert( \"Allowed\", ci.isChecked );\r\n\t\t\tout.append( entry );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nQVariantList NewGameSettings::animals()\r\n{\r\n\tQVariantList out;\r\n\tfor ( auto ci : m_checkableItems )\r\n\t{\r\n\t\tif ( ci.type == \"Animal\" )\r\n\t\t{\r\n\t\t\tQVariantMap entry;\r\n\t\t\tentry.insert( \"ID\", ci.sid );\r\n\t\t\tentry.insert( \"Name\", ci.name );\r\n\t\t\tentry.insert( \"Allowed\", ci.isChecked );\r\n\t\t\tentry.insert( \"Amount\", ci.max );\r\n\t\t\tout.append( entry );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nbool NewGameSettings::isChecked( QString sid )\r\n{\r\n\tif ( m_checkableItems.contains( sid ) )\r\n\t{\r\n\t\tCheckableItem& ci = m_checkableItems[sid];\r\n\t\treturn ci.isChecked;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid NewGameSettings::setChecked( QString sid, bool value )\r\n{\r\n\tif ( m_checkableItems.contains( sid ) )\r\n\t{\r\n\t\tauto& ci     = m_checkableItems[sid];\r\n\t\tci.isChecked = value;\r\n\t}\r\n}\r\n\r\nbool NewGameSettings::setPeaceful( bool value )\r\n{\r\n\tif ( m_isPeaceful != value )\r\n\t{\r\n\t\tm_isPeaceful = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setMaxPerType( int value )\r\n{\r\n\tif ( m_maxPerType != value )\r\n\t{\r\n\t\tm_maxPerType = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool NewGameSettings::setNumWildAnimals( int value )\r\n{\r\n\tif ( m_numWildAnimals != value )\r\n\t{\r\n\t\tm_numWildAnimals = value;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nint NewGameSettings::maxAnimalsPerType( QString type )\r\n{\r\n\tif( m_checkableItems.contains( type ) )\r\n\t{\r\n\t\tconst auto& ci = m_checkableItems.value( type );\r\n\t\treturn ci.max;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid NewGameSettings::setAmount( QString sid, int value )\r\n{\r\n\tif ( m_checkableItems.contains( sid ) )\r\n\t{\r\n\t\tauto& ci     = m_checkableItems[sid];\r\n\t\tci.max = value;\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/game/newgamesettings.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QObject>\r\n#include <QVariantMap>\r\n\r\nstruct StartingItem\r\n{\r\n\tQString itemSID;\r\n\tQString mat1;\r\n\tQString mat2;\r\n\tint amount = 1;\r\n};\r\n\r\nstruct StartingAnimal\r\n{\r\n\tQString type;\r\n\tQString gender;\r\n\tint amount = 1;\r\n};\r\n\r\nstruct CheckableItem\r\n{\r\n\tQString sid;\r\n\tQString name;\r\n\tQString type;\r\n\tbool isChecked;\r\n\tint max;\r\n};\r\n\r\nclass NewGameSettings : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tNewGameSettings( QObject* parent = 0 );\r\n\t~NewGameSettings();\r\n\r\n\tvoid save();\r\n\r\n\tvoid setRandomName();\r\n\tvoid setRandomSeed();\r\n\r\n\tbool setKingdomName( QString value );\r\n\tbool setSeed( QString value );\r\n\r\n\tQString kingdomName()\r\n\t{\r\n\t\treturn m_kingdomName;\r\n\t}\r\n\tQString seed()\r\n\t{\r\n\t\treturn m_seed;\r\n\t}\r\n\r\n\tint worldSize()\r\n\t{\r\n\t\treturn m_worldSize;\r\n\t}\r\n\tint zLevels()\r\n\t{\r\n\t\treturn m_zLevels;\r\n\t}\r\n\tint ground()\r\n\t{\r\n\t\treturn m_ground;\r\n\t}\r\n\tint flatness()\r\n\t{\r\n\t\treturn m_flatness;\r\n\t}\r\n\tint oceanSize()\r\n\t{\r\n\t\treturn m_oceanSize;\r\n\t}\r\n\tint rivers()\r\n\t{\r\n\t\treturn m_rivers;\r\n\t}\r\n\tint riverSize()\r\n\t{\r\n\t\treturn m_riverSize;\r\n\t}\r\n\t int numGnomes()\r\n\t{\r\n\t\treturn m_numGnomes;\r\n\t}\r\n\tint startZone()\r\n\t{\r\n\t\treturn m_startZone;\r\n\t}\r\n\tint treeDensity()\r\n\t{\r\n\t\treturn m_treeDensity;\r\n\t}\r\n\tint plantDensity()\r\n\t{\r\n\t\treturn m_plantDensity;\r\n\t}\r\n\tbool isPeaceful()\r\n\t{\r\n\t\treturn m_isPeaceful;\r\n\t}\r\n\tint globalMaxPerType()\r\n\t{\r\n\t\treturn m_maxPerType;\r\n\t}\r\n\tint numWildAnimals()\r\n\t{\r\n\t\treturn m_numWildAnimals;\r\n\t}\r\n\tint maxAnimalsPerType( QString type );\r\n\t\r\n\r\n\tbool setWorldSize( int value );\r\n\tbool setZLevels( int value );\r\n\tbool setGround( int value );\r\n\tbool setFlatness( int value );\r\n\tbool setOceanSize( int value );\r\n\tbool setRivers( int value );\r\n\tbool setRiverSize( int value );\r\n\tbool setNumGnomes( int value );\r\n\tbool setStartZone( int value );\r\n\tbool setTreeDensity( int value );\r\n\tbool setPlantDensity( int value );\r\n\tbool setPeaceful( bool value );\r\n\tbool setMaxPerType( int value );\r\n\tbool setNumWildAnimals( int value );\r\n\r\n\tvoid materialsForItem( QString item, QStringList& mats1, QStringList& mats2 );\r\n\tvoid addStartingItem( QString itemSID, QString mat1, QString mat2, int amount );\r\n\tvoid removeStartingItem( QString tag );\r\n\r\n\tvoid addStartingAnimal( QString type, QString gender, int amount );\r\n\tvoid removeStartingAnimal( QString tag );\r\n\r\n\tQList<StartingItem> startingItems()\r\n\t{\r\n\t\treturn m_startingItems;\r\n\t}\r\n\tQList<StartingAnimal> startingAnimals()\r\n\t{\r\n\t\treturn m_startingAnimals;\r\n\t}\r\n\r\n\tQVariantList trees();\r\n\tQVariantList plants();\r\n\tQVariantList animals();\r\n\r\n\tvoid setPreset( QString name );\r\n\tQStringList presetNames();\r\n\tQString addPreset();\r\n\tbool removePreset( QString name );\r\n\tbool savePreset( QVariantList items );\r\n\tbool onSavePreset();\r\n\r\n\tbool isChecked( QString sid );\r\n\tvoid setChecked( QString sid, bool value );\r\n\r\n\tvoid setAmount( QString sid, int value );\r\n\r\nprivate:\r\n\tvoid loadEmbarkMap();\r\n\tvoid loadPresets();\r\n\tvoid saveUserPresets();\r\n\r\n\tvoid setStartingItems( QVariantList sil );\r\n\tvoid collectStartItems( QVariantList& sil );\r\n\r\n\r\n\tQString m_kingdomName;\r\n\tQString m_seed;\r\n\r\n\tint m_worldSize      = 100;\r\n\tint m_zLevels        = 130;\r\n\tint m_ground         = 100;\r\n\tint m_flatness       = 0;\r\n\tint m_oceanSize      = 0;\r\n\tint m_rivers         = 1;\r\n\tint m_riverSize      = 3;\r\n\tint m_numGnomes      = 8;\r\n\tint m_startZone      = 10;\r\n\tint m_treeDensity    = 50;\r\n\tint m_plantDensity   = 50;\r\n\tint m_numWildAnimals = 500;\r\n\tint m_maxPerType     = 1000;\r\n\r\n\tbool m_isPeaceful = true;\r\n\r\n\tQList<StartingItem> m_startingItems;\r\n\tQList<StartingAnimal> m_startingAnimals;\r\n\r\n\tQStringList materials( QString itemSID );\r\n\r\n\tQVariantList m_standardPresets;\r\n\tQList<QVariantMap> m_userPresets;\r\n\r\n\tQString m_selectedPreset;\r\n\r\n\tQMap<QString, CheckableItem> m_checkableItems;\r\n};\r\n"
  },
  {
    "path": "src/game/object.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"object.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n\r\nObject::Object()\r\n{\r\n}\r\n\r\nObject::Object( const Position& position ) :\r\n\tm_position( position ),\r\n\tm_spriteID( 0 )\r\n{\r\n\tm_id = GameState::createID();\r\n}\r\n\r\nObject::Object( QVariantMap in ) :\r\n\tm_id( in.value( \"ID\" ).toUInt() ),\r\n\tm_position( in.value( \"Position\" ).toString() ),\r\n\tm_spriteID( in.value( \"SpriteID\" ).toUInt() )\r\n{\r\n}\r\n\r\nvoid Object::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"ID\", m_id );\r\n\tout.insert( \"Position\", m_position.toString() );\r\n\tout.insert( \"SpriteID\", m_spriteID );\r\n}\r\n\r\nObject::~Object()\r\n{\r\n}\r\n\r\nunsigned int Object::id() const\r\n{\r\n\treturn m_id;\r\n}\r\n\r\nconst Position& Object::getPos() const\r\n{\r\n\treturn m_position;\r\n}\r\n\r\nvoid Object::setPos( Position position )\r\n{\r\n\tm_position = position;\r\n}\r\n\r\nunsigned int Object::spriteID() const\r\n{\r\n\treturn m_spriteID;\r\n}\r\n\r\nvoid Object::setSpriteID( unsigned int id )\r\n{\r\n\tm_spriteID = id;\r\n}\r\n"
  },
  {
    "path": "src/game/object.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QVariant>\r\n#include <QtGlobal>\r\n\r\nclass Object\r\n{\r\npublic:\r\n\tObject();\r\n\tObject( const Position& position );\r\n\tObject( QVariantMap in );\r\n\tvirtual ~Object();\r\n\r\n\tbool operator<( const Object& o ) const\r\n\t{\r\n\t\treturn m_id < o.m_id;\r\n\t}\r\n\r\n\tunsigned int id() const;\r\n\r\n\tconst Position& getPos() const;\r\n\tvoid setPos( Position position );\r\n\r\n\tvirtual unsigned int spriteID() const;\r\n\tvoid setSpriteID( unsigned int id );\r\n\r\n\tvirtual void serialize( QVariantMap& out ) const;\r\n\r\nprotected:\r\n\tunsigned int m_id;\r\n\r\n\tPosition m_position;\r\n\r\n\tunsigned int m_spriteID;\r\n};\r\n"
  },
  {
    "path": "src/game/pasture.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"pasture.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nPastureProperties::PastureProperties( QVariantMap& in )\r\n{\r\n\tanimalType = in.value( \"AnimalType\" ).toString();\r\n\tharvest    = in.value( \"Harvest\" ).toBool();\r\n\tharvestHay = in.value( \"HarvestHay\" ).toBool();\r\n\tmaxHay     = in.value( \"MaxHay\" ).toInt();\r\n\r\n\tmax           = in.value( \"Max\" ).toInt();\r\n\tmaxMale       = in.value( \"MaxMale\" ).toInt();\r\n\tmaxFemale     = in.value( \"MaxFemale\" ).toInt();\r\n\ttameWild      = in.value( \"TameWild\" ).toBool();\r\n\tcollectEggs   = in.value( \"CollectEggs\" ).toBool();\r\n\tonlyAvailable = in.value( \"OnlyAvailable\" ).toBool();\r\n\r\n\tmaxTroughCapacity = in.value( \"MaxTroughCapacity\" ).toInt();\r\n\ttroughContent     = in.value( \"TroughContent\" ).toInt();\r\n\r\n\tfoodSettings = in.value( \"Food\" ).toStringList().toSet();\r\n\r\n\tanimalSize = DB::select( \"PastureSize\", \"Animals\", animalType ).toInt();\r\n}\r\n\r\nvoid PastureProperties::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"Type\", \"pasture\" );\r\n\tout.insert( \"AnimalType\", animalType );\r\n\tout.insert( \"Harvest\", harvest );\r\n\tout.insert( \"HarvestHay\", harvestHay );\r\n\tout.insert( \"MaxHay\", maxHay );\r\n\r\n\tout.insert( \"Max\", max );\r\n\tout.insert( \"MaxMale\", maxMale );\r\n\tout.insert( \"MaxFemale\", maxFemale );\r\n\tout.insert( \"TameWild\", tameWild );\r\n\tout.insert( \"CollectEggs\", collectEggs );\r\n\tout.insert( \"OnlyAvailable\", onlyAvailable );\r\n\r\n\tout.insert( \"MaxTroughCapacity\", maxTroughCapacity );\r\n\tout.insert( \"TroughContent\", troughContent );\r\n\r\n\tout.insert( \"Food\", QStringList( foodSettings.values() ) );\r\n}\r\n\r\nPasture::Pasture( QList<QPair<Position, bool>> tiles, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_name = \"Pasture\";\r\n\r\n\tfor ( auto p : tiles )\r\n\t{\r\n\t\tif ( p.second )\r\n\t\t{\r\n\t\t\tPastureField* grofi = new PastureField;\r\n\t\t\tgrofi->pos = p.first;\r\n\t\t\tm_fields.insert( p.first.toInt(), grofi );\r\n\t\t}\r\n\t}\r\n\tif ( m_fields.size() )\r\n\t{\r\n\t\tfor ( auto field : m_fields )\r\n\t\t{\r\n\t\t\tm_properties.firstPos = field->pos;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nPasture::Pasture( QVariantMap vals, Game* game ) :\r\n\tWorldObject( vals, game ),\r\n\tm_properties( vals )\r\n{\r\n\tQVariantList vfl = vals.value( \"Fields\" ).toList();\r\n\tfor ( auto vf : vfl )\r\n\t{\r\n\t\tPastureField* grofi = new PastureField;\r\n\t\tauto vfm = vf.toMap();\r\n\t\tgrofi->pos = Position( vfm.value( \"Pos\" ).toString() );\r\n\t\tif( vfm.contains( \"Job\" ) )\r\n\t\t{\r\n\t\t\tgrofi->job = g->jm()->getJob( vfm.value( \"Job\" ).toUInt() );\r\n\t\t}\r\n\t\tgrofi->util   = vf.toMap().value( \"Util\" ).toUInt();\r\n\t\tm_fields.insert( grofi->pos.toInt(), grofi );\r\n\t}\r\n\tif ( m_fields.size() )\r\n\t{\r\n\t\tfor ( auto field : m_fields )\r\n\t\t{\r\n\t\t\tm_properties.firstPos = field->pos;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tQVariantList val = vals.value( \"Animals\" ).toList();\r\n\tfor ( auto va : val )\r\n\t{\r\n\t\tm_animals.append( va.toUInt() );\r\n\t}\r\n}\r\n/*\r\nPasture::Pasture( const Pasture& other )\r\n{\r\n\tm_properties = other.m_properties;\r\n\tm_fields = other.m_fields;\r\n\tm_animals = other.m_animals;\r\n\tm_animalsInJob = other.m_animalsInJob;\r\n\tm_jobsOut = other.m_jobsOut;\r\n}\r\n*/\r\n\r\nQVariant Pasture::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\tWorldObject::serialize( out );\r\n\tm_properties.serialize( out );\r\n\r\n\tQVariantList tiles;\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tQVariantMap entry;\r\n\t\tentry.insert( \"Pos\", field->pos.toString() );\r\n\t\tif( field->job )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> spJob = field->job.toStrongRef();\r\n\t\t\tentry.insert( \"Job\", spJob->id() );\r\n\t\t}\r\n\t\tentry.insert( \"Util\", field->util );\r\n\t\ttiles.append( entry );\r\n\t}\r\n\tout.insert( \"Fields\", tiles );\r\n\r\n\tQVariantList animals;\r\n\tfor ( auto an : m_animals )\r\n\t{\r\n\t\tanimals.append( an );\r\n\t}\r\n\tout.insert( \"Animals\", animals );\r\n\r\n\treturn out;\r\n}\r\n\r\nPasture::~Pasture()\r\n{\r\n\tfor ( const auto& field : m_fields )\r\n\t{\r\n\t\tdelete field;\r\n\t}\r\n}\r\n\r\nvoid Pasture::addTile( const Position & pos )\r\n{\r\n\tPastureField* grofi = new PastureField;\r\n\tgrofi->pos = pos;\r\n\tm_fields.insert( pos.toInt(), grofi );\r\n\r\n\tif( m_properties.animalSize != 0 )\r\n\t{\r\n\t\tm_properties.max = m_fields.size() / m_properties.animalSize;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_properties.max = 0;\r\n\t}\r\n\r\n\tg->w()->setTileFlag( pos, TileFlag::TF_PASTURE );\r\n}\r\n\r\n// farming manager calls this on hour changed\r\nvoid Pasture::onTick( quint64 tick, int& count )\r\n{\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tTile& tile = g->w()->getTile( field->pos );\r\n\t\tif( GameState::season != 3 )\r\n\t\t{\r\n\t\t\tif ( tile.flags & TileFlag::TF_GRASS )\r\n\t\t\t{\r\n\t\t\t\tif( tick % 500 == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.vegetationLevel = qMin( 100, tile.vegetationLevel + 1 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( !m_active )\r\n\t\treturn;\r\n\r\n\tint countMale   = 0;\r\n\tint countFemale = 0;\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif ( animal )\r\n\t\t{\r\n\t\t\tif ( animal->gender() == Gender::MALE )\r\n\t\t\t{\r\n\t\t\t\t++countMale;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++countFemale;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tcount = countMale + countFemale;\r\n\r\n\tfor ( auto& a : g->cm()->animals() )\r\n\t{\r\n\t\tif ( a->species() == m_properties.animalType && a->isTame() && a->pastureID() == 0 && !a->toDestroy() && !a->isDead() )\r\n\t\t{\r\n\t\t\tif ( a->gender() == Gender::MALE && countMale < m_properties.maxMale )\r\n\t\t\t{\r\n\t\t\t\tm_animals.append( a->id() );\r\n\t\t\t\ta->setPastureID( id() );\r\n\t\t\t\t++countMale;\r\n\t\t\t\tif ( m_animals.size() >= m_properties.max )\r\n\t\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\telse if ( a->gender() == Gender::FEMALE && countFemale < m_properties.maxFemale )\r\n\t\t\t{\r\n\t\t\t\tm_animals.append( a->id() );\r\n\t\t\t\ta->setPastureID( id() );\r\n\t\t\t\t++countFemale;\r\n\t\t\t\tif ( m_animals.size() >= m_properties.max )\r\n\t\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// lead animals back to pasture\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tint posID      = animal->getPos().toInt();\r\n\t\tif ( !m_fields.contains( posID ) && !animal->inJob() )\r\n\t\t{\r\n\t\t\tif ( g->w()->regionMap().checkConnectedRegions( m_fields.first()->pos, animal->getPos() ) )\r\n\t\t\t{\r\n\t\t\t\t// find a free field first\r\n\t\t\t\tQList<Position>freeFields;\r\n\t\t\t\tfor ( auto& field : m_fields )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( !field->job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfreeFields.append( field->pos );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif( freeFields.size() )\r\n\t\t\t\t{\r\n\t\t\t\t\tint random = rand() % freeFields.size();\r\n\t\t\t\t\tauto targetPos = freeFields[random];\r\n\r\n\t\t\t\t\tauto jobID = g->jm()->addJob( \"LeadAnimalToPasture\", animal->getPos(), 0, false );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob->setAnimal( animal->id() );\r\n\t\t\t\t\t\tanimal->setInJob( job->id() );\r\n\t\t\t\t\t\tanimal->setImmobile( true );\r\n\t\t\t\t\t\tjob->setPosItemInput( targetPos );\r\n\t\t\t\t\t\tm_fields[targetPos.toInt()]->job = job;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak; // no reason to check other animals\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t// harvest animals\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif ( animal && animal->numProduce() > 0 && !animal->inJob() )\r\n\t\t{\r\n\t\t\tif ( m_fields.contains( animal->getPos().toInt() ) )\r\n\t\t\t{\r\n\t\t\t\tif( !m_fields[animal->getPos().toInt()]->job )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto jobID = g->jm()->addJob( \"HarvestAnimal\", animal->getPos(), 0, false );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob->setAnimal( animal->id() );\r\n\t\t\t\t\t\tanimal->setInJob( job->id() );\r\n\t\t\t\t\t\tanimal->setImmobile( true );\r\n\t\t\t\t\t\tm_fields[animal->getPos().toInt()]->job = job;\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\t//fill troughs\r\n\tif ( !m_properties.foodSettings.isEmpty() && m_properties.maxTroughCapacity > 0 )\r\n\t{\r\n\t\tif ( m_properties.troughContent < m_properties.maxTroughCapacity - 9 )\r\n\t\t{\r\n\t\t\tfor ( auto foodString : m_properties.foodSettings )\r\n\t\t\t{\r\n\t\t\t\tauto fsl = foodString.split( \"_\" );\r\n\t\t\t\tif ( g->inv()->itemCount( fsl[0], fsl[1] ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto& field : m_fields )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( field->util && !field->job )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( g->inv()->itemSID( field->util ) == \"Trough\" )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tauto jobID = g->jm()->addJob( \"FillTrough\", field->pos, 0, false );\r\n\t\t\t\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\t\t\t\tif( job )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tjob->setPosItemInput( field->pos );\r\n\t\t\t\t\t\t\t\t\tjob->addRequiredItem( 1, fsl[0], fsl[1], {} );\r\n\t\t\t\t\t\t\t\t\tfield->job = job;\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}\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\t//harvest hay\r\n\tif ( m_properties.harvestHay && GameState::season != 3 )\r\n\t{\r\n\t\tif ( g->inv()->itemCount( \"Hay\", \"any\" ) < (unsigned int)m_properties.maxHay )\r\n\t\t{\r\n\t\t\tfor ( auto& field : m_fields )\r\n\t\t\t{\r\n\t\t\t\tif ( !field->job && g->w()->hasMaxGrass( field->pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto jobID = g->jm()->addJob( \"HarvestHay\", field->pos, 0, false );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfield->job = job;\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 Pasture::addAnimal( unsigned int animalID )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn;\r\n\r\n\tif ( m_animals.size() >= m_properties.max )\r\n\t\treturn;\r\n\tint countMale   = 0;\r\n\tint countFemale = 0;\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tif ( g->cm()->animal( id )->gender() == Gender::MALE )\r\n\t\t{\r\n\t\t\t++countMale;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t++countFemale;\r\n\t\t}\r\n\t}\r\n\r\n\tauto a = g->cm()->animal( animalID );\r\n\r\n\tif ( a && a->species() == m_properties.animalType && a->isTame() && a->pastureID() == 0 && !a->toDestroy() && !a->isDead() )\r\n\t{\r\n\t\tif ( a->gender() == Gender::MALE && countMale < m_properties.maxMale )\r\n\t\t{\r\n\t\t\tm_animals.append( a->id() );\r\n\t\t\ta->setPastureID( id() );\r\n\t\t\t++countMale;\r\n\t\t\tif ( m_animals.size() >= m_properties.max )\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t\telse if ( a->gender() == Gender::FEMALE && countFemale < m_properties.maxFemale )\r\n\t\t{\r\n\t\t\tm_animals.append( a->id() );\r\n\t\t\ta->setPastureID( id() );\r\n\t\t\t++countFemale;\r\n\t\t\tif ( m_animals.size() >= m_properties.max )\r\n\t\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n\r\n/*\r\n\t\t\tif ( m_properties.tameWild )\r\n\t\t\t{\r\n\t\t\t\tif ( m_animals.size() < m_properties.max )\r\n\t\t\t\t{\r\n\t\t\t\t\tint countMale   = 0;\r\n\t\t\t\t\tint countFemale = 0;\r\n\t\t\t\t\tfor ( auto id : m_animals )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( g->cm()->animal( id )->gender() == Gender::MALE )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t++countMale;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t++countFemale;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tint random = rand() % m_fields.size();\r\n\t\t\t\t\tPosition fieldPos;\r\n\t\t\t\t\tfor ( auto field : m_fields )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( random == 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tfieldPos = field->pos;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t--random;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tauto animals = g->cm()->animalsByDistance( fieldPos, m_properties.animalType );\r\n\t\t\t\t\tAnimal* a    = nullptr;\r\n\t\t\t\t\twhile ( !animals.empty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ta = animals.get();\r\n\t\t\t\t\t\tif ( !a->isTame() && a->pastureID() == 0 && !a->toDestroy() && !a->isDead() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( a->gender() == Gender::MALE && countMale < m_properties.maxMale )\r\n\t\t\t\t\t\t\t{\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\telse if ( a->gender() == Gender::FEMALE && countFemale < m_properties.maxFemale )\r\n\t\t\t\t\t\t\t{\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}\r\n\t\t\t\t\t\ta = nullptr;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( a )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQSharedPointer<Job> job( new Job() );\r\n\r\n\t\t\t\t\t\tjob->setType( \"TameAnimal\" );\r\n\t\t\t\t\t\tjob->setRequiredSkill( \"AnimalHusbandry\" );\r\n\t\t\t\t\t\tjob->setPos( a->getPos() );\r\n\t\t\t\t\t\tjob->addPossibleWorkPosition( a->getPos() );\r\n\t\t\t\t\t\tjob->setAnimal( a->id() );\r\n\t\t\t\t\t\tjob->setPosItemInput( fieldPos );\r\n\t\t\t\t\t\ta->setInJob( job->id() );\r\n\t\t\t\t\t\ta->setImmobile( true );\r\n\t\t\t\t\t\tjob->setNoJobSprite( true );\r\n\t\t\t\t\t\tm_animalsInJob.insert( a->id() );\r\n\r\n\t\t\t\t\t\treturn job;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n*/\r\n\r\nbool Pasture::removeTile( const Position & pos )\r\n{\r\n\tPastureField* ff = m_fields.value( pos.toInt() );\r\n\tm_fields.remove( pos.toInt() );\r\n\tdelete ff;\r\n\r\n\tg->w()->clearTileFlag( pos, TileFlag::TF_PASTURE );\r\n\r\n\r\n\tif ( m_fields.size() )\r\n\t{\r\n\t\tfor ( auto field : m_fields )\r\n\t\t{\r\n\t\t\tm_properties.firstPos = field->pos;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_properties.firstPos = Position();\r\n\t}\r\n\r\n\tif( m_properties.animalSize != 0 )\r\n\t{\r\n\t\tm_properties.max = m_fields.size() / m_properties.animalSize;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_properties.max = 0;\r\n\t}\r\n\tm_properties.maxMale   = qMin( m_properties.max, m_properties.maxMale );\r\n\tm_properties.maxFemale = qMin( m_properties.max, m_properties.maxFemale );\r\n\r\n\twhile ( m_animals.size() && m_properties.max < m_animals.size() )\r\n\t{\r\n\t\tauto id        = m_animals.takeLast();\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif ( animal )\r\n\t\t{\r\n\t\t\tanimal->setPastureID( 0 );\r\n\t\t}\r\n\t}\r\n\r\n\t// if last tile deleted return true\r\n\treturn m_fields.empty();\r\n}\r\n\r\nvoid Pasture::getInfo( int& numPlots, int& numMale, int& numFemale )\r\n{\r\n\tnumPlots  = m_fields.size();\r\n\tnumMale   = 0;\r\n\tnumFemale = 0;\r\n\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif( animal )\r\n\t\t{\r\n\t\t\tif ( animal->gender() == Gender::MALE )\r\n\t\t\t{\r\n\t\t\t\t++numMale;\r\n\t\t\t}\r\n\t\t\telse if ( animal->gender() == Gender::FEMALE )\r\n\t\t\t{\r\n\t\t\t\t++numFemale;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Pasture::removeAnimal( unsigned int animalID )\r\n{\r\n\tAnimal* animal = g->cm()->animal( animalID );\r\n\tif ( animal )\r\n\t{\r\n\t\tanimal->setFollowID( 0 );\r\n\t\tanimal->setPastureID( 0 );\r\n\t}\r\n\r\n\tm_animals.removeAll( animalID );\r\n\r\n\tint plots;\r\n\tint male;\r\n\tint female;\r\n\tgetInfo( plots, male, female );\r\n}\r\n\r\nvoid Pasture::removeAllAnimals()\r\n{\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif ( animal )\r\n\t\t{\r\n\t\t\tanimal->setFollowID( 0 );\r\n\t\t\tanimal->setPastureID( 0 );\r\n\t\t}\r\n\t}\r\n\tm_animals.clear();\r\n\r\n\tint plots;\r\n\tint male;\r\n\tint female;\r\n\tgetInfo( plots, male, female );\r\n}\r\n\r\nbool Pasture::canDelete()\r\n{\r\n\treturn true;\r\n}\r\n\r\nint Pasture::countTiles()\r\n{\r\n\treturn m_fields.size();\r\n}\r\n\r\nbool Pasture::addUtil( Position pos, unsigned int itemID )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tPastureField* pf = m_fields[pos.toInt()];\r\n\t\tif ( pf->util == 0 )\r\n\t\t{\r\n\t\t\tpf->util = itemID;\r\n\r\n\t\t\t//if item is trough\r\n\t\t\tif ( g->inv()->itemSID( itemID ) == \"Trough\" )\r\n\t\t\t{\r\n\t\t\t\tm_properties.maxTroughCapacity += 20;\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Pasture::removeUtil( Position pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tPastureField* pf = m_fields[pos.toInt()];\r\n\r\n\t\tif ( pf->util != 0 )\r\n\t\t{\r\n\t\t\tunsigned int itemID = pf->util;\r\n\r\n\t\t\tpf->util = 0;\r\n\r\n\t\t\t//if item is trough\r\n\t\t\tif ( g->inv()->itemSID( itemID ) == \"Trough\" )\r\n\t\t\t{\r\n\t\t\t\tm_properties.maxTroughCapacity -= 20;\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nunsigned int Pasture::util( Position pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tPastureField* pf = m_fields[pos.toInt()];\r\n\t\treturn pf->util;\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nPosition Pasture::randomFieldPos()\r\n{\r\n\tint random = rand() % m_fields.size();\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tif ( random == 0 )\r\n\t\t{\r\n\t\t\treturn field->pos;\r\n\t\t}\r\n\t\t--random;\r\n\t}\r\n\treturn Position();\r\n}\r\n\r\nPosition Pasture::findShed()\r\n{\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tif ( field->util )\r\n\t\t{\r\n\t\t\tif ( g->inv()->itemSID( field->util ) == \"Shed\" )\r\n\t\t\t{\r\n\t\t\t\treturn field->pos;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn Position();\r\n}\r\n\r\nQSet<QString>& Pasture::foodSettings()\r\n{\r\n\treturn m_properties.foodSettings;\r\n}\r\n\r\nvoid Pasture::addFoodSetting( QString itemSID, QString materialSID )\r\n{\r\n\tm_properties.foodSettings.insert( itemSID + \"_\" + materialSID );\r\n}\r\n\r\nvoid Pasture::removeFoodSetting( QString itemSID, QString materialSID )\r\n{\r\n\tm_properties.foodSettings.remove( itemSID + \"_\" + materialSID );\r\n}\r\n\r\nvoid Pasture::addFood( unsigned int itemID )\r\n{\r\n\tm_properties.troughContent += 10;\r\n}\r\n\r\nint Pasture::maxHay()\r\n{\r\n\treturn m_properties.maxHay;\r\n}\r\n\r\nvoid Pasture::setMaxHay( int value )\r\n{\r\n\tm_properties.maxHay = value;\r\n}\r\n\r\nint Pasture::foodLevel()\r\n{\r\n\treturn m_properties.troughContent;\r\n}\r\n\r\nint Pasture::maxFoodLevel()\r\n{\r\n\treturn m_properties.maxTroughCapacity;\r\n}\r\n\r\n\r\nbool Pasture::eatFromTrough()\r\n{\r\n\tif ( m_properties.troughContent > 0 )\r\n\t{\r\n\t\tm_properties.troughContent -= 1;\r\n\t\treturn true;\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid Pasture::setAnimalType( QString type )\r\n{\r\n\tif ( m_properties.animalType != type )\r\n\t{\r\n\t\tfor ( auto id : m_animals )\r\n\t\t{\r\n\t\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\t\tif ( animal )\r\n\t\t\t{\r\n\t\t\t\tanimal->setPastureID( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_animals.clear();\r\n\t}\r\n\r\n\tm_properties.animalType = type;\r\n\r\n\tm_properties.animalSize = DB::select( \"PastureSize\", \"Animals\", type ).toInt();\r\n\tif ( m_properties.animalSize != 0 )\r\n\t{\r\n\t\tint numPlots = m_fields.size();\r\n\r\n\t\tif( m_properties.animalSize != 0 )\r\n\t\t{\r\n\t\t\tm_properties.max = m_fields.size() / m_properties.animalSize;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_properties.max = 0;\r\n\t\t}\r\n\t\tm_properties.maxMale   = m_properties.max;\r\n\t\tm_properties.maxFemale = m_properties.max;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_properties.max       = 0;\r\n\t\tm_properties.maxMale   = 0;\r\n\t\tm_properties.maxFemale = 0;\r\n\t}\r\n}\r\n\r\nQString Pasture::animalType()\r\n{\r\n\treturn m_properties.animalType;\r\n}\r\n\r\nbool Pasture::harvest()\r\n{\r\n\treturn m_properties.harvest;\r\n}\r\n\r\nvoid Pasture::setHarvest( bool harvest )\r\n{\r\n\tm_properties.harvest = harvest;\r\n}\r\n\r\nbool Pasture::harvestHay()\r\n{\r\n\treturn m_properties.harvestHay;\r\n}\r\n\r\nvoid Pasture::setHarvestHay( bool harvest )\r\n{\r\n\tm_properties.harvestHay = harvest;\r\n}\r\n\r\nbool Pasture::tameWild()\r\n{\r\n\treturn m_properties.tameWild;\r\n}\r\n\t\r\nvoid Pasture::setTameWild( bool value )\r\n{\r\n\tm_properties.tameWild = value;\r\n}\r\n\r\nint Pasture::maxNumber()\r\n{\r\n\treturn m_properties.max;\r\n}\r\n\r\nint Pasture::animalSize()\r\n{\r\n\treturn m_properties.animalSize;\r\n}\r\n\r\nvoid Pasture::setMaxMale( int max )\r\n{\r\n\tm_properties.maxMale = max;\r\n\r\n\tint count = 0;\r\n\tQList<unsigned int> newAnimals;\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif ( animal )\r\n\t\t{\r\n\t\t\tif ( animal->gender() == Gender::MALE )\r\n\t\t\t{\r\n\t\t\t\tif ( count < max )\r\n\t\t\t\t{\r\n\t\t\t\t\tnewAnimals.append( id );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tanimal->setPastureID( 0 );\r\n\t\t\t\t}\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnewAnimals.append( id );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_animals = newAnimals;\r\n}\r\n\r\nvoid Pasture::setMaxFemale( int max )\r\n{\r\n\tm_properties.maxFemale = max;\r\n\r\n\tint count = 0;\r\n\tQList<unsigned int> newAnimals;\r\n\tfor ( auto id : m_animals )\r\n\t{\r\n\t\tAnimal* animal = g->cm()->animal( id );\r\n\t\tif ( animal )\r\n\t\t{\r\n\t\t\tif ( animal->gender() == Gender::FEMALE )\r\n\t\t\t{\r\n\t\t\t\tif ( count < max )\r\n\t\t\t\t{\r\n\t\t\t\t\tnewAnimals.append( id );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tanimal->setPastureID( 0 );\r\n\t\t\t\t}\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tnewAnimals.append( id );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_animals = newAnimals;\r\n}\r\n\r\nPosition Pasture::firstPos()\r\n{\r\n\tif ( m_fields.size() )\r\n\t{\r\n\t\treturn m_properties.firstPos;\r\n\t}\r\n\treturn Position();\r\n}"
  },
  {
    "path": "src/game/pasture.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/animal.h\"\r\n#include \"../game/worldobject.h\"\r\n#include \"../game/job.h\"\r\n\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QPair>\r\n#include <QVariantMap>\r\n\r\nclass Job;\r\nclass Game;\r\n\r\nstruct PastureField\r\n{\r\n\tPosition pos;\r\n\tQWeakPointer<Job> job;\r\n\tunsigned int util = 0;\r\n};\r\n\r\nstruct PastureProperties\r\n{\r\n\tQString animalType = \"\";\r\n\r\n\tPosition firstPos;\r\n\r\n\tint max        = 0;\r\n\tint maxMale    = 0;\r\n\tint maxFemale  = 0;\r\n\tint animalSize = 0;\r\n\r\n\tbool onlyAvailable = false;\r\n\tbool tameWild      = false;\r\n\tbool collectEggs   = false;\r\n\tbool harvest       = true;\r\n\tbool harvestHay    = false;\r\n\tint maxHay         = 100;\r\n\r\n\tint maxTroughCapacity = 0;\r\n\tint troughContent     = 0;\r\n\r\n\tQList<qint8> jobPriorities;\r\n\r\n\tQSet<QString> foodSettings;\r\n\r\n\tvoid serialize( QVariantMap& out ) const;\r\n\tPastureProperties() {};\r\n\tPastureProperties( QVariantMap& in );\r\n};\r\n\r\nclass Pasture : public WorldObject\r\n{\r\n\tfriend class AggregatorAgri;\r\n\tQ_DISABLE_COPY_MOVE( Pasture )\r\npublic:\r\n\tPasture( QList<QPair<Position, bool>> tiles, Game* game );\r\n\tPasture( QVariantMap vals, Game* game );\r\n\t//Pasture( const Pasture& other );\r\n\t~Pasture();\r\n\r\n\tQVariant serialize() const;\r\n\r\n\tvoid onTick( quint64 tick, int& count );\r\n\r\n\tvoid addAnimal( unsigned int id );\r\n\r\n\tbool removeTile( const Position & pos );\r\n\tvoid addTile( const Position & pos );\r\n\r\n\tvoid getInfo( int& numPlots, int& numMale, int& numFemale );\r\n\r\n\tbool canDelete();\r\n\tint countTiles();\r\n\r\n\tvoid removeAnimal( unsigned int animalID );\r\n\tvoid removeAllAnimals();\r\n\r\n\tQList<unsigned int> animals()\r\n\t{\r\n\t\treturn m_animals;\r\n\t}\r\n\r\n\tbool addUtil( Position pos, unsigned int itemID );\r\n\tbool removeUtil( Position pos );\r\n\tunsigned int util( Position pos );\r\n\r\n\tPosition randomFieldPos();\r\n\tPosition findShed();\r\n\r\n\tQSet<QString>& foodSettings();\r\n\tvoid addFoodSetting( QString itemSID, QString materialSID );\r\n\tvoid removeFoodSetting( QString itemSID, QString materialSID );\r\n\tvoid addFood( unsigned int itemID );\r\n\tbool eatFromTrough();\r\n\r\n\tvoid setAnimalType( QString type );\r\n\tQString animalType();\r\n\r\n\tbool harvest();\r\n\tvoid setHarvest( bool harvest );\r\n\r\n\tbool harvestHay();\r\n\tvoid setHarvestHay( bool harvest );\r\n\tint maxHay();\r\n\tvoid setMaxHay( int value );\r\n\tint foodLevel();\r\n\tint maxFoodLevel();\r\n\r\n\tint maxNumber();\r\n\tint animalSize();\r\n\r\n\tvoid setMaxMale( int max );\r\n\tvoid setMaxFemale( int max );\r\n\r\n\tbool tameWild();\r\n\tvoid setTameWild( bool value );\r\n\r\n\tPosition firstPos();\r\n\r\nprivate:\r\n\tPastureProperties m_properties;\r\n\r\n\tQMap<unsigned int, PastureField*> m_fields;\r\n\r\n\tQList<unsigned int> m_animals;\r\n};\r\n"
  },
  {
    "path": "src/game/plant.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"plant.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n#include <QRandomGenerator>\r\n\r\n#include <random>\r\n\r\nPlant::Plant() :\r\n\tObject( Position() ),\r\n\tm_plantID( \"None\" )\r\n{\r\n}\r\n\r\nPlant::Plant( Position& pos, QString ID, bool fullyGrown, Game* game ) :\r\n\tg( game ),\r\n\tObject( pos ),\r\n\tm_plantID( ID )\r\n{\r\n\tQVariantMap row = DB::selectRow( \"Plants\", ID );\r\n\r\n\tm_isTree             = ( row.value( \"Type\" ).toString() == \"Tree\" );\r\n\tm_isFruitTree        = ( !row.value( \"FruitItemID\" ).toString().isEmpty() );\r\n\tm_isPlant            = ( row.value( \"Type\" ).toString() == \"Plant\" );\r\n\tm_isMushroom         = ( row.value( \"Type\" ).toString() == \"Mushroom\" );\r\n\tm_isUndergroundPlant = ( row.value( \"Type\" ).toString() == \"UndergroundPlant\" );\r\n\r\n\tm_producesHarvest = row.contains( \"OnHarvest\" );\r\n\r\n\tsetGrowsThisSeason();\r\n\r\n\tif ( fullyGrown )\r\n\t{\r\n\t\tm_state      = DB::numRows( \"Plants_States\", m_plantID ) - 1;\r\n\t\tm_fullyGrown = true;\r\n\t\tif ( m_isTree )\r\n\t\t{\r\n\t\t\tm_matureWood = true;\r\n\t\t\tif ( isFruitTree() )\r\n\t\t\t{\r\n\t\t\t\tm_harvestable = true;\r\n\t\t\t\tm_numFruits   = row.value( \"NumFruitsPerSeason\" ).toInt();\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( m_isPlant )\r\n\t\t{\r\n\t\t\tm_harvestable = true;\r\n\t\t}\r\n\t}\r\n\r\n\tupdateState();\r\n\r\n\tQString growLight = row.value( \"GrowsIn\" ).toString();\r\n\tif ( growLight == \"Sun\" )\r\n\t{\r\n\t\tm_growLight = GrowLight::SUN;\r\n\t}\r\n\telse if ( growLight == \"Dark\" )\r\n\t{\r\n\t\tm_growLight = GrowLight::DARK;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_growLight = GrowLight::SUN_AND_DARK;\r\n\t}\r\n\r\n\tsetGrowTime();\r\n}\r\n\r\nPlant::Plant( QVariant values, Game* game ) :\r\n\tg( game ),\r\n\tObject( Position() )\r\n{\r\n\tQVariantMap in = values.toMap();\r\n\r\n\tm_id               = in.value( \"ID\" ).toUInt();\r\n\tm_position         = Position( in.value( \"Pos\" ).toString() );\r\n\tm_plantID          = in.value( \"PlantID\" ).toString();\r\n\tm_state            = in.value( \"State\" ).toUInt();\r\n\tm_ticksToNextState = in.value( \"TTNS\" ).toInt();\r\n\r\n\tQVariantMap row = DB::selectRow( \"Plants\", m_plantID );\r\n\tQVariantList sl = row[\"States\"].toList();\r\n\tm_fullyGrown    = ( m_state == ( sl.size() - 1 ) );\r\n\t//m_fullyGrown = in.value( \"FullyGrown\" ).toBool();\r\n\tm_matureWood         = in.value( \"MatureWood\" ).toBool();\r\n\tm_harvestable        = in.value( \"Harvestable\" ).toBool();\r\n\tm_producesHarvest    = in.value( \"ProdHarvest\" ).toBool();\r\n\tm_isTree             = in.value( \"IsTree\" ).toBool();\r\n\tm_isFruitTree        = ( !row.value( \"FruitItemID\" ).toString().isEmpty() ); //in.value( \"IsFruitTree\" ).toBool(); //TODO for compatibility with old saves\r\n\tm_isMulti            = in.value( \"IsMulti\" ).toBool();\r\n\tm_isPlant            = in.value( \"IsPlant\" ).toBool();\r\n\tm_isUndergroundPlant = in.value( \"IsUnderground\" ).toBool();\r\n\tm_numFruits          = in.value( \"NumFruits\" ).toInt();\r\n\tm_hasAlpha           = in.value( \"HasAlpha\" ).toBool();\r\n\tm_lightIntensity     = in.value( \"LightIntensity\" ).toInt();\r\n\tsetGrowsThisSeason();\r\n\r\n\tQString growLight = in.value( \"GrowsIn\" ).toString();\r\n\tif ( growLight == \"Sun\" )\r\n\t{\r\n\t\tm_growLight = GrowLight::SUN;\r\n\t}\r\n\telse if ( growLight == \"Dark\" )\r\n\t{\r\n\t\tm_growLight = GrowLight::DARK;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_growLight = GrowLight::SUN_AND_DARK;\r\n\t}\r\n\r\n\tupdateState();\r\n}\r\n\r\nPlant::~Plant()\r\n{\r\n}\r\n\r\nQVariant Plant::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"ID\", m_id );\r\n\tout.insert( \"Pos\", m_position.toString() );\r\n\r\n\tout.insert( \"PlantID\", m_plantID );\r\n\tout.insert( \"State\", m_state );\r\n\tout.insert( \"TTNS\", m_ticksToNextState );\r\n\tout.insert( \"FullyGrown\", m_fullyGrown );\r\n\tout.insert( \"MatureWood\", m_matureWood );\r\n\tout.insert( \"Harvestable\", m_harvestable );\r\n\tout.insert( \"ProdHarvest\", m_producesHarvest );\r\n\tout.insert( \"IsTree\", m_isTree );\r\n\tout.insert( \"IsFruitTree\", m_isFruitTree );\r\n\tout.insert( \"IsMulti\", m_isMulti );\r\n\tout.insert( \"IsPlant\", m_isPlant );\r\n\tout.insert( \"IsUnderground\", m_isUndergroundPlant );\r\n\tout.insert( \"NumFruits\", m_numFruits );\r\n\tout.insert( \"HasAlpha\", m_hasAlpha );\r\n\tout.insert( \"LightIntensity\", m_lightIntensity );\r\n\tswitch ( m_growLight )\r\n\t{\r\n\t\tcase GrowLight::SUN:\r\n\t\t\tout.insert( \"GrowsIn\", \"Sun\" );\r\n\t\t\tbreak;\r\n\t\tcase GrowLight::DARK:\r\n\t\t\tout.insert( \"GrowsIn\", \"Dark\" );\r\n\t\t\tbreak;\r\n\t\tcase GrowLight::SUN_AND_DARK:\r\n\t\t\tout.insert( \"GrowsIn\", \"SunAndDark\" );\r\n\t\t\tbreak;\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nvoid Plant::setGrowsThisSeason()\r\n{\r\n\tQVariantMap row     = DB::selectRow( \"Plants\", m_plantID );\r\n\tQString season      = GameState::seasonString;\r\n\tauto growSeasonList = row.value( \"GrowsInSeason\" ).toString().split( \"|\" );\r\n\tfor ( auto gs : growSeasonList )\r\n\t{\r\n\t\tif ( gs == season )\r\n\t\t{\r\n\t\t\tm_growsThisSeason = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\tm_growsThisSeason = false;\r\n}\r\n\r\nbool Plant::growsThisSeason()\r\n{\r\n\treturn m_growsThisSeason;\r\n}\r\n\r\nOnTickReturn Plant::onTick( quint64 tickNumber, bool dayChanged, bool seasonChanged )\r\n{\r\n\treturn liveOneTick( dayChanged, seasonChanged );\r\n}\r\n\r\nOnTickReturn Plant::liveOneTick( bool dayChanged, bool seasonChanged )\r\n{\r\n\tif ( m_fullyGrown && !seasonChanged )\r\n\t{\r\n\t\treturn OnTickReturn::NOOP;\r\n\t}\r\n\r\n\tif ( seasonChanged )\r\n\t{\r\n\t\tQVariantMap row = DB::selectRow( \"Plants\", m_plantID );\r\n\t\tQString season  = GameState::seasonString;\r\n\r\n\t\tsetGrowsThisSeason();\r\n\r\n\t\t// if is killed in season and is that season\r\n\t\tQString isKilledInSeason = row.value( \"IsKilledInSeason\" ).toString();\r\n\t\tif ( isKilledInSeason == season )\r\n\t\t{\r\n\t\t\tm_state       = 0;\r\n\t\t\tm_harvestable = false;\r\n\t\t\tm_fullyGrown  = false;\r\n\t\t\tm_numFruits   = 0;\r\n\t\t\tsetGrowTime();\r\n\t\t\tupdateState();\r\n\t\t\treturn OnTickReturn::UPDATE;\r\n\t\t}\r\n\t\t// if loses fruit and has fruit\r\n\t\telse if ( harvestable() )\r\n\t\t{\r\n\t\t\tQString losesFruitInSeason = row.value( \"LosesFruitInSeason\" ).toString();\r\n\t\t\tif ( losesFruitInSeason == season )\r\n\t\t\t{\r\n\t\t\t\tm_harvestable = false;\r\n\t\t\t\tm_fullyGrown  = false;\r\n\t\t\t\tm_state       = qMax( 0, m_state - 1 );\r\n\t\t\t\tm_numFruits   = 0;\r\n\t\t\t\tsetGrowTime();\r\n\t\t\t\tupdateState();\r\n\t\t\t\treturn OnTickReturn::UPDATE;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_growsThisSeason )\r\n\t{\r\n\t\tswitch ( m_growLight )\r\n\t\t{\r\n\t\t\tcase GrowLight::SUN:\r\n\t\t\t\tif ( GameState::daylight && g->w()->hasSunlight( m_position ) )\r\n\t\t\t\t\t--m_ticksToNextState;\r\n\t\t\t\tbreak;\r\n\t\t\tcase GrowLight::DARK:\r\n\t\t\t\tif ( !GameState::daylight )\r\n\t\t\t\t\t--m_ticksToNextState;\r\n\t\t\t\tbreak;\r\n\t\t\tcase GrowLight::SUN_AND_DARK:\r\n\t\t\t\t--m_ticksToNextState;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_ticksToNextState == 0 )\r\n\t{\r\n\t\tsetGrowTime();\r\n\t\t++m_state;\r\n\t\tupdateState();\r\n\t\treturn OnTickReturn::UPDATE;\r\n\t}\r\n\treturn OnTickReturn::NOOP;\r\n}\r\n\r\nvoid Plant::setGrowTime()\r\n{\r\n\tauto sl = DB::selectRows( \"Plants_States\", m_plantID );\r\n\r\n\tif ( m_state < sl.size() - 1 )\r\n\t{\r\n\t\tQVariantMap sm     = sl[m_state];\r\n\t\tint ticks          = sm[\"GrowTime\"].toFloat() * Global::util->ticksPerDay;\r\n\t\tint dev            = ticks * 0.05;\r\n\t\tint rand           = ( QRandomGenerator::global()->generate() % dev ) - ( dev / 2 );\r\n\t\tm_ticksToNextState = ticks + rand;\r\n\t\t//float stddev = mean*0.05;\r\n\t\t//std::normal_distribution<float> dist( mean, stddev );\r\n\t\t//m_ticksToNextState = dist( *QRandomGenerator64::global() );\r\n\t}\r\n}\r\n\r\nvoid Plant::updateState()\r\n{\r\n\tauto sl = DB::selectRows( \"Plants_States\", m_plantID );\r\n\r\n\tif ( m_state < sl.size() )\r\n\t{\r\n\t\tQVariantMap sm     = sl[m_state];\r\n\t\tconst bool isMulti = !sm.value( \"Layout\" ).toString().isEmpty();\r\n\t\t//!TODO Logik broken if plants contain multiple multi-phases with different bounding boxes, would need to properly deconstruct the plant first...\r\n\t\t// Check if this can become a multi-sprite plant without colliding with anything\r\n\t\tif ( !m_isMulti && isMulti && !testLayoutMulti( sm.value( \"Layout\" ).toString(), m_position, g ) )\r\n\t\t{\r\n\t\t\tm_state = qMax( 0, m_state - 1 );\r\n\t\t\t\r\n\t\t\tif( !m_sprite )\r\n\t\t\t{\r\n\t\t\t\tm_sprite = g->sf()->createSprite( \"SolidSelectionWall\", { \"Purple\" } );\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tm_isMulti        = isMulti;\r\n\t\tQString spriteID = sm.value( \"SpriteID\" ).toString();\r\n\r\n\t\tm_matureWood  = sm.value( \"Fell\" ).toBool();\r\n\t\tm_harvestable = sm.value( \"Harvest\" ).toBool();\r\n\t\tm_hasAlpha    = sm.value( \"HasAlpha\" ).toBool();\r\n\r\n\t\tint newLightIntens = sm.value( \"LightIntensity\" ).toInt();\r\n\r\n\t\tif ( newLightIntens == 0 && m_lightIntensity )\r\n\t\t{\r\n\t\t\tg->w()->removeLight( m_id );\r\n\t\t}\r\n\t\telse if ( newLightIntens > 0 && !m_lightIntensity )\r\n\t\t{\r\n\t\t\tg->w()->addLight( m_id, m_position, newLightIntens );\r\n\t\t}\r\n\t\telse if ( newLightIntens > 0 && m_lightIntensity > 0 && newLightIntens != m_lightIntensity )\r\n\t\t{\r\n\t\t\tg->w()->moveLight( m_id, m_position, newLightIntens );\r\n\t\t}\r\n\t\tm_lightIntensity = newLightIntens;\r\n\t\tif ( m_harvestable )\r\n\t\t{\r\n\t\t\tm_numFruits = DB::select( \"NumFruitsPerSeason\", \"Plants\", m_plantID ).toInt();\r\n\t\t}\r\n\t\tif ( !m_isMulti )\r\n\t\t{\r\n\t\t\tm_sprite = g->sf()->createSprite( spriteID, { DB::select( \"Material\", \"Plants\", m_plantID ).toString() } );\r\n\t\t\tg->w()->setWallSprite( m_position, m_sprite->uID );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tlayoutMulti( sm.value( \"Layout\" ).toString(), m_numFruits > 0 );\r\n\t\t}\r\n\t}\r\n\tif ( m_state > sl.size() - 1 )\r\n\t{\r\n\t\tm_state = sl.size() - 1;\r\n\t}\r\n\tif ( m_state == sl.size() - 1 )\r\n\t{\r\n\t\tm_fullyGrown = true;\r\n\t}\r\n}\r\n\r\nbool Plant::isFruitTree()\r\n{\r\n\treturn m_isFruitTree;\r\n}\r\n\r\nQString Plant::getDesignation()\r\n{\r\n\tif ( m_isTree )\r\n\t{\r\n\t\tQString materialID = DB::select( \"Material\", \"Plants\", m_plantID ).toString();\r\n\t\treturn S::s( \"$MaterialName_\" + materialID ) + \" \" + S::s( \"$Tree\" );\r\n\t}\r\n\telse if ( m_isPlant || m_isMushroom )\r\n\t{\r\n\t\treturn S::s( \"$MaterialName_\" + m_plantID ) + \" \" + S::s( \"$Plant\" );\r\n\t}\r\n\treturn \"error: unset plant designation\";\r\n}\r\n\r\nbool Plant::reduceOneGrowLevel()\r\n{\r\n\tif ( m_isTree )\r\n\t{\r\n\t\tm_state = qMax( 0, m_state - 1 );\r\n\r\n\t\tsetGrowTime();\r\n\t\tupdateState();\r\n\r\n\t\tm_fullyGrown = false;\r\n\t\tif ( m_state == 0 )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Plant::fell()\r\n{\r\n\tif ( m_isTree )\r\n\t{\r\n\t\tauto rows = DB::selectRows( \"Plants_OnFell\", m_plantID );\r\n\t\tQString itemID;\r\n\t\tQString materialID;\r\n\t\tfor ( auto row : rows )\r\n\t\t{\r\n\t\t\titemID     = row.value( \"ItemID\" ).toString();\r\n\t\t\tmaterialID = row.value( \"MaterialID\" ).toString();\r\n\r\n\t\t\tif ( row.value( \"Random\" ).toInt() > 0 )\r\n\t\t\t{\r\n\t\t\t\tint random = row.value( \"Random\" ).toInt();\r\n\r\n\t\t\t\tint randVal = ( rand() % random ) + 1;\r\n\t\t\t\tfor ( int i = 0; i < randVal; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( m_position, itemID, materialID );\r\n\t\t\t\t}\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tif ( m_matureWood )\r\n\t\t\t{\r\n\t\t\t\tauto sl = DB::selectRows( \"Plants_States\", m_plantID );\r\n\r\n\t\t\t\tif ( m_state < sl.size() )\r\n\t\t\t\t{\r\n\t\t\t\t\tQVariantMap sm = sl[m_state];\r\n\r\n\t\t\t\t\tif ( !sm.value( \"Layout\" ).toString().isEmpty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto ll = DB::selectRows( \"TreeLayouts_Layout\", m_plantID );\r\n\t\t\t\t\t\tfor ( auto vm : ll )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tPosition offset( vm.value( \"Offset\" ).toString() );\r\n\t\t\t\t\t\t\tPosition newPos = m_position + offset;\r\n\t\t\t\t\t\t\tg->w()->setWallSprite( newPos, 0, 0 );\r\n\t\t\t\t\t\t\tg->w()->clearTileFlag( newPos, TileFlag::TF_OCCUPIED );\r\n\t\t\t\t\t\t\tg->w()->clearTileFlag( newPos, TileFlag::TF_OVERSIZE );\r\n\t\t\t\t\t\t\tg->w()->getTile( newPos ).wallType = WT_NOWALL;\r\n\t\t\t\t\t\t\tif ( g->w()->floorType( newPos ) & FT_SOLIDFLOOR )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tg->w()->setTileFlag( newPos, TileFlag::TF_WALKABLE );\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif ( newPos.x == 0 || newPos.x == Global::dimX - 1 || newPos.y == 0 || newPos.y == Global::dimX - 1 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tg->inv()->createItem( m_position, itemID, materialID );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tg->w()->getFloorLevelBelow( newPos, false );\r\n\t\t\t\t\t\t\t\tg->inv()->createItem( newPos, itemID, materialID );\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\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->createItem( m_position, itemID, materialID );\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\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Plant::harvest( Position& pos )\r\n{\r\n\tauto rows = DB::selectRows( \"Plants_OnHarvest\", m_plantID );\r\n\r\n\tfor ( auto row : rows )\r\n\t{\r\n\t\tauto harvItemsList = DB::selectRows( \"Plants_OnHarvest_HarvestedItem\", m_plantID );\r\n\t\tfor ( auto harvItem : harvItemsList )\r\n\t\t{\r\n\t\t\tQString itemID     = harvItem.value( \"ItemID\" ).toString();\r\n\t\t\tQString materialID = harvItem.value( \"MaterialID\" ).toString();\r\n\t\t\tif ( harvItem.contains( \"Chance\" ) )\r\n\t\t\t{\r\n\t\t\t\tfloat chance = harvItem.value( \"Chance\" ).toFloat();\r\n\t\t\t\tif ( chance > 0.0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tint ra = rand() % 100;\r\n\t\t\t\t\tif ( ra < chance * 100 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->createItem( pos, itemID, materialID );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( pos, itemID, materialID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tg->inv()->createItem( pos, itemID, materialID );\r\n\t\t\t}\r\n\t\t}\r\n\t\tQString action = row.value( \"Action\" ).toString();\r\n\t\tif ( action == \"Destroy\" )\r\n\t\t{\r\n\t\t\tif ( !m_lightIntensity )\r\n\t\t\t{\r\n\t\t\t\tg->w()->removeLight( m_id );\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tif ( action == \"ReduceFruitCount\" )\r\n\t\t{\r\n\t\t\tif ( m_numFruits == 0 )\r\n\t\t\t{\r\n\t\t\t\t// something else, most likely winter killed all fruits already\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tm_numFruits = qMax( 0, m_numFruits - 1 );\r\n\t\t\tif ( m_numFruits == 0 )\r\n\t\t\t{\r\n\t\t\t\tm_harvestable = false;\r\n\t\t\t\tm_fullyGrown  = false;\r\n\t\t\t\tm_state       = qMax( 0, m_state - 1 );\r\n\t\t\t\tsetGrowTime();\r\n\t\t\t\tupdateState();\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( action == \"StateOneBack\" )\r\n\t\t{\r\n\t\t\tm_harvestable = false;\r\n\t\t\tm_state       = qMax( 0, m_state - 1 );\r\n\t\t\tsetGrowTime();\r\n\t\t\tupdateState();\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool Plant::harvestable()\r\n{\r\n\treturn m_harvestable;\r\n}\r\n\r\nvoid Plant::layoutMulti( QString layoutSID, bool withFruit )\r\n{\r\n\tPosition extractPos = m_position.eastOf();\r\n\tif ( !g->w()->isWalkable( extractPos ) )\r\n\t{\r\n\t\textractPos = m_position.southOf();\r\n\r\n\t\tif ( !g->w()->isWalkable( extractPos ) )\r\n\t\t{\r\n\t\t\textractPos = m_position.westOf();\r\n\r\n\t\t\tif ( !g->w()->isWalkable( extractPos ) )\r\n\t\t\t{\r\n\t\t\t\textractPos = m_position.northOf();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tauto ll = DB::selectRows( \"TreeLayouts_Layout\", layoutSID );\r\n\r\n\tbool _isFruitTree = isFruitTree();\r\n\r\n\tfor ( auto vm : ll )\r\n\t{\r\n\t\tPosition offset( vm.value( \"Offset\" ).toString() );\r\n\r\n\t\tQString spriteID = vm.value( \"SpriteID\" ).toString();\r\n\r\n\t\tif ( offset == Position( 0, 0, 0 ) )\r\n\t\t{\r\n\t\t\tm_sprite = g->sf()->createSprite( spriteID, { \"None\" } );\r\n\t\t}\r\n\r\n\t\tif ( withFruit && _isFruitTree )\r\n\t\t{\r\n\t\t\tif ( vm.value( \"FruitPos\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\tif ( rand() % 3 == 0 )\r\n\t\t\t\t\tspriteID += \"WithFruit\";\r\n\t\t\t}\r\n\t\t}\r\n\t\tSprite* sprite = g->sf()->createSprite( spriteID, { \"None\" } );\r\n\t\tif ( ( m_position.z + offset.z ) < Global::dimZ )\r\n\t\t{\r\n\t\t\tPosition pos = m_position + offset;\r\n\r\n\t\t\tg->w()->setWallSprite( pos, sprite->uID, Global::util->rotString2Char( vm.value( \"Rotation\" ).toString() ) );\r\n\t\t\tg->w()->clearTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\t\t\tg->w()->setTileFlag( pos, TileFlag::TF_OCCUPIED );\r\n\t\t\tg->w()->setTileFlag( pos, TileFlag::TF_OVERSIZE );\r\n\r\n\t\t\tg->w()->getTile( pos ).wallType = offset == Position() ? static_cast<WallType>( WT_MOVEBLOCKING | WT_VIEWBLOCKING ) : static_cast<WallType>( WT_MOVEBLOCKING | WT_VIEWBLOCKING );\r\n\r\n\t\t\tg->gm()->forceMoveGnomes( pos, extractPos );\r\n\t\t\tg->cm()->forceMoveAnimals( pos, extractPos );\r\n\t\t\tg->w()->expelTileItems( pos, extractPos );\r\n\t\t\tif ( m_isTree )\r\n\t\t\t{\r\n\t\t\t\tg->w()->setTileFlag( pos, TileFlag::TF_SUNLIGHT );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Plant::testLayoutMulti( QString layoutSID, Position rootPos, Game* game )\r\n{\r\n\tauto ll = DB::selectRows( \"TreeLayouts_Layout\", layoutSID );\r\n\tfor ( const auto& vm : ll )\r\n\t{\r\n\t\tconst Position offset( vm.value( \"Offset\" ).toString() );\r\n\t\tconst Position pos = rootPos + offset;\r\n\t\tconst auto tf      = game->w()->getTileFlag( pos );\r\n\t\tconst auto ft      = game->w()->floorType( pos );\r\n\t\tconst auto wt      = game->w()->wallType( pos );\r\n\r\n\t\t// Floating floors above the ground\r\n\t\tif ( offset.z > 0 && ft != FT_NOFLOOR )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// Any existing wall\r\n\t\tif ( wt != WT_NOWALL )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// Any existing plant\r\n\t\tif ( tf & TileFlag::TF_OCCUPIED )\r\n\t\t{\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 Plant::speedUpGrowth( unsigned int ticks )\r\n{\r\n\tif ( m_ticksToNextState > 1 )\r\n\t{\r\n\t\tticks = qMin( ticks, m_ticksToNextState - 1 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tticks = 0;\r\n\t}\r\n\r\n\tm_ticksToNextState = m_ticksToNextState - ticks;\r\n}\r\n"
  },
  {
    "path": "src/game/plant.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"object.h\"\r\n\r\n#include <QString>\r\n\r\nclass Game;\r\n\r\nenum class GrowLight : unsigned char\r\n{\r\n\tSUN,\r\n\tDARK,\r\n\tSUN_AND_DARK\r\n};\r\n\r\nenum class OnTickReturn : unsigned char\r\n{\r\n\tNOOP,\r\n\tUPDATE,\r\n\tDESTROY\r\n};\r\n\r\nclass Plant : public Object\r\n{\r\npublic:\r\n\tPlant();\r\n\tPlant( Position& pos, QString ID, bool fullyGrown, Game* game );\r\n\tPlant( QVariant values, Game* game );\r\n\t~Plant();\r\n\r\n\tvirtual QVariant serialize() const;\r\n\r\n\tOnTickReturn onTick( quint64 tickNumber, bool dayChanged, bool seasonChanged );\r\n\r\n\tOnTickReturn liveOneTick( bool dayChanged = false, bool seasonChanged = false );\r\n\r\n\tQString getDesignation();\r\n\r\n\tbool isTree()\r\n\t{\r\n\t\treturn m_isTree;\r\n\t}\r\n\tbool isMushroom()\r\n\t{\r\n\t\treturn m_isMushroom;\r\n\t}\r\n\tbool isPlant()\r\n\t{\r\n\t\treturn m_isPlant;\r\n\t}\r\n\tbool isFruitTree();\r\n\r\n\tbool fullGrown()\r\n\t{\r\n\t\treturn m_fullyGrown;\r\n\t}\r\n\tbool producesHarvest()\r\n\t{\r\n\t\treturn m_producesHarvest;\r\n\t}\r\n\tbool harvestable();\r\n\tbool matureWood()\r\n\t{\r\n\t\treturn m_isTree && m_matureWood;\r\n\t}\r\n\r\n\tbool hasAlpha()\r\n\t{\r\n\t\treturn m_hasAlpha;\r\n\t}\r\n\tint lightIntensity()\r\n\t{\r\n\t\treturn m_lightIntensity;\r\n\t}\r\n\r\n\t//return true when plant is destroyed\r\n\tbool fell();\r\n\t//return true when plant is destroyed\r\n\t// param pos Position of the harvest to be created\r\n\tbool harvest( Position& pos );\r\n\t//return true when plant is destroyed\r\n\tbool reduceOneGrowLevel();\r\n\r\n\tvoid setSprite( Sprite* s )\r\n\t{\r\n\t\tm_sprite = s;\r\n\t}\r\n\tSprite* getSprite()\r\n\t{\r\n\t\treturn m_sprite;\r\n\t}\r\n\r\n\tvoid speedUpGrowth( unsigned int ticks );\r\n\r\n\tbool growsThisSeason();\r\n\tvoid setGrowsThisSeason();\r\n\r\n\tstatic bool testLayoutMulti( QString layoutSID, Position rootPos, Game* game );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQString m_plantID;\r\n\r\n\tSprite* m_sprite = 0;\r\n\r\n\tqint8 m_state                   = 0;\r\n\tunsigned int m_ticksToNextState = 0;\r\n\tbool m_fullyGrown               = false;\r\n\tbool m_matureWood               = false;\r\n\tbool m_harvestable              = false;\r\n\tbool m_producesHarvest          = false;\r\n\r\n\tbool m_isTree             = false;\r\n\tbool m_isFruitTree        = false;\r\n\tbool m_isMulti            = false;\r\n\tbool m_isPlant            = false;\r\n\tbool m_isMushroom         = false;\r\n\tbool m_isUndergroundPlant = false;\r\n\tbool m_hasAlpha           = false;\r\n\tint m_lightIntensity      = 0;\r\n\r\n\tbool m_growsThisSeason = true;\r\n\r\n\tGrowLight m_growLight = GrowLight::SUN;\r\n\r\n\tint m_numFruits = 0;\r\n\r\n\tvoid setGrowTime();\r\n\tvoid updateState();\r\n\tvoid layoutMulti( QString layoutSID, bool withFruit = false );\r\n};\r\n"
  },
  {
    "path": "src/game/room.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"room.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../game/game.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QString>\r\n\r\nRoom::Room() :\r\n\tWorldObject( nullptr )\r\n{\r\n}\r\n\r\nRoom::Room( QList<QPair<Position, bool>> tiles, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_id = GameState::createID();\r\n\r\n\tm_name = \"Room \"; // + QString::number( m_id );\r\n\r\n\tint i = 1;\r\n\tfor ( auto p : tiles )\r\n\t{\r\n\t\tif ( p.second )\r\n\t\t{\r\n\t\t\taddTile( p.first );\r\n\t\t}\r\n\t}\r\n\r\n\tcheckRoofed();\r\n\tcheckEnclosed();\r\n}\r\n\r\nRoom::~Room()\r\n{\r\n\tfor ( const auto& field : m_fields )\r\n\t{\r\n\t\tdelete field;\r\n\t}\r\n}\r\n\r\nvoid Room::addTile( const Position & pos )\r\n{\r\n\tRoomTile* rt = new RoomTile;\r\n\trt->pos      = pos;\r\n\trt->furnitureID = g->w()->getFurnitureOnTile( pos );\r\n\r\n\tm_fields.insert( pos.toInt(), rt );\r\n\r\n\tg->w()->setTileFlag( rt->pos, TileFlag::TF_ROOM );\r\n}\r\n\r\nRoom::Room( QVariantMap vals, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_id             = vals.value( \"ID\" ).toUInt();\r\n\tm_owner          = vals.value( \"Owner\" ).toUInt();\r\n\tm_lastUpdateTick = vals.value( \"LastUpdate\" ).value<quint64>();\r\n\tm_name           = vals.value( \"Name\" ).toString();\r\n\tm_active         = vals.value( \"Active\" ).toBool();\r\n\tm_type           = (RoomType)vals.value( \"Type\" ).toInt();\r\n\r\n\tQVariantList vfl = vals.value( \"Fields\" ).toList();\r\n\tfor ( auto vf : vfl )\r\n\t{\r\n\t\tRoomTile* rt    = new RoomTile;\r\n\t\trt->pos         = Position( vf.toMap().value( \"Pos\" ).toString() );\r\n\t\trt->furnitureID = vf.toMap().value( \"FurID\" ).toUInt();\r\n\t\tm_fields.insert( rt->pos.toInt(), rt );\r\n\t}\r\n}\r\n\r\nQVariant Room::serialize() const\r\n{\r\n\tQVariantMap out;\r\n\r\n\tout.insert( \"ID\", m_id );\r\n\tout.insert( \"Owner\", m_owner );\r\n\tout.insert( \"LastUpdate\", m_lastUpdateTick );\r\n\tout.insert( \"Active\", m_active );\r\n\tout.insert( \"Type\", (unsigned char)m_type );\r\n\r\n\tQVariantList fields;\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tQVariantMap fima;\r\n\t\tfima.insert( \"Pos\", field->pos.toString() );\r\n\t\tfima.insert( \"FurID\", field->furnitureID );\r\n\t\tfields.append( fima );\r\n\t}\r\n\tout.insert( \"Fields\", fields );\r\n\tout.insert( \"Name\", m_name );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Room::onTick( quint64 tick )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn;\r\n\tbool lastUpdateLongAgo = ( tick - m_lastUpdateTick ) > 200;\r\n\tif ( lastUpdateLongAgo )\r\n\t{\r\n\t\tcheckEnclosed();\r\n\t\tcheckRoofed();\r\n\t\tm_lastUpdateTick = tick;\r\n\t}\r\n}\r\n\r\nbool Room::removeTile( const Position & pos )\r\n{\r\n\tRoomTile* rt   = m_fields.value( pos.toInt() );\r\n\t// remove tile and remove tile flag\r\n\tm_fields.remove( pos.toInt() );\r\n\tg->w()->clearTileFlag( pos, TileFlag::TF_ROOM );\r\n\tdelete rt;\r\n\r\n\tunsigned int itemID = rt->furnitureID;\r\n\tif ( itemID )\r\n\t{\r\n\t\tif ( g->inv()->itemSID( itemID ) == \"AlarmBell\" )\r\n\t\t{\r\n\t\t\tbool found = false;\r\n\t\t\tfor ( auto& f : m_fields )\r\n\t\t\t{\r\n\t\t\t\tif ( f->furnitureID )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( g->inv()->itemSID( f->furnitureID ) == \"AlarmBell\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfound = true;\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\tm_hasAlarmBell = found;\r\n\t\t}\r\n\t}\r\n\r\n\t// if last tile deleted return true\r\n\treturn m_fields.empty();\r\n}\r\n\r\nvoid Room::addFurniture( unsigned int itemUID, Position pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tm_fields[pos.toInt()]->furnitureID = itemUID;\r\n\t\tif ( itemUID )\r\n\t\t{\r\n\t\t\tg->inv()->setConstructed( itemUID, true );\r\n\t\t\tg->inv()->setItemPos( itemUID, pos );\r\n\t\t}\r\n\t\tif ( g->inv()->itemSID( itemUID ) == \"AlarmBell\" )\r\n\t\t{\r\n\t\t\tm_hasAlarmBell = true;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Room::removeFurniture( const Position& pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tRoomTile* rt = m_fields[pos.toInt()];\r\n\r\n\t\tunsigned int itemID = rt->furnitureID;\r\n\t\trt->furnitureID     = 0;\r\n\t\tif ( itemID )\r\n\t\t{\r\n\t\t\tif ( g->inv()->itemSID( itemID ) == \"AlarmBell\" )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto& f : m_fields )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( f->furnitureID )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( g->inv()->itemSID( f->furnitureID ) == \"AlarmBell\" )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn;\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\tm_hasAlarmBell = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Room::checkRoofed()\r\n{\r\n\tbool roofed = true;\r\n\tfor ( auto tile : m_fields )\r\n\t{\r\n\t\tPosition pos = tile->pos;\r\n\t\tpos.z        = pos.z + 1;\r\n\t\tTile& _tile  = g->w()->getTile( pos );\r\n\t\tif ( !( (bool)( _tile.floorType & FloorType::FT_SOLIDFLOOR ) ) )\r\n\t\t{\r\n\t\t\troofed = false;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tm_roofed = roofed;\r\n\treturn roofed;\r\n}\r\n\r\nbool Room::checkEnclosed()\r\n{\r\n\tbool enclosed = true;\r\n\tfor ( auto tile : m_fields )\r\n\t{\r\n\t\tPosition posi = tile->pos;\r\n\r\n\t\tPosition pos( posi.x, posi.y - 1, posi.z );\r\n\t\tif ( !m_fields.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tTile& tn = g->w()->getTile( pos );\r\n\t\t\tif ( !( (bool)( tn.wallType & WT_SOLIDWALL ) || (bool)( tn.flags & TileFlag::TF_DOOR ) ) )\r\n\t\t\t{\r\n\t\t\t\tenclosed = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpos = Position( posi.x, posi.y + 1, posi.z );\r\n\t\tif ( !m_fields.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tTile& tn = g->w()->getTile( pos );\r\n\t\t\tif ( !( (bool)( tn.wallType & WT_SOLIDWALL ) || (bool)( tn.flags & TileFlag::TF_DOOR ) ) )\r\n\t\t\t{\r\n\t\t\t\tenclosed = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpos = Position( posi.x - 1, posi.y, posi.z );\r\n\t\tif ( !m_fields.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tTile& tn = g->w()->getTile( pos );\r\n\t\t\tif ( !( (bool)( tn.wallType & WT_SOLIDWALL ) || (bool)( tn.flags & TileFlag::TF_DOOR ) ) )\r\n\t\t\t{\r\n\t\t\t\tenclosed = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tpos = Position( posi.x + 1, posi.y, posi.z );\r\n\t\tif ( !m_fields.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tTile& tn = g->w()->getTile( pos );\r\n\t\t\tif ( !( (bool)( tn.wallType & WT_SOLIDWALL ) || (bool)( tn.flags & TileFlag::TF_DOOR ) ) )\r\n\t\t\t{\r\n\t\t\t\tenclosed = false;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tm_enclosed = enclosed;\r\n\treturn enclosed;\r\n}\r\n\r\nQList<unsigned int> Room::beds()\r\n{\r\n\tQList<unsigned int> beds;\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tif ( g->inv()->isInGroup( \"Furniture\", \"Beds\", field->furnitureID ) )\r\n\t\t{\r\n\t\t\tbeds.append( field->furnitureID );\r\n\t\t}\r\n\t}\r\n\treturn beds;\r\n}\r\n\r\nQList<unsigned int> Room::chairs()\r\n{\r\n\tQList<unsigned int> chairs;\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tif ( g->inv()->isInGroup( \"Furniture\", \"Chairs\", field->furnitureID ) )\r\n\t\t{\r\n\t\t\tchairs.append( field->furnitureID );\r\n\t\t}\r\n\t}\r\n\treturn chairs;\r\n}\r\n\r\nbool Room::hasAlarmBell() const\r\n{\r\n\treturn m_hasAlarmBell;\r\n}\r\n\r\nvoid Room::setHasAlarmBell( bool value )\r\n{\r\n\tm_hasAlarmBell = value;\r\n}\r\n\r\nPosition Room::firstBellPos() const\r\n{\r\n\tfor ( const auto& f : m_fields )\r\n\t{\r\n\t\tif ( f->furnitureID )\r\n\t\t{\r\n\t\t\tif ( g->inv()->itemSID( f->furnitureID ) == \"AlarmBell\" )\r\n\t\t\t{\r\n\t\t\t\treturn f->pos;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn Position();\r\n}\r\n\r\nQList<Position> Room::allBellPos() const\r\n{\r\n\tQList<Position> out;\r\n\tfor ( const auto& f : m_fields )\r\n\t{\r\n\t\tif ( f->furnitureID )\r\n\t\t{\r\n\t\t\tif ( g->inv()->itemSID( f->furnitureID ) == \"AlarmBell\" )\r\n\t\t\t{\r\n\t\t\t\tout.append( f->pos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nPosition Room::randomTilePos() const\r\n{\r\n\tif ( m_fields.size() )\r\n\t{\r\n\t\tauto id = rand() % m_fields.size();\r\n\t\tfor ( auto rt : m_fields )\r\n\t\t{\r\n\t\t\tif ( id == 0 )\r\n\t\t\t{\r\n\t\t\t\treturn rt->pos;\r\n\t\t\t}\r\n\t\t\t--id;\r\n\t\t}\r\n\t}\r\n\treturn Position();\r\n}\r\n\r\nunsigned int Room::value()\r\n{\r\n\tunsigned int out = 0;\r\n\tfor ( const auto& f : m_fields )\r\n\t{\r\n\t\tif ( f->furnitureID )\r\n\t\t{\r\n\t\t\tout += g->inv()->value( f->furnitureID );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n"
  },
  {
    "path": "src/game/room.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../base/priorityqueue.h\"\r\n\r\n#include \"../game/worldobject.h\"\r\n\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QPair>\r\n#include <QtGlobal>\r\n\r\nenum class RoomType : unsigned char\r\n{\r\n\tNotSet,\r\n\tPersonalRoom,\r\n\tDorm,\r\n\tDining,\r\n\tHospital\r\n};\r\n\r\nstruct RoomTile\r\n{\r\n\tPosition pos;\r\n\tunsigned int furnitureID = 0;\r\n};\r\n\r\nclass Job;\r\n\r\nclass Room : public WorldObject\r\n{\r\n\tQ_DISABLE_COPY_MOVE( Room )\r\npublic:\r\n\tRoom();\r\n\tRoom( QList<QPair<Position, bool>> tiles, Game* game );\r\n\tRoom( QVariantMap vals, Game* game );\r\n\t~Room();\r\n\r\n\tQVariant serialize() const;\r\n\r\n\tQMap<unsigned int, RoomTile*>& getFields()\r\n\t{\r\n\t\treturn m_fields;\r\n\t}\r\n\r\n\tvoid onTick( quint64 tick );\r\n\r\n\t// return true if last tile was removed\r\n\tbool removeTile( const Position & pos );\r\n\tvoid addTile( const Position & pos );\r\n\r\n\tvoid setType( RoomType type )\r\n\t{\r\n\t\tm_type = type;\r\n\t};\r\n\tRoomType type() const\r\n\t{\r\n\t\treturn m_type;\r\n\t}\r\n\r\n\tvoid addFurniture( unsigned int itemUID, Position pos );\r\n\tvoid removeFurniture( const Position& pos );\r\n\r\n\tbool checkRoofed();\r\n\tbool checkEnclosed();\r\n\r\n\tbool roofed() const\r\n\t{\r\n\t\treturn m_roofed;\r\n\t}\r\n\tbool enclosed() const\r\n\t{\r\n\t\treturn m_enclosed;\r\n\t}\r\n\r\n\tunsigned int value();\r\n\r\n\tvoid setOwner( unsigned int id )\r\n\t{\r\n\t\tm_owner = id;\r\n\t}\r\n\tunsigned int owner() const\r\n\t{\r\n\t\treturn m_owner;\r\n\t}\r\n\r\n\tQList<unsigned int> beds();\r\n\tQList<unsigned int> chairs();\r\n\r\n\tbool hasAlarmBell() const;\r\n\tvoid setHasAlarmBell( bool value );\r\n\r\n\tPosition firstBellPos() const;\r\n\tQList<Position> allBellPos() const;\r\n\r\n\tPosition randomTilePos() const;\r\n\r\nprivate:\r\n\tquint64 m_lastUpdateTick = 0;\r\n\r\n\tunsigned int m_owner = 0;\r\n\tbool m_roofed        = false;\r\n\tbool m_enclosed      = false;\r\n\tbool m_hasAlarmBell  = false;\r\n\r\n\tQMap<unsigned int, RoomTile*> m_fields;\r\n\r\n\tRoomType m_type = RoomType::NotSet;\r\n};\r\n"
  },
  {
    "path": "src/game/roommanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"roommanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QDebug>\r\n\r\nRoomManager::RoomManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n\tm_errorDoor.name = \"Error Door\";\r\n}\r\n\r\nRoomManager::~RoomManager()\r\n{\r\n\tfor ( const auto& room : m_rooms )\r\n\t{\r\n\t\tdelete room;\r\n\t}\r\n}\r\n\r\nvoid RoomManager::onTick( quint64 tick )\r\n{\r\n\tfor ( const auto& room : m_rooms )\r\n\t{\r\n\t\troom->onTick( tick );\r\n\t}\r\n}\r\n\r\nvoid RoomManager::addRoom( Position firstClick, QList<QPair<Position, bool>> fields, RoomType type )\r\n{\r\n\tif ( m_allRoomTiles.contains( firstClick ) )\r\n\t{\r\n\t\tunsigned int spID = m_allRoomTiles.value( firstClick );\r\n\t\tRoom& sp          = *m_rooms[spID];\r\n\t\tfor ( auto p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second && !m_allRoomTiles.contains( p.first ) )\r\n\t\t\t{\r\n\t\t\t\tm_allRoomTiles.insert( p.first, spID );\r\n\t\t\t\tsp.addTile( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tauto sp = new Room( fields, g );\r\n\t\tfor ( auto p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tm_allRoomTiles.insert( p.first, sp->id() );\r\n\t\t\t}\r\n\t\t}\r\n\t\tsp->setType( type );\r\n\r\n\t\tswitch( type )\r\n\t\t{\r\n\t\t\tcase RoomType::PersonalRoom:\r\n\t\t\t\tsp->setName( \"Personal Room\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase RoomType::Dorm:\r\n\t\t\t\tsp->setName( \"Dormitory\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase RoomType::Hospital:\r\n\t\t\t\tsp->setName( \"Hospital\" );\r\n\t\t\t\tbreak;\r\n\t\t\tcase RoomType::Dining:\r\n\t\t\t\tsp->setName( \"Dining Room\" );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tm_rooms.insert( sp->id(), sp );\r\n\t}\r\n}\r\n\r\nvoid RoomManager::addNoPass( Position firstClick, QList<QPair<Position, bool>> fields )\r\n{\r\n\tfor ( auto p : fields )\r\n\t{\r\n\t\tif ( p.second )\r\n\t\t{\r\n\t\t\tg->m_world->setTileFlag( p.first, TileFlag::TF_NOPASS );\r\n\t\t\tg->m_world->regionMap().updatePosition( p.first );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid RoomManager::load( QVariantMap vals )\r\n{\r\n\tauto sp = new Room( vals, g );\r\n\tfor ( auto sf : vals.value( \"Fields\" ).toList() )\r\n\t{\r\n\t\tauto sfm = sf.toMap();\r\n\t\tm_allRoomTiles.insert( Position( sfm.value( \"Pos\" ) ), sp->id() );\r\n\t\tauto furID = sfm.value( \"FurID\" ).toUInt();\r\n\t\tif ( g->m_inv->itemSID( furID ) == \"AlarmBell\" )\r\n\t\t{\r\n\t\t\tsp->setHasAlarmBell( true );\r\n\t\t}\r\n\t}\r\n\tm_rooms.insert( sp->id(), sp );\r\n}\r\n\r\nvoid RoomManager::removeRoom( unsigned int id )\r\n{\r\n\tauto it = m_rooms.find( id );\r\n\tif ( it != m_rooms.end() )\r\n\t{\r\n\t\tfor ( auto field = m_allRoomTiles.begin(); field != m_allRoomTiles.end(); )\r\n\t\t{\r\n\t\t\tif ( field.value() == it.value()->id() )\r\n\t\t\t{\r\n\t\t\t\tit.value()->removeTile( field.key() );\r\n\t\t\t\tfield = m_allRoomTiles.erase( field );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t++field;\r\n\t\t\t}\r\n\t\t}\r\n\t\tdelete it.value();\r\n\t\tm_rooms.erase( it );\r\n\t}\r\n}\r\n\r\nvoid RoomManager::removeTile( Position pos )\r\n{\r\n\tRoom* sp = getRoomAtPos( pos );\r\n\tif ( sp )\r\n\t{\r\n\t\tif ( sp->removeTile( pos ) )\r\n\t\t{\r\n\t\t\tm_rooms.remove( sp->id() );\r\n\t\t}\r\n\t}\r\n\tm_allRoomTiles.remove( pos );\r\n}\r\n\r\nRoom* RoomManager::getRoomAtPos( Position pos )\r\n{\r\n\tif ( m_allRoomTiles.contains( pos ) )\r\n\t{\r\n\t\treturn getRoom( m_allRoomTiles[pos] );\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nRoom* RoomManager::getRoom( unsigned int id )\r\n{\r\n\tif ( m_rooms.contains( id ) )\r\n\t{\r\n\t\treturn m_rooms[id];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nconst QHash<unsigned int, Room*>& RoomManager::allRooms()\r\n{\r\n\treturn m_rooms;\r\n}\r\n\r\nconst QHash<Position, Door>& RoomManager::allDoors()\r\n{\r\n\treturn m_doors;\r\n}\r\n\r\nvoid RoomManager::addFurniture( unsigned int itemUID, Position pos )\r\n{\r\n\tRoom* room = getRoomAtPos( pos );\r\n\tif ( room )\r\n\t{\r\n\t\troom->addFurniture( itemUID, pos );\r\n\t}\r\n}\r\n\r\nvoid RoomManager::removeFurniture( Position pos )\r\n{\r\n\tRoom* room = getRoomAtPos( pos );\r\n\tif ( room )\r\n\t{\r\n\t\troom->removeFurniture( pos );\r\n\t}\r\n}\r\n\r\nvoid RoomManager::addDoor( Position pos, unsigned int itemUID, unsigned int materialUID )\r\n{\r\n\tDoor door;\r\n\tdoor.pos         = pos;\r\n\tdoor.itemUID     = itemUID;\r\n\tdoor.materialUID = materialUID;\r\n\tm_doors.insert( pos, door );\r\n}\r\n\r\nvoid RoomManager::removeDoor( Position pos )\r\n{\r\n\tm_doors.remove( pos );\r\n}\r\n\r\nvoid RoomManager::loadDoor( QVariantMap vm )\r\n{\r\n\tDoor door;\r\n\tdoor.pos           = Position( vm.value( \"Pos\" ).toString() );\r\n\tdoor.itemUID       = vm.value( \"ItemUID\" ).toUInt();\r\n\tdoor.materialUID   = vm.value( \"MaterialUID\" ).toUInt();\r\n\tdoor.name          = vm.value( \"Name\" ).toString();\r\n\tdoor.blockGnomes   = vm.value( \"BlockGnomes\" ).toBool();\r\n\tdoor.blockAnimals  = vm.value( \"BlockAnimals\" ).toBool();\r\n\tdoor.blockMonsters = vm.value( \"BlockMonsters\" ).toBool();\r\n\tm_doors.insert( door.pos, door );\r\n\r\n\tg->m_world->getTile( door.pos ).wallSpriteUID = g->m_inv->spriteID( door.itemUID );\r\n\tunsigned int nextItem                         = g->m_inv->getFirstObjectAtPosition( door.pos );\r\n\tif ( nextItem )\r\n\t{\r\n\t\tg->m_world->setItemSprite( door.pos, g->m_inv->spriteID( nextItem ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tg->m_world->setItemSprite( door.pos, 0 );\r\n\t}\r\n}\r\n\r\nDoor* RoomManager::getDoor( unsigned int tileUID )\r\n{\r\n\tif ( m_doors.contains( tileUID ) )\r\n\t{\r\n\t\treturn &m_doors[tileUID];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQList<unsigned int> RoomManager::getDorms()\r\n{\r\n\tQList<unsigned int> out;\r\n\r\n\tfor ( const auto& room : m_rooms)\r\n\t{\r\n\t\tif ( room->type() == RoomType::Dorm )\r\n\t\t{\r\n\t\t\tout.append( room->id() );\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nQList<unsigned int> RoomManager::getDinings()\r\n{\r\n\tQList<unsigned int> out;\r\n\r\n\tfor ( const auto& room : m_rooms )\r\n\t{\r\n\t\tif ( room->type() == RoomType::Dining )\r\n\t\t{\r\n\t\t\tout.append( room->id() );\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nbool RoomManager::isRoom( Position pos ) const\r\n{\r\n\treturn m_allRoomTiles.contains( pos );\r\n}\r\n\r\nbool RoomManager::isDining( Position pos )\r\n{\r\n\tauto room = getRoomAtPos( pos );\r\n\tif (room)\r\n\t{\r\n\t\tif ( room->type() == RoomType::Dining )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RoomManager::allowBell( Position pos )\r\n{\r\n\tauto room = getRoomAtPos( pos );\r\n\tif ( room )\r\n\t{\r\n\t\tif ( room->type() == RoomType::Dining )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RoomManager::isDoor( const unsigned int tileUID )\r\n{\r\n\treturn m_doors.contains( tileUID );\r\n}\r\n\r\nbool RoomManager::blockGnomes( const unsigned int tileUID )\r\n{\r\n\tif ( m_doors.contains( tileUID ) )\r\n\t{\r\n\t\treturn m_doors[tileUID].blockGnomes;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RoomManager::blockAnimals( const unsigned int tileUID )\r\n{\r\n\tif ( m_doors.contains( tileUID ) )\r\n\t{\r\n\t\treturn m_doors[tileUID].blockAnimals;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RoomManager::blockMonsters( const unsigned int tileUID )\r\n{\r\n\tif ( m_doors.contains( tileUID ) )\r\n\t{\r\n\t\treturn m_doors[tileUID].blockMonsters;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RoomManager::createAlarmJob( unsigned int roomID )\r\n{\r\n\tauto room = getRoom( roomID );\r\n\tif ( room )\r\n\t{\r\n\t\tif ( room->type() == RoomType::Dining )\r\n\t\t{\r\n\t\t\tauto pos = room->firstBellPos();\r\n\r\n\t\t\tif ( pos.isZero() )\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"create alarm job - no bell\";\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tif ( g->m_jobManager->addJob( \"SoundAlarm\", pos, 0 ) )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//qDebug() << \"create alarm job - create job returned 0\";\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool RoomManager::cancelAlarmJob( unsigned int roomID )\r\n{\r\n\tauto room = getRoom( roomID );\r\n\tif ( room )\r\n\t{\r\n\t\tif ( room->type() == RoomType::Dining )\r\n\t\t{\r\n\t\t\tauto posList = room->allBellPos();\r\n\r\n\t\t\tfor ( const auto& pos : posList )\r\n\t\t\t{\r\n\t\t\t\tg->m_jobManager->cancelJob( pos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}"
  },
  {
    "path": "src/game/roommanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/room.h\"\r\n\r\n#include <QSet>\r\n\r\nclass Job;\r\nclass Room;\r\nclass Game;\r\n\r\nstruct Door\r\n{\r\n\tPosition pos;\r\n\tQString name             = \"Door\";\r\n\tunsigned int itemUID     = 0;\r\n\tunsigned int materialUID = 0;\r\n\tbool blockGnomes         = false;\r\n\tbool blockAnimals        = true;\r\n\tbool blockMonsters       = true;\r\n};\r\n\r\nclass RoomManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( RoomManager )\r\npublic:\r\n\tRoomManager() = delete;\r\n\tRoomManager( Game* parent );\r\n\t~RoomManager();\r\n\r\n\tvoid onTick( quint64 tick );\r\n\r\n\tvoid addRoom( Position firstClick, QList<QPair<Position, bool>> fields, RoomType type );\r\n\tvoid addNoPass( Position firstClick, QList<QPair<Position, bool>> fields );\r\n\tvoid load( QVariantMap vals );\r\n\r\n\tvoid addFurniture( unsigned int itemUID, Position pos );\r\n\tvoid removeFurniture( Position pos );\r\n\r\n\tvoid removeRoom( unsigned int id );\r\n\tvoid removeTile( Position pos );\r\n\r\n\tbool isRoom( Position pos ) const;\r\n\tbool isDining( Position pos );\r\n\tbool allowBell( Position pos );\r\n\r\n\tRoom* getRoomAtPos( Position pos );\r\n\tRoom* getRoom( unsigned int id );\r\n\r\n\tconst QHash<unsigned int, Room*>& allRooms();\r\n\tconst QHash<Position, Door>& allDoors();\r\n\r\n\tQList<unsigned int> getDorms();\r\n\tQList<unsigned int> getDinings();\r\n\r\n\tvoid addDoor( Position pos, unsigned int itemID, unsigned int materialUID );\r\n\tvoid removeDoor( Position pos );\r\n\tvoid loadDoor( QVariantMap vm );\r\n\r\n\tDoor* getDoor( unsigned int tileUID );\r\n\r\n\tbool isDoor( const unsigned int tileUID );\r\n\tbool blockGnomes( const unsigned int tileUID );\r\n\tbool blockAnimals( const unsigned int tileUID );\r\n\tbool blockMonsters( const unsigned int tileUID );\r\n\r\n\tbool createAlarmJob( unsigned int roomID );\r\n\tbool cancelAlarmJob( unsigned int roomID );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQHash<unsigned int, Room*> m_rooms;\r\n\tQHash<Position, unsigned int> m_allRoomTiles;\r\n\r\n\tQHash<Position, Door> m_doors;\r\n\r\n\tDoor m_errorDoor;\r\n};\r\n"
  },
  {
    "path": "src/game/soundmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"soundmanager.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/position.h\"\r\n#include \"../gui/eventconnector.h\"\r\n#include \"game.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n\r\nSoundManager::SoundManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nSoundManager::~SoundManager()\r\n{\r\n}\r\n\r\nvoid SoundManager::onTick( quint64 tick )\r\n{\r\n}\r\n\r\nvoid SoundManager::playEffect( QString type, Position& pos, QString material )\r\n{\r\n\tplayEffect( type, pos, material, 0 );\r\n}\r\n\r\nvoid SoundManager::playEffect( QString type, Position& pos, QString material, int duration )\r\n{\r\n\temit signalPlayEffect( SoundEffect { type, material, pos } );\r\n}\r\n"
  },
  {
    "path": "src/game/soundmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n\r\nstruct SoundEffect\r\n{\r\n\tQString type;\r\n\tQString material;\r\n\tPosition origin;\r\n};\r\nQ_DECLARE_METATYPE( SoundEffect )\r\n\r\nclass Job;\r\nclass Game;\r\n\r\nclass SoundManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( SoundManager )\r\npublic:\r\n\tSoundManager( Game* parent = 0 );\r\n\t~SoundManager();\r\n\r\n\tvoid onTick( quint64 tick );\r\n\tvoid playEffect( QString type, Position& pos, QString material );\r\n\tvoid playEffect( QString type, Position& pos, QString material, int duration );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\nsignals:\r\n\tvoid signalPlayEffect( const SoundEffect& effect );\r\n};\r\n"
  },
  {
    "path": "src/game/stockpile.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"stockpile.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QString>\r\n\r\nStockpile::Stockpile( Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_name = \"Stockpile\";\r\n}\r\n\r\nStockpile::Stockpile( QList<QPair<Position, bool>> tiles, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_name = \"Stockpile\"; // + QString::number( m_id );\r\n\r\n\tint i = 1;\r\n\tfor ( auto p : tiles )\r\n\t{\r\n\t\tif ( p.second )\r\n\t\t{\r\n\t\t\taddTile( p.first );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nStockpile::~Stockpile()\r\n{\r\n\tfor ( const auto& field : m_fields )\r\n\t{\r\n\t\tdelete field;\r\n\t}\r\n}\r\n\r\nvoid Stockpile::addTile( Position& pos )\r\n{\r\n\tInventoryField* infi = new InventoryField;\r\n\tinfi->pos            = pos;\r\n\tinfi->capacity       = 1;\r\n\tinfi->stackSize      = 1;\r\n\tinfi->containerID    = 0;\r\n\r\n\tm_fields.insert( pos.toInt(), infi );\r\n\r\n\tg->w()->setTileFlag( infi->pos, TileFlag::TF_STOCKPILE );\r\n}\r\n\r\nStockpile::Stockpile( QVariantMap vals, Game* game ) :\r\n\tWorldObject( vals, game )\r\n{\r\n\tm_pullOthers        = vals.value( \"PullOthers\" ).toBool();\r\n\tm_allowPull         = vals.value( \"AllowPull\" ).toBool();\r\n\tm_limitWithmaterial = vals.value( \"LimitWithMaterial\" ).toBool();\r\n\r\n\tQVariantList vfl = vals.value( \"Fields\" ).toList();\r\n\tfor ( auto vf : vfl )\r\n\t{\r\n\t\tInventoryField* infi = new InventoryField;\r\n\t\tinfi->pos            = Position( vf.toMap().value( \"Pos\" ).toString() );\r\n\t\tinfi->containerID    = vf.toMap().value( \"ContainerID\" ).toUInt();\r\n\t\tinfi->capacity       = vf.toMap().value( \"Capacity\" ).toUInt();\r\n\t\tinfi->stackSize      = vf.toMap().value( \"StackSize\" ).toUInt();\r\n\r\n\t\tif ( vf.toMap().contains( \"Items\" ) )\r\n\t\t{\r\n\t\t\tQVariantList vli = vf.toMap().value( \"Items\" ).toList();\r\n\t\t\tfor ( auto vi : vli )\r\n\t\t\t{\r\n\t\t\t\tif ( g->inv()->itemExists( vi.toUInt() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tinfi->items.insert( vi.toUInt() );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( vf.toMap().contains( \"ReservedItems\" ) )\r\n\t\t{\r\n\t\t\tQVariantList vli = vf.toMap().value( \"ReservedItems\" ).toList();\r\n\t\t\tfor ( auto vi : vli )\r\n\t\t\t{\r\n\t\t\t\tunsigned int itemID = vi.toUInt();\r\n\t\t\t\tif ( g->inv()->itemExists( itemID ) && g->inv()->isInJob( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tinfi->reservedItems.insert( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( infi->containerID )\r\n\t\t{\r\n\t\t\tinfi->requireSame = g->inv()->requireSame( infi->containerID );\r\n\t\t\t//repair capacity\r\n\t\t\tinfi->capacity = DB::select( \"Capacity\", \"Containers\", g->inv()->itemSID( infi->containerID ) ).value<unsigned char>(); \r\n\r\n\t\t}\r\n\r\n\t\tm_fields.insert( infi->pos.toInt(), infi );\r\n\r\n\t\tQVariantList vjl = vals.value( \"Jobs\" ).toList();\r\n\t\tfor ( auto vj : vjl )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> job( new Job( vj.toMap() ) );\r\n\t\t\tm_jobsOut.insert( job->id(), job );\r\n\t\t}\r\n\t}\r\n\r\n\tFilter filter( vals.value( \"Filter\" ).toMap() );\r\n\tm_filter = filter;\r\n\r\n\tQVariantList vll = vals.value( \"Limits\" ).toList();\r\n\tfor ( auto vl : vll )\r\n\t{\r\n\t\tauto vm = vl.toMap();\r\n\t\tStockpileItemLimit limit( vm.value( \"Max\" ).toInt(), vm.value( \"Activate\" ).toInt(), vm.value( \"Suspend\" ).toInt(), vm.value( \"Suspended\" ).toBool() );\r\n\t\tm_limits.insert( vm.value( \"Key\" ).toString(), limit );\r\n\t}\r\n}\r\n\r\nQVariant Stockpile::serialize()\r\n{\r\n\tQVariantMap out;\r\n\r\n\tWorldObject::serialize( out );\r\n\r\n\tout.insert( \"PullOthers\", m_pullOthers );\r\n\tout.insert( \"AllowPull\", m_allowPull );\r\n\tout.insert( \"LimitWithMaterial\", m_limitWithmaterial );\r\n\r\n\tQVariantList fields;\r\n\tfor ( auto field : m_fields )\r\n\t{\r\n\t\tQVariantMap fima;\r\n\t\tfima.insert( \"Pos\", field->pos.toString() );\r\n\t\tfima.insert( \"Capacity\", field->capacity );\r\n\t\tfima.insert( \"StackSize\", field->stackSize );\r\n\t\tfima.insert( \"ContainerID\", field->containerID );\r\n\r\n\t\tif ( field->items.size() > 0 )\r\n\t\t{\r\n\t\t\tQVariantList items;\r\n\t\t\tfor ( auto item : field->items )\r\n\t\t\t{\r\n\t\t\t\titems.append( item );\r\n\t\t\t}\r\n\t\t\tfima.insert( \"Items\", items );\r\n\t\t}\r\n\r\n\t\tif ( field->reservedItems.size() > 0 )\r\n\t\t{\r\n\t\t\tQVariantList reservedItems;\r\n\t\t\tfor ( auto item : field->reservedItems )\r\n\t\t\t{\r\n\t\t\t\treservedItems.append( item );\r\n\t\t\t}\r\n\t\t\tfima.insert( \"ReservedItems\", reservedItems );\r\n\t\t}\r\n\t\tfields.append( fima );\r\n\t}\r\n\tout.insert( \"Fields\", fields );\r\n\r\n\tQVariantList limits;\r\n\tfor ( auto key : m_limits.keys() )\r\n\t{\r\n\t\tauto limit = m_limits[key];\r\n\t\tQVariantMap lima;\r\n\t\tlima.insert( \"Key\", key );\r\n\t\tlima.insert( \"Max\", limit.max );\r\n\t\tlima.insert( \"Activate\", limit.activateThreshold );\r\n\t\tlima.insert( \"Suspend\", limit.suspendThreshold );\r\n\t\tlima.insert( \"Suspended\", limit.suspended );\r\n\t\tlimits.append( lima );\r\n\t}\r\n\tout.insert( \"Limits\", limits );\r\n\r\n\tQVariantList jobs;\r\n\tfor ( auto job : m_jobsOut )\r\n\t{\r\n\t\tjobs.append( job->serialize() );\r\n\t}\r\n\tout.insert( \"Jobs\", jobs );\r\n\r\n\tout.insert( \"Filter\", m_filter.serialize() );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Stockpile::pasteSettings( QVariantMap vals )\r\n{\r\n\tm_active     = vals.value( \"Active\" ).toBool();\r\n\tm_pullOthers = vals.value( \"PullOthers\" ).toBool();\r\n\tm_allowPull  = vals.value( \"AllowPull\" ).toBool();\r\n\r\n\tFilter filter( vals.value( \"Filter\" ).toMap() );\r\n\tm_filter = filter;\r\n\r\n\tm_limits.clear();\r\n\tQVariantList vll = vals.value( \"Limits\" ).toList();\r\n\tfor ( auto vl : vll )\r\n\t{\r\n\t\tauto vm = vl.toMap();\r\n\t\tStockpileItemLimit limit( vm.value( \"Max\" ).toInt(), vm.value( \"Activate\" ).toInt(), vm.value( \"Suspend\" ).toInt(), false );\r\n\t\tm_limits.insert( vm.value( \"Key\" ).toString(), limit );\r\n\t}\r\n}\r\n\r\nbool Stockpile::onTick( quint64 tick )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn false;\r\n\tbool lastUpdateLongAgo = ( tick - m_lastUpdateTick ) > 100;\r\n\tif ( ( m_filterChanged || m_possibleItems.empty() ) && lastUpdateLongAgo )\r\n\t{\r\n\t\tm_filterChanged = false;\r\n\t\tif ( !m_fields.empty() )\r\n\t\t{\r\n\t\t\tauto possibleSloits     = freeSlots();\r\n\t\t\tconst auto activeFilter = m_filter.getActive();\r\n\t\t\tQSet<QPair<QString, QString>> effectiveFilter;\r\n\t\t\tif ( possibleSloits.contains( QPair<QString, QString> { \"Any\", \"Any\" } ) )\r\n\t\t\t{\r\n\t\t\t\teffectiveFilter = activeFilter;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& filter : activeFilter )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( possibleSloits.contains( filter ) || possibleSloits.contains( QPair<QString, QString> { filter.first, \"Any\" } ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\teffectiveFilter.insert( filter );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tm_possibleItems = g->inv()->getClosestItemsForStockpile( m_id, m_fields.first()->pos, m_pullOthers, effectiveFilter );\r\n\t\t\tif ( m_possibleItems.size() > 5000 )\r\n\t\t\t{\r\n\t\t\t\tqWarning() << \"Excessive number of candidates for stockpile\";\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_lastUpdateTick = tick;\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQSet<QPair<QString, QString>> Stockpile::freeSlots() const\r\n{\r\n\tQSet<QPair<QString, QString>> freeSlots;\r\n\tfor ( auto infi : m_fields )\r\n\t{\r\n\t\tif ( !infi->isFull )\r\n\t\t{\r\n\t\t\tif ( infi->containerID )\r\n\t\t\t{\r\n\t\t\t\tif ( infi->items.size() == 0 || !infi->requireSame )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( const auto& itemSID : Global::util->itemsAllowedInContainer( infi->containerID ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfreeSlots.insert( { itemSID, \"Any\" } );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tauto item = *infi->items.begin();\r\n\t\t\t\t\t// Same item only\r\n\t\t\t\t\tfreeSlots.insert( { g->inv()->itemSID( item ), g->inv()->materialSID( item ) } );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( infi->items.size() == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tfreeSlots.insert( { \"Any\", \"Any\" } );\r\n\t\t\t\t}\r\n\t\t\t\telse if ( infi->items.size() < infi->stackSize )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto item = *infi->items.begin();\r\n\t\t\t\t\t// Same item only\r\n\t\t\t\t\tfreeSlots.insert( { g->inv()->itemSID( item ), g->inv()->materialSID( item ) } );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn freeSlots;\r\n}\r\n\r\nunsigned int Stockpile::getJob()\r\n{\r\n\tif ( m_isFull || !m_active || m_filter.getActive().isEmpty() || m_fields.empty() )\r\n\t\treturn 0;\r\n\r\n\tint itemsChecked = 0;\r\n\twhile ( !m_possibleItems.empty() && itemsChecked < 50 )\r\n\t{\r\n\t\t++itemsChecked;\r\n\t\tunsigned int item   = m_possibleItems.takeFirst();\r\n\t\tQString itemSID     = g->inv()->itemSID( item );\r\n\t\tQString materialSID = g->inv()->materialSID( item );\r\n\t\tbool suspended      = false;\r\n\r\n\t\tif ( m_limitWithmaterial )\r\n\t\t{\r\n\t\t\tif ( m_limits.contains( itemSID + materialSID ) )\r\n\t\t\t{\r\n\t\t\t\tsuspended = m_limits[itemSID + materialSID].suspended;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( m_limits.contains( itemSID ) )\r\n\t\t\t{\r\n\t\t\t\tsuspended = m_limits[itemSID].suspended;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( !suspended && !g->inv()->isInJob( item ) && g->inv()->isInStockpile( item ) != m_id && g->w()->regionMap().checkConnectedRegions( m_fields.first()->pos, g->inv()->getItemPos( item ) ) )\r\n\t\t{\r\n\t\t\tm_isFull = true;\r\n\t\t\t//loop over all stockpile fields\r\n\t\t\tfor ( auto infi : m_fields )\r\n\t\t\t{\r\n\t\t\t\tif ( !infi->isFull )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_isFull = false;\r\n\t\t\t\t\tif ( infi->reservedItems.size() > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned int reservedItemID = *infi->reservedItems.begin();\r\n\t\t\t\t\t\tif ( !g->inv()->itemExists( reservedItemID ) || g->inv()->isInJob( reservedItemID ) == 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tinfi->reservedItems.remove( reservedItemID );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// start with tiles that have a container\r\n\t\t\t\t\tif ( infi->containerID )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( infi->items.size() + infi->reservedItems.size() == 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t//container is empty\r\n\t\t\t\t\t\t\tif ( Global::util->itemAllowedInContainer( item, infi->containerID ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn createJob( item, infi );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse // container not empty\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( infi->requireSame )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( infi->capacity > ( g->inv()->itemsInContainer( infi->containerID ).size() + infi->reservedItems.size() ) && infi->capacity > infi->items.size() + infi->reservedItems.size() )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tunsigned int firstItem = 0;\r\n\t\t\t\t\t\t\t\t\tif ( g->inv()->itemsInContainer( infi->containerID ).size() )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tfirstItem = *g->inv()->itemsInContainer( infi->containerID ).begin();\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\telse if ( infi->reservedItems.size() )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\tfirstItem = *infi->reservedItems.begin();\r\n\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\tif ( ( firstItem != 0 && g->inv()->isSameTypeAndMaterial( item, firstItem ) ) )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\treturn createJob( item, infi );\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\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tinfi->isFull = true;\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\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( infi->capacity > ( g->inv()->itemsInContainer( infi->containerID ).size() + infi->reservedItems.size() ) &&\r\n\t\t\t\t\t\t\t\t\t infi->capacity > infi->items.size() + infi->reservedItems.size() )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( Global::util->itemAllowedInContainer( item, infi->containerID ) )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\treturn createJob( item, infi );\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\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tinfi->isFull = true;\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}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t//loop over all stockpile fields\r\n\t\t\tfor ( auto infi : m_fields )\r\n\t\t\t{\r\n\t\t\t\tif ( !infi->isFull )\r\n\t\t\t\t{\r\n\t\t\t\t\t// now tiles without container\r\n\t\t\t\t\tif ( !infi->containerID ) // no container\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( infi->items.size() + infi->reservedItems.size() == 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// field is empty\r\n\t\t\t\t\t\t\tif ( !g->inv()->isInJob( item ) && g->inv()->isInStockpile( item ) != m_id )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// create hauling job\r\n\t\t\t\t\t\t\t\treturn createJob( item, infi );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t// field isn't empty, is the item stackable and same type and material as the one on the field\r\n\t\t\t\t\t\t\tunsigned char newStackSize = infi->stackSize;\r\n\t\t\t\t\t\t\tif ( infi->reservedItems.size() > 0 )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tnewStackSize = qMax( newStackSize, g->inv()->stackSize( *infi->reservedItems.begin() ) );\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif ( newStackSize > 1 && ( ( infi->items.size() + infi->reservedItems.size() ) < newStackSize ) )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t// get the stack defining item\r\n\t\t\t\t\t\t\t\t// look if there are any items of that type that aren't in stockpiles yet\r\n\t\t\t\t\t\t\t\tunsigned int itemID = 0;\r\n\t\t\t\t\t\t\t\tif ( !infi->items.empty() )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\titemID = *infi->items.begin();\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\titemID = *infi->reservedItems.begin();\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\tif ( g->inv()->isSameTypeAndMaterial( itemID, item ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\treturn createJob( item, infi );\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\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tinfi->isFull = true;\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\treturn 0;\r\n}\r\n\r\nunsigned int Stockpile::createJob( unsigned int itemID, InventoryField* infi )\r\n{\r\n\tQString itemSID        = g->inv()->itemSID( itemID );\r\n\tQString materialSID    = g->inv()->materialSID( itemID );\r\n\tint freeSpace          = 1;\r\n\tint countItems         = infi->items.size();\r\n\tint countReservedItems = infi->reservedItems.size();\r\n\tif ( infi->containerID )\r\n\t{\r\n\t\tfreeSpace = infi->capacity - ( countItems + countReservedItems );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( infi->items.size() == 0 && infi->reservedItems.size() == 0 )\r\n\t\t{\r\n\t\t\tfreeSpace = g->inv()->stackSize( itemID );\r\n\t\t}\r\n\t\telse if ( infi->items.size() == 0 && infi->reservedItems.size() > 0 )\r\n\t\t{\r\n\t\t\tfreeSpace = g->inv()->stackSize( *infi->reservedItems.begin() ) - ( countItems + countReservedItems );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfreeSpace = infi->stackSize - ( countItems + countReservedItems );\r\n\t\t}\r\n\t}\r\n\r\n\t// space for more than one item?\r\n\tif ( freeSpace > 1 )\r\n\t{\r\n\t\t// there is more than one item of this type not in stockpiles already\r\n\t\tint itemCount = g->inv()->itemCountNotInStockpile( itemSID, materialSID );\r\n\t\tif ( itemCount > 1 )\r\n\t\t{\r\n\t\t\t// carry container exists?\r\n\t\t\tQString carryContainer = Global::util->carryContainerForItem( itemSID );\r\n\t\t\tfreeSpace              = qMin( freeSpace, Global::util->capacity( carryContainer ) );\r\n\r\n\t\t\tif ( !carryContainer.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tif ( g->inv()->itemCount( carryContainer, \"any\" ) > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tQSharedPointer<Job> job( new Job );\r\n\t\t\t\t\tjob->setType( \"HauleMultipleItems\" );\r\n\t\t\t\t\tjob->setRequiredSkill( \"Hauling\" );\r\n\t\t\t\t\tjob->setRequiredTool( carryContainer, 0 );\r\n\t\t\t\t\tjob->setStockpile( m_id );\r\n\t\t\t\t\tjob->setPos( infi->pos );\r\n\t\t\t\t\tjob->setPosItemInput( infi->pos );\r\n\t\t\t\t\tjob->addPossibleWorkPosition( infi->pos );\r\n\r\n\t\t\t\t\tjob->addItemToHaul( itemID );\r\n\t\t\t\t\tinfi->reservedItems.insert( itemID );\r\n\t\t\t\t\tg->inv()->setInJob( itemID, job->id() );\r\n\t\t\t\t\t--freeSpace;\r\n\r\n\t\t\t\t\t//auto possibleItems = g->inv()->getClosestItems( infi->pos, false, itemSID, materialSID );\r\n\t\t\t\t\t// m_possible items are now sorted by item and material\r\n\t\t\t\t\t//\r\n\t\t\t\t\twhile ( !m_possibleItems.empty() && freeSpace > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto nextItem = m_possibleItems.takeFirst();\r\n\t\t\t\t\t\tif ( materialSID != g->inv()->materialSID( nextItem ) || itemSID != g->inv()->itemSID( nextItem ) )\r\n\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\r\n\t\t\t\t\t\tif ( !g->inv()->isInJob( nextItem ) && g->inv()->isInStockpile( nextItem ) != m_id && g->w()->regionMap().checkConnectedRegions( infi->pos, g->inv()->getItemPos( nextItem ) ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tjob->addItemToHaul( nextItem );\r\n\t\t\t\t\t\t\tinfi->reservedItems.insert( nextItem );\r\n\t\t\t\t\t\t\tg->inv()->setInJob( nextItem, job->id() );\r\n\t\t\t\t\t\t\t--freeSpace;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_jobsOut.insert( job->id(), job );\r\n\t\t\t\t\treturn job->id();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tQSharedPointer<Job> job( new Job );\r\n\tjob->setType( \"HauleItem\" );\r\n\tjob->setRequiredSkill( \"Hauling\" );\r\n\r\n\tjob->setStockpile( m_id );\r\n\r\n\tjob->addItemToHaul( itemID );\r\n\tg->inv()->setInJob( itemID, job->id() );\r\n\r\n\tjob->setPos( infi->pos );\r\n\tjob->setPosItemInput( infi->pos );\r\n\tjob->addPossibleWorkPosition( infi->pos );\r\n\tjob->setWorkPos( infi->pos );\r\n\r\n\tinfi->reservedItems.insert( itemID );\r\n\r\n\tif ( m_limitWithmaterial )\r\n\t{\r\n\t\tint threshold = m_limits[itemSID + materialSID].suspendThreshold;\r\n\t\tif ( threshold > 0 && countPlusReserved( itemSID, materialSID ) >= threshold )\r\n\t\t{\r\n\t\t\tm_limits[itemSID + materialSID].suspended = true;\r\n\t\t\tm_suspendStatusChanged                    = true;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tint threshold = m_limits[itemSID].suspendThreshold;\r\n\t\tif ( threshold > 0 && countPlusReserved( itemSID ) >= threshold )\r\n\t\t{\r\n\t\t\tm_limits[itemSID].suspended = true;\r\n\t\t\tm_suspendStatusChanged      = true;\r\n\t\t}\r\n\t}\r\n\r\n\tm_jobsOut.insert( job->id(), job );\r\n\treturn job->id();\r\n}\r\n\r\nunsigned int Stockpile::getCleanUpJob()\r\n{\r\n\tif ( !m_active || m_filter.getActive().isEmpty() )\r\n\t\treturn 0;\r\n\r\n\t// cleaning up\r\n\t//loop over all stockpile fields\r\n\tfor ( auto i = m_fields.begin(); i != m_fields.end(); ++i )\r\n\t{\r\n\t\tInventoryField* infi = i.value();\r\n\t\t//first tiles with container\r\n\t\tif ( infi->containerID )\r\n\t\t{\r\n\t\t\tif ( infi->requireSame )\r\n\t\t\t{\r\n\t\t\t\tif ( infi->capacity > ( g->inv()->itemsInContainer( infi->containerID ).size() + infi->reservedItems.size() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int firstItem = 0;\r\n\t\t\t\t\tif ( g->inv()->itemsInContainer( infi->containerID ).size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfirstItem = *g->inv()->itemsInContainer( infi->containerID ).begin();\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse if ( infi->reservedItems.size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfirstItem = *infi->reservedItems.begin();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( firstItem != 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( g->inv()->isInJob( firstItem ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\treturn 0;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfor ( auto j = m_fields.begin(); j != m_fields.end(); ++j )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tInventoryField* infi2 = j.value();\r\n\t\t\t\t\t\t\tif ( !infi2->items.empty() && infi2->reservedItems.empty() && !infi2->containerID )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tfor ( auto oi : infi2->items )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tif ( g->inv()->itemSID( oi ) == g->inv()->itemSID( firstItem ) &&\r\n\t\t\t\t\t\t\t\t\t\t g->inv()->materialSID( oi ) == g->inv()->materialSID( firstItem ) &&\r\n\t\t\t\t\t\t\t\t\t\t !g->inv()->isInJob( oi ) )\r\n\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\treturn createJob( oi, infi );\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}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( infi->capacity > ( g->inv()->itemsInContainer( infi->containerID ).size() + infi->reservedItems.size() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto j = m_fields.begin(); j != m_fields.end(); ++j )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tInventoryField* infi2 = j.value();\r\n\t\t\t\t\t\tif ( !infi2->items.empty() && infi2->reservedItems.empty() && !infi2->containerID )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tfor ( auto oi : infi2->items )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tif ( Global::util->itemAllowedInContainer( oi, infi->containerID ) && !g->inv()->isInJob( oi ) )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\treturn createJob( oi, infi );\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}\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 ( auto i = m_fields.begin(); i != m_fields.end(); ++i )\r\n\t{\r\n\t\tInventoryField* infi = i.value();\r\n\t\tif ( !infi->containerID )\r\n\t\t{\r\n\t\t\tif ( infi->stackSize > 1 && ( infi->items.size() + infi->reservedItems.size() < infi->stackSize ) )\r\n\t\t\t{\r\n\t\t\t\tunsigned int firstItem = *infi->items.begin();\r\n\t\t\t\tif ( g->inv()->isInJob( firstItem ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn 0;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tauto iter = m_fields.end() - 1;\r\n\t\t\t\twhile ( iter != i )\r\n\t\t\t\t{\r\n\t\t\t\t\tInventoryField* infi2 = iter.value();\r\n\t\t\t\t\tif ( !infi2->items.empty() && infi2->reservedItems.empty() && !infi2->containerID )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor ( auto oi : infi2->items )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( g->inv()->itemSID( oi ) == g->inv()->itemSID( firstItem ) &&\r\n\t\t\t\t\t\t\t\t g->inv()->materialSID( oi ) == g->inv()->materialSID( firstItem ) &&\r\n\t\t\t\t\t\t\t\t !g->inv()->isInJob( oi ) &&\r\n\t\t\t\t\t\t\t\t infi2->items.size() < infi2->stackSize )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\treturn createJob( oi, infi );\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\t--iter;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool Stockpile::finishJob( unsigned int jobID )\r\n{\r\n\treturn giveBackJob( jobID );\r\n}\r\n\r\nbool Stockpile::giveBackJob( unsigned int jobID )\r\n{\r\n\tif ( m_jobsOut.contains( jobID ) )\r\n\t{\r\n\t\tQSharedPointer<Job> job = m_jobsOut[jobID];\r\n\t\tfor ( auto itemID : job->itemsToHaul() )\r\n\t\t{\r\n\t\t\tg->inv()->setInJob( itemID, 0 );\r\n\t\t\tPosition pos = job->pos();\r\n\t\t\tif ( m_fields.contains( pos.toInt() ) )\r\n\t\t\t{\r\n\t\t\t\tm_fields[pos.toInt()]->reservedItems.remove( itemID );\r\n\t\t\t\tm_fields[pos.toInt()]->isFull = false;\r\n\t\t\t\tm_isFull                      = false;\r\n\t\t\t}\r\n\t\t\tQString itemSID     = g->inv()->itemSID( itemID );\r\n\t\t\tQString materialSID = g->inv()->materialSID( itemID );\r\n\t\t\tif ( m_limitWithmaterial )\r\n\t\t\t{\r\n\t\t\t\tif ( countPlusReserved( itemSID, materialSID ) <= m_limits[itemSID + materialSID].activateThreshold )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_limits[itemSID + materialSID].suspended = false;\r\n\t\t\t\t\tm_suspendStatusChanged                    = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( countPlusReserved( itemSID ) <= m_limits[itemSID].activateThreshold )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_limits[itemSID].suspended = false;\r\n\t\t\t\t\tm_suspendStatusChanged      = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_jobsOut.remove( jobID );\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Stockpile::setInfiNotFull( Position pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tInventoryField* field = m_fields.value( pos.toInt() );\r\n\t\tfield->isFull         = false;\r\n\t\tm_isFull              = false;\r\n\t}\r\n}\r\n\r\nbool Stockpile::insertItem( Position pos, unsigned int item )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tInventoryField* field = m_fields.value( pos.toInt() );\r\n\t\tfield->reservedItems.remove( item );\r\n\t\tfield->items.insert( item );\r\n\t\tfield->isFull  = false;\r\n\t\tm_isFull       = false;\r\n\t\tg->inv()->setInStockpile( item, m_id );\r\n\t\tg->inv()->setInJob( item, 0 );\r\n\r\n\t\tif ( field->containerID )\r\n\t\t{\r\n\t\t\tif ( Global::util->itemAllowedInContainer( item, field->containerID ) )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->putItemInContainer( item, field->containerID );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfield->stackSize = g->inv()->stackSize( *field->items.begin() );\r\n\t\t\tg->inv()->setInContainer( item, 0 );\r\n\t\t}\r\n\t\t// if count of that item type reached suspend threshold, suspend that item\r\n\t\tQString itemSID     = g->inv()->itemSID( item );\r\n\t\tQString materialSID = g->inv()->materialSID( item );\r\n\t\tif ( m_limitWithmaterial )\r\n\t\t{\r\n\t\t\tint threshold = m_limits[itemSID + materialSID].suspendThreshold;\r\n\t\t\tif ( threshold > 0 && countPlusReserved( itemSID, materialSID ) >= threshold )\r\n\t\t\t{\r\n\t\t\t\tm_limits[itemSID + materialSID].suspended = true;\r\n\t\t\t\tm_suspendStatusChanged                    = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tint threshold = m_limits[itemSID].suspendThreshold;\r\n\t\t\tif ( threshold > 0 && countPlusReserved( itemSID ) >= threshold )\r\n\t\t\t{\r\n\t\t\t\tm_limits[itemSID].suspended = true;\r\n\t\t\t\tm_suspendStatusChanged      = true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tg->inv()->setInStockpile( item, 0 );\r\n\tg->inv()->setInJob( item, 0 );\r\n\r\n\tif ( Global::debugMode )\r\n\t\tqDebug() << \"item insert failed\";\r\n\treturn false;\r\n}\r\n\r\nbool Stockpile::removeItem( Position pos, unsigned int item )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tInventoryField* field = m_fields[pos.toInt()];\r\n\t\tif ( field->items.remove( item ) )\r\n\t\t{\r\n\t\t\tfield->isFull = false;\r\n\t\t\tm_isFull      = false;\r\n\t\t\tg->inv()->setInStockpile( item, 0 );\r\n\t\t\tif ( field->items.empty() && !field->containerID )\r\n\t\t\t{\r\n\t\t\t\tfield->stackSize = 1;\r\n\t\t\t}\r\n\t\t\tQString itemSID     = g->inv()->itemSID( item );\r\n\t\t\tQString materialSID = g->inv()->materialSID( item );\r\n\r\n\t\t\tif ( m_limitWithmaterial )\r\n\t\t\t{\r\n\t\t\t\tif ( countPlusReserved( itemSID, materialSID ) <= m_limits[itemSID + materialSID].activateThreshold )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_limits[itemSID + materialSID].suspended = false;\r\n\t\t\t\t\t//qDebug() << m_name << \"suspend status changed\";\r\n\t\t\t\t\tm_suspendStatusChanged = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( countPlusReserved( itemSID ) <= m_limits[itemSID].activateThreshold )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_limits[itemSID].suspended = false;\r\n\t\t\t\t\t//qDebug() << m_name << \"suspend status changed\";\r\n\t\t\t\t\tm_suspendStatusChanged = true;\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\tif ( Global::debugMode )\r\n\t\tqDebug() << \"remove item failed\";\r\n\treturn false;\r\n}\r\n\r\nvoid Stockpile::setCheckState( bool state, QString category, QString group, QString item, QString material )\r\n{\r\n\tm_filterChanged = true;\r\n\tif ( material != \"\" )\r\n\t{\r\n\t\tqDebug() << category << group << item << material << state;\r\n\t\tm_filter.setCheckState( category, group, item, material, state );\r\n\t}\r\n\telse if ( item != \"\" )\r\n\t{\r\n\t\tm_filter.setCheckState( category, group, item, state );\r\n\t}\r\n\telse if ( group != \"\" )\r\n\t{\r\n\t\tm_filter.setCheckState( category, group, state );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_filter.setCheckState( category, state );\r\n\t}\r\n\tif ( !state )\r\n\t{\r\n\t\t// unchecked some items, need to expel it from the stockpile\r\n\t\tQSet<QString> filter = m_filter.getActiveSimple();\r\n\r\n\t\tfor ( auto infi : m_fields )\r\n\t\t{\r\n\t\t\tQList<unsigned int> toRemove;\r\n\t\t\tfor ( auto oi : infi->items )\r\n\t\t\t{\r\n\t\t\t\tif ( !filter.contains( g->inv()->combinedID( oi ) ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->setInStockpile( oi, false );\r\n\t\t\t\t\ttoRemove.append( oi );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfor ( auto tr : toRemove )\r\n\t\t\t{\r\n\t\t\t\tinfi->items.remove( tr );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Stockpile::addContainer( unsigned int containerID, Position& pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tif ( containerID )\r\n\t\t{\r\n\t\t\tInventoryField* field = m_fields.value( pos.toInt() );\r\n\r\n\t\t\tfield->containerID = containerID;\r\n\t\t\tfield->requireSame = g->inv()->requireSame( containerID );\r\n\r\n\t\t\tfield->capacity = g->inv()->capacity( containerID );\r\n\r\n\t\t\tg->inv()->setConstructed( containerID, true );\r\n\r\n\t\t\tfor ( auto itemID : g->inv()->itemsInContainer( containerID ) )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->setItemPos( itemID, pos );\r\n\t\t\t\tif ( allowedInStockpile( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t//insertItem( pos, itemID );\r\n\t\t\t\t\tg->inv()->setInStockpile( itemID, m_id );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tauto items = m_fields[pos.toInt()]->items;\r\n\t\t\tfor ( auto item : items )\r\n\t\t\t{\r\n\t\t\t\tif ( Global::util->itemAllowedInContainer( item, containerID ) && g->inv()->itemsInContainer( containerID ).size() < g->inv()->capacity( containerID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\t// if an item is already in the container and the container requires same\r\n\t\t\t\t\tif ( field->requireSame && g->inv()->itemsInContainer( containerID ).size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned int firstItem = *g->inv()->itemsInContainer( containerID ).begin();\r\n\t\t\t\t\t\tif ( g->inv()->isSameTypeAndMaterial( item, firstItem ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->inv()->putItemInContainer( item, containerID );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->putItemInContainer( item, containerID );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tremoveItem( pos, item );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfield->items.clear();\r\n\t\t\tfor ( auto itemID : g->inv()->itemsInContainer( containerID ) )\r\n\t\t\t{\r\n\t\t\t\tif ( allowedInStockpile( itemID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfield->items.insert( itemID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Stockpile::removeContainer( unsigned int containerID, Position& pos )\r\n{\r\n\tif ( m_fields.contains( pos.toInt() ) )\r\n\t{\r\n\t\tInventoryField* field = m_fields.value( pos.toInt() );\r\n\t\tif ( field->containerID == containerID )\r\n\t\t{\r\n\t\t\tauto items     = g->inv()->itemsInContainer( containerID );\r\n\t\t\tfor ( auto item : items )\r\n\t\t\t{\r\n\t\t\t\tremoveItem( pos, item );\r\n\t\t\t}\r\n\t\t\tfield->capacity    = 1;\r\n\t\t\tfield->stackSize   = 1;\r\n\t\t\tfield->containerID = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Stockpile::allowedInStockpile( unsigned int itemID )\r\n{\r\n\treturn m_filter.getActiveSimple().contains( g->inv()->combinedID( itemID ) );\r\n}\r\n\r\nQSharedPointer<Job> Stockpile::getJob( unsigned int jobID )\r\n{\r\n\treturn m_jobsOut[jobID];\r\n}\r\n\r\nbool Stockpile::hasJobID( unsigned int jobID ) const\r\n{\r\n\treturn m_jobsOut.contains( jobID );\r\n}\r\n\r\nbool Stockpile::removeTile( Position& pos )\r\n{\r\n\tInventoryField* infi = m_fields.value( pos.toInt() );\r\n\t// unconstruct container on tile\r\n\tif ( infi->containerID != 0 )\r\n\t{\r\n\t\tg->w()->deconstruct( infi->pos, infi->pos, false );\r\n\t\t//g->inv()->setConstructed( infi->containerID, false );\r\n\t}\r\n\r\n\t// unstockpile all items on tile\r\n\tfor ( auto itemID : infi->items )\r\n\t{\r\n\t\tg->inv()->setInContainer( itemID, 0 );\r\n\t\tg->inv()->setInStockpile( itemID, 0 );\r\n\t}\r\n\tif ( m_jobsOut.contains( pos.toInt() ) )\r\n\t{\r\n\t\tm_jobsOut[pos.toInt()]->setCanceled();\r\n\t}\r\n\r\n\tinfi->items.clear();\r\n\tinfi->reservedItems.clear();\r\n\t// remove tile and remove tile flag\r\n\tm_fields.remove( pos.toInt() );\r\n\tg->w()->clearTileFlag( pos, TileFlag::TF_STOCKPILE );\r\n\tdelete infi;\r\n\t// if last tile deleted return true\r\n\tif ( m_fields.empty() )\r\n\t{\r\n\t\tm_active = false;\r\n\t}\r\n\r\n\treturn m_fields.empty();\r\n}\r\n\r\nvoid Stockpile::linkWorkshop( unsigned int workshopID )\r\n{\r\n\tif ( !m_linkedWorkshops.contains( workshopID ) )\r\n\t{\r\n\t\tm_linkedWorkshops.push_back( workshopID );\r\n\t}\r\n}\r\n\r\nvoid Stockpile::unlinkWorkshop( unsigned int workshopID )\r\n{\r\n\tif ( m_linkedWorkshops.contains( workshopID ) )\r\n\t{\r\n\t\tm_linkedWorkshops.removeAll( workshopID );\r\n\t}\r\n}\r\n\r\nint Stockpile::count( QString itemSID, QString materialSID )\r\n{\r\n\tint count      = 0;\r\n\tfor ( auto spf : m_fields )\r\n\t{\r\n\t\t// if exists get item from that position\r\n\t\tfor ( auto itemUID : spf->items )\r\n\t\t{\r\n\t\t\tif ( itemSID == g->inv()->itemSID( itemUID ) && materialSID == g->inv()->materialSID( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn count;\r\n}\r\n\r\nint Stockpile::count( QString itemSID )\r\n{\r\n\tint count      = 0;\r\n\tfor ( auto spf : m_fields )\r\n\t{\r\n\t\t// if exists get item from that position\r\n\t\tfor ( auto itemUID : spf->items )\r\n\t\t{\r\n\t\t\tif ( itemSID == g->inv()->itemSID( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn count;\r\n}\r\n\r\nint Stockpile::countPlusReserved( QString itemSID )\r\n{\r\n\tint count      = 0;\r\n\tfor ( auto spf : m_fields )\r\n\t{\r\n\t\t// if exists get item from that position\r\n\t\tfor ( auto itemUID : spf->items )\r\n\t\t{\r\n\t\t\tif ( itemSID == g->inv()->itemSID( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( auto itemUID : spf->reservedItems )\r\n\t\t{\r\n\t\t\tif ( itemSID == g->inv()->itemSID( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn count;\r\n}\r\n\r\nint Stockpile::countPlusReserved( QString itemSID, QString materialSID )\r\n{\r\n\tint count      = 0;\r\n\tfor ( auto spf : m_fields )\r\n\t{\r\n\t\t// if exists get item from that position\r\n\t\tfor ( auto itemUID : spf->items )\r\n\t\t{\r\n\t\t\tif ( itemSID == g->inv()->itemSID( itemUID ) && materialSID == g->inv()->materialSID( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor ( auto itemUID : spf->reservedItems )\r\n\t\t{\r\n\t\t\tif ( itemSID == g->inv()->itemSID( itemUID ) && materialSID == g->inv()->materialSID( itemUID ) )\r\n\t\t\t{\r\n\t\t\t\t++count;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn count;\r\n}\r\n\r\nvoid Stockpile::setPullOthers( bool value )\r\n{\r\n\tm_pullOthers = value;\r\n}\r\n\r\nbool Stockpile::pullsOthers()\r\n{\r\n\treturn m_pullOthers;\r\n}\r\n\r\nvoid Stockpile::setAllowPull( bool value )\r\n{\r\n\tm_allowPull = value;\r\n}\r\n\r\nbool Stockpile::allowsPull()\r\n{\r\n\treturn m_allowPull;\r\n}\r\n\r\nvoid Stockpile::setPriority( int p )\r\n{\r\n\tm_priority = p;\r\n}\r\n\r\nint Stockpile::priority()\r\n{\r\n\treturn m_priority;\r\n}\r\n\r\nvoid Stockpile::resetLimits()\r\n{\r\n\tm_limits.clear();\r\n}\r\n\r\nStockpileItemLimit Stockpile::limit( QString key )\r\n{\r\n\treturn m_limits[key];\r\n}\r\n\r\nvoid Stockpile::setLimit( QString key, StockpileItemLimit limit )\r\n{\r\n\tm_limits.insert( key, limit );\r\n}\r\n\r\nbool Stockpile::suspendChanged()\r\n{\r\n\tbool out               = m_suspendStatusChanged;\r\n\tm_suspendStatusChanged = false;\r\n\treturn out;\r\n}\r\n\r\nbool Stockpile::stillHasJobs()\r\n{\r\n\treturn !m_jobsOut.isEmpty();\r\n}\r\n\r\nint Stockpile::countFields()\r\n{\r\n\treturn m_fields.size();\r\n}\r\n\r\nvoid Stockpile::setLimitWithMaterial( bool value )\r\n{\r\n\tm_limitWithmaterial = value;\r\n}\r\n\r\nbool Stockpile::limitWithMaterial()\r\n{\r\n\treturn m_limitWithmaterial;\r\n}\r\n\r\nint Stockpile::capacity( unsigned int tileID )\r\n{\r\n\tif ( m_fields.contains( tileID ) )\r\n\t{\r\n\r\n\t\tInventoryField* field = m_fields.value( tileID );\r\n\t\treturn field->capacity;\r\n\t\t\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint Stockpile::itemCount( unsigned int tileID )\r\n{\r\n\tif ( m_fields.contains( tileID ) )\r\n\t{\r\n\r\n\t\tInventoryField* field = m_fields.value( tileID );\r\n\t\treturn field->items.size();\r\n\t\t\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nint Stockpile::reserved( unsigned int tileID )\r\n{\r\n\tif ( m_fields.contains( tileID ) )\r\n\t{\r\n\r\n\t\tInventoryField* field = m_fields.value( tileID );\r\n\t\treturn field->reservedItems.size();\r\n\t\t\r\n\t}\r\n\treturn 0;\r\n}"
  },
  {
    "path": "src/game/stockpile.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/filter.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/priorityqueue.h\"\r\n#include \"../game/worldobject.h\"\r\n\r\n#include <QHash>\r\n#include <QList>\r\n#include <QMap>\r\n#include <QPair>\r\n#include <QSize>\r\n#include <QThread>\r\n#include <QtGlobal>\r\n\r\nclass Game;\r\n\r\nstruct InventoryField\r\n{\r\n\tPosition pos;\r\n\tbool isFull              = false;\r\n\tunsigned char capacity   = 1;\r\n\tunsigned char stackSize  = 1;\r\n\tunsigned int containerID = 0;\r\n\tQSet<unsigned int> items;\r\n\tQSet<unsigned int> reservedItems;\r\n\r\n\tbool requireSame = false;\r\n};\r\n\r\nstruct StockpileItemLimit\r\n{\r\n\tStockpileItemLimit() {};\r\n\tStockpileItemLimit( int max_, int at, int st, bool susp )\r\n\t{\r\n\t\tmax               = max_;\r\n\t\tactivateThreshold = at;\r\n\t\tsuspendThreshold  = st;\r\n\t\tsuspended         = susp;\r\n\t}\r\n\tint max               = 100;\r\n\tint activateThreshold = 0;\r\n\tint suspendThreshold  = 0;\r\n\tbool suspended        = false;\r\n};\r\n\r\nclass Job;\r\n\r\nclass Stockpile : public WorldObject\r\n{\r\n\tQ_DISABLE_COPY_MOVE( Stockpile )\r\npublic:\r\n\tStockpile( Game* game );\r\n\tStockpile( QList<QPair<Position, bool>> tiles, Game* game );\r\n\tStockpile( QVariantMap vals, Game* game );\r\n\t~Stockpile();\r\n\r\n\tQVariant serialize();\r\n\tvoid pasteSettings( QVariantMap vals );\r\n\r\n\tQMap<unsigned int, InventoryField*>& getFields()\r\n\t{\r\n\t\treturn m_fields;\r\n\t}\r\n\r\n\t// returns true if the possible item list was updated\r\n\tbool onTick( quint64 tick );\r\n\r\n\tQSet<QPair<QString, QString>> freeSlots() const;\r\n\r\n\tFilter filter()\r\n\t{\r\n\t\treturn m_filter;\r\n\t}\r\n\tFilter* pFilter()\r\n\t{\r\n\t\treturn &m_filter;\r\n\t}\r\n\r\n\tbool insertItem( Position pos, unsigned int item );\r\n\tbool removeItem( Position pos, unsigned int item );\r\n\r\n\tvoid addContainer( unsigned int containerID, Position& pos );\r\n\tvoid removeContainer( unsigned int containerID, Position& pos );\r\n\r\n\tvoid setCheckState( bool state, QString category, QString group = \"\", QString item = \"\", QString material = \"\" );\r\n\r\n\tunsigned int getJob();\r\n\tunsigned int getCleanUpJob();\r\n\tbool finishJob( unsigned int jobID );\r\n\tbool giveBackJob( unsigned int jobID );\r\n\r\n\tQSharedPointer<Job> getJob( unsigned int jobID );\r\n\tbool hasJobID( unsigned int jobID ) const;\r\n\r\n\t// return true if last tile was removed\r\n\tbool removeTile( Position& pos );\r\n\tvoid addTile( Position& pos );\r\n\r\n\tvoid linkWorkshop( unsigned int workshopID );\r\n\tvoid unlinkWorkshop( unsigned int workshopID );\r\n\r\n\tint count( QString itemSID, QString materialSID );\r\n\tint count( QString itemSID );\r\n\tint countPlusReserved( QString itemSID );\r\n\tint countPlusReserved( QString itemSID, QString materialSID );\r\n\r\n\tvoid setPullOthers( bool value );\r\n\tbool pullsOthers();\r\n\tvoid setAllowPull( bool value );\r\n\tbool allowsPull();\r\n\r\n\tvoid setPriority( int p );\r\n\tint priority();\r\n\r\n\tvoid resetLimits();\r\n\tStockpileItemLimit limit( QString key );\r\n\tvoid setLimit( QString key, StockpileItemLimit limit );\r\n\tQMap<QString, StockpileItemLimit> limits()\r\n\t{\r\n\t\treturn m_limits;\r\n\t}\r\n\r\n\tvoid setLimitWithMaterial( bool value );\r\n\tbool limitWithMaterial();\r\n\r\n\tbool suspendChanged();\r\n\r\n\tbool stillHasJobs();\r\n\r\n\tint countFields();\r\n\r\n\tvoid setInfiNotFull( Position pos );\r\n\r\n\tint capacity( unsigned int tileID );\r\n\tint itemCount( unsigned int tileID );\r\n\tint reserved( unsigned int tileID );\r\n\r\n\r\nprivate:\r\n\tbool m_pullOthers = false;\r\n\tbool m_allowPull  = false;\r\n\r\n\tint m_priority = 0;\r\n\r\n\tbool m_isFull = false;\r\n\r\n\tQMap<unsigned int, InventoryField*> m_fields;\r\n\r\n\tQList<unsigned int> m_possibleItems;\r\n\tbool m_filterChanged = true;\r\n\r\n\tFilter m_filter;\r\n\r\n\tQMap<unsigned int, QSharedPointer<Job>> m_jobsOut;\r\n\r\n\tQList<unsigned int> m_linkedWorkshops;\r\n\r\n\tQMap<QString, StockpileItemLimit> m_limits;\r\n\r\n\tbool m_limitWithmaterial = false;\r\n\r\n\tunsigned int createJob( unsigned int itemID, InventoryField* infi );\r\n\r\n\tbool allowedInStockpile( unsigned int itemID );\r\n\r\n\tbool m_suspendStatusChanged = false;\r\n};\r\n"
  },
  {
    "path": "src/game/stockpilemanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"stockpilemanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/stockpile.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nStockpileManager::StockpileManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nStockpileManager::~StockpileManager()\r\n{\r\n\tfor ( const auto& sp : m_stockpiles )\r\n\t{\r\n\t\tdelete sp;\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::onTick( quint64 tick )\r\n{\r\n\tfor ( auto& sp : m_stockpiles )\r\n\t{\r\n\t\tif ( sp->countFields() == 0 && !sp->stillHasJobs() )\r\n\t\t{\r\n\t\t\tremoveStockpile( sp->id() );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto& sp : m_stockpiles )\r\n\t{\r\n\t\tif ( sp->onTick( tick ) )\r\n\t\t{\r\n\t\t\t//stockpile updated its possible item list\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::addStockpile( Position& firstClick, QList<QPair<Position, bool>> fields )\r\n{\r\n\tif ( m_allStockpileTiles.contains( firstClick.toInt() ) )\r\n\t{\r\n\t\tunsigned int spID = m_allStockpileTiles.value( firstClick.toInt() );\r\n\t\tStockpile* sp     = m_stockpiles[spID];\r\n\t\tfor ( auto p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second && !m_allStockpileTiles.contains( p.first.toInt() ) )\r\n\t\t\t{\r\n\t\t\t\tm_allStockpileTiles.insert( p.first.toInt(), spID );\r\n\t\t\t\tsp->addTile( p.first );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_lastAdded = spID;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tStockpile* sp = new Stockpile( fields, g );\r\n\t\tfor ( auto p : fields )\r\n\t\t{\r\n\t\t\tif ( p.second )\r\n\t\t\t{\r\n\t\t\t\tm_allStockpileTiles.insert( p.first.toInt(), sp->id() );\r\n\t\t\t}\r\n\t\t}\r\n\t\tsp->setPriority( m_stockpilesOrdered.size() );\r\n\t\tm_stockpiles.insert( sp->id(), sp );\r\n\t\tm_stockpilesOrdered.append( sp->id() );\r\n\t\tm_lastAdded = sp->id();\r\n\t}\r\n\tqDebug() << \"StockpileManager::addStockpile\";\r\n\temit signalStockpileAdded( m_lastAdded );\r\n}\r\n\r\nvoid StockpileManager::load( QVariantMap vals )\r\n{\r\n\tStockpile* sp = new Stockpile( vals, g );\r\n\tfor ( auto sf : vals.value( \"Fields\" ).toList() )\r\n\t{\r\n\t\tauto sfm = sf.toMap();\r\n\t\tm_allStockpileTiles.insert( Position( sfm.value( \"Pos\" ) ).toInt(), sp->id() );\r\n\t}\r\n\tsp->setPriority( m_stockpilesOrdered.size() );\r\n\tm_stockpiles.insert( sp->id(), sp );\r\n\tm_stockpilesOrdered.append( sp->id() );\r\n}\r\n\r\nvoid StockpileManager::removeStockpile( unsigned int id )\r\n{\r\n\tauto sp = m_stockpiles.value( id );\r\n\tif ( sp )\r\n\t{\r\n\t\tdelete sp;\r\n\t}\r\n\tm_stockpiles.remove( id );\r\n\tm_stockpilesOrdered.removeAll( id );\r\n\temit signalStockpileDeleted( id );\r\n}\r\n\r\nvoid StockpileManager::removeTile( Position& pos )\r\n{\r\n\tStockpile* sp = getStockpileAtPos( pos );\r\n\tif ( sp && sp->removeTile( pos ) )\r\n\t{\r\n\t\tunsigned int id = sp->id();\r\n\t\tif ( !sp->stillHasJobs() )\r\n\t\t{\r\n\t\t\tremoveStockpile( id );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\temit signalStockpileDeleted( id );\r\n\t\t}\r\n\t}\r\n\tm_allStockpileTiles.remove( pos.toInt() );\r\n}\r\n\r\nStockpile* StockpileManager::getStockpileAtPos( Position& pos )\r\n{\r\n\tif ( m_allStockpileTiles.contains( pos.toInt() ) )\r\n\t{\r\n\t\treturn m_stockpiles[m_allStockpileTiles[pos.toInt()]];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nStockpile* StockpileManager::getStockpileAtTileID( unsigned int id )\r\n{\r\n\tif ( m_allStockpileTiles.contains( id ) )\r\n\t{\r\n\t\treturn m_stockpiles[m_allStockpileTiles[id]];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nStockpile* StockpileManager::getStockpile( unsigned int id )\r\n{\r\n\tif ( m_stockpiles.contains( id ) )\r\n\t{\r\n\t\treturn m_stockpiles[id];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nStockpile* StockpileManager::getLastAddedStockpile()\r\n{\r\n\tif ( m_lastAdded && m_stockpiles.contains( m_lastAdded ) )\r\n\t{\r\n\t\treturn m_stockpiles[m_lastAdded];\r\n\t}\r\n\treturn m_stockpiles.last();\r\n}\r\n\r\nvoid StockpileManager::insertItem( unsigned int stockpileID, Position pos, unsigned int item )\r\n{\r\n\tif ( m_stockpiles.contains( stockpileID ) )\r\n\t{\r\n\t\tif ( !m_stockpiles[stockpileID]->insertItem( pos, item ) )\r\n\t\t{\r\n\t\t\tif ( Global::debugMode )\r\n\t\t\t\tqDebug() << \"insert into stockpile \" << stockpileID << \" failed\";\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\temit signalStockpileContentChanged( stockpileID );\r\n\t\t\tif ( m_stockpiles[stockpileID]->suspendChanged() )\r\n\t\t\t{\r\n\t\t\t\temit signalSuspendStatusChanged( stockpileID );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::removeItem( unsigned int stockpileID, Position pos, unsigned int item )\r\n{\r\n\tif ( m_stockpiles.contains( stockpileID ) )\r\n\t{\r\n\t\tm_stockpiles[stockpileID]->removeItem( pos, item );\r\n\t\temit signalStockpileContentChanged( stockpileID );\r\n\t\tif ( m_stockpiles[stockpileID]->suspendChanged() )\r\n\t\t{\r\n\t\t\temit signalSuspendStatusChanged( stockpileID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nunsigned int StockpileManager::getJob()\r\n{\r\n\tfor ( auto stockpileID : m_stockpilesOrdered )\r\n\t{\r\n\t\tunsigned int job = m_stockpiles[stockpileID]->getJob();\r\n\t\tif ( job )\r\n\t\t{\r\n\t\t\tif ( m_stockpiles[stockpileID]->suspendChanged() )\r\n\t\t\t{\r\n\t\t\t\temit signalSuspendStatusChanged( stockpileID );\r\n\t\t\t}\r\n\t\t\treturn job;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto stockpileID : m_stockpilesOrdered )\r\n\t{\r\n\t\tunsigned int job = m_stockpiles[stockpileID]->getCleanUpJob();\r\n\t\tif ( job )\r\n\t\t{\r\n\t\t\tif ( m_stockpiles[stockpileID]->suspendChanged() )\r\n\t\t\t{\r\n\t\t\t\temit signalSuspendStatusChanged( stockpileID );\r\n\t\t\t}\r\n\t\t\treturn job;\r\n\t\t}\r\n\t}\r\n\r\n\treturn 0;\r\n}\r\n\r\nbool StockpileManager::finishJob( unsigned int jobID )\r\n{\r\n\tfor ( auto& sp : m_stockpiles )\r\n\t{\r\n\t\tif ( sp->finishJob( jobID ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool StockpileManager::giveBackJob( unsigned int jobID )\r\n{\r\n\tfor ( auto& sp : m_stockpiles )\r\n\t{\r\n\t\tif ( sp->giveBackJob( jobID ) )\r\n\t\t{\r\n\t\t\tif ( sp->suspendChanged() )\r\n\t\t\t{\r\n\t\t\t\temit signalSuspendStatusChanged( sp->id() );\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQSharedPointer<Job> StockpileManager::getJob( unsigned int jobID )\r\n{\r\n\tfor ( const auto& sp : m_stockpiles )\r\n\t{\r\n\t\tif ( sp->hasJobID( jobID ) )\r\n\t\t{\r\n\t\t\treturn sp->getJob( jobID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool StockpileManager::hasJobID( unsigned int jobID ) const\r\n{\r\n\tfor ( const auto& sp : m_stockpiles )\r\n\t{\r\n\t\tif ( sp->hasJobID( jobID ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid StockpileManager::addContainer( unsigned int containerID, Position& pos )\r\n{\r\n\tStockpile* sp = getStockpileAtPos( pos );\r\n\tif ( sp )\r\n\t{\r\n\t\tsp->addContainer( containerID, pos );\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::removeContainer( unsigned int containerID, Position& pos )\r\n{\r\n\tStockpile* sp = getStockpileAtPos( pos );\r\n\tif ( sp )\r\n\t{\r\n\t\tsp->removeContainer( containerID, pos );\r\n\t}\r\n}\r\n\r\nunsigned int StockpileManager::maxPriority()\r\n{\r\n\treturn m_stockpilesOrdered.size();\r\n}\r\n\r\nvoid StockpileManager::movePriorityUp( unsigned int stockpileID )\r\n{\r\n\tint index = m_stockpilesOrdered.indexOf( stockpileID );\r\n\tif ( index > 0 )\r\n\t{\r\n\t\tm_stockpilesOrdered.move( index, index - 1 );\r\n\t\tm_stockpiles[m_stockpilesOrdered[index - 1]]->setPriority( index - 1 );\r\n\t\tm_stockpiles[m_stockpilesOrdered[index]]->setPriority( index );\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::setPriority( unsigned int stockpileID, int priority )\r\n{\r\n\tint index = m_stockpilesOrdered.indexOf( stockpileID );\r\n\r\n\tif ( index != -1 && index < m_stockpilesOrdered.size() )\r\n\t{\r\n\t\tm_stockpilesOrdered.takeAt( index );\r\n\t\tm_stockpilesOrdered.insert( priority, stockpileID );\r\n\r\n\t\tfor ( int i = 0; i < m_stockpilesOrdered.size(); ++i )\r\n\t\t{\r\n\t\t\tm_stockpiles[m_stockpilesOrdered[i]]->setPriority( i );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::movePriorityDown( unsigned int stockpileID )\r\n{\r\n\tint index = m_stockpilesOrdered.indexOf( stockpileID );\r\n\tif ( index != -1 && index < m_stockpilesOrdered.size() - 1 )\r\n\t{\r\n\t\tm_stockpilesOrdered.move( index, index + 1 );\r\n\r\n\t\tm_stockpiles[m_stockpilesOrdered[index + 1]]->setPriority( index + 1 );\r\n\t\tm_stockpiles[m_stockpilesOrdered[index]]->setPriority( index );\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::movePriorityTop( unsigned int stockpileID )\r\n{\r\n\tint index = m_stockpilesOrdered.indexOf( stockpileID );\r\n\tif ( index > 0 )\r\n\t{\r\n\t\tm_stockpilesOrdered.takeAt( index );\r\n\t\tm_stockpilesOrdered.insert( 0, stockpileID );\r\n\t\tfor ( int i = 0; i < m_stockpilesOrdered.size(); ++i )\r\n\t\t{\r\n\t\t\tm_stockpiles[m_stockpilesOrdered[i]]->setPriority( i );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid StockpileManager::movePriorityBottom( unsigned int stockpileID )\r\n{\r\n\tint index = m_stockpilesOrdered.indexOf( stockpileID );\r\n\tif ( index != -1 && index < m_stockpilesOrdered.size() - 1 )\r\n\t{\r\n\t\tm_stockpilesOrdered.takeAt( index );\r\n\t\tm_stockpilesOrdered.append( stockpileID );\r\n\t\tfor ( int i = 0; i < m_stockpilesOrdered.size(); ++i )\r\n\t\t{\r\n\t\t\tm_stockpiles[m_stockpilesOrdered[i]]->setPriority( i );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool StockpileManager::allowsPull( unsigned int stockpileID )\r\n{\r\n\treturn m_stockpiles[stockpileID]->allowsPull();\r\n}\r\n\r\nbool StockpileManager::hasPriority( unsigned int stockpileID, unsigned int stockpileID2 )\r\n{\r\n\treturn m_stockpiles[stockpileID]->priority() < m_stockpiles[stockpileID2]->priority();\r\n}\r\n\r\nQString StockpileManager::name( unsigned int id )\r\n{\r\n\tif ( m_stockpiles.contains( id ) )\r\n\t{\r\n\t\treturn m_stockpiles[id]->name();\r\n\t}\r\n\treturn \"ERROR\";\r\n}\r\n\r\nvoid StockpileManager::setInfiNotFull( Position pos )\r\n{\r\n\tauto sp = getStockpileAtPos( pos );\r\n\r\n\tif ( sp )\r\n\t{\r\n\t\tsp->setInfiNotFull( pos );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/game/stockpilemanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/stockpile.h\"\r\n\r\n#include <QSet>\r\n\r\nclass Job;\r\nclass Stockpile;\r\nclass Inventory;\r\nclass Game;\r\n\r\nclass StockpileManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( StockpileManager )\r\npublic:\r\n\tStockpileManager( Game* parent );\r\n\t~StockpileManager();\r\n\r\n\tvoid onTick( quint64 tick );\r\n\r\n\tvoid addStockpile( Position& firstClick, QList<QPair<Position, bool>> fields );\r\n\tvoid load( QVariantMap vals );\r\n\r\n\tvoid addContainer( unsigned int containerID, Position& pos );\r\n\tvoid removeContainer( unsigned int containerID, Position& pos );\r\n\r\n\tvoid removeStockpile( unsigned int id );\r\n\tvoid removeTile( Position& pos );\r\n\r\n\tbool isStockPile( Position& pos )\r\n\t{\r\n\t\treturn m_allStockpileTiles.contains( pos.toInt() );\r\n\t}\r\n\r\n\tStockpile* getStockpileAtPos( Position& pos );\r\n\tStockpile* getStockpileAtTileID( unsigned int id );\r\n\tStockpile* getStockpile( unsigned int id );\r\n\tStockpile* getLastAddedStockpile();\r\n\r\n\tvoid insertItem( unsigned int stockpileID, Position pos, unsigned int item );\r\n\tvoid removeItem( unsigned int stockpileID, Position pos, unsigned int item );\r\n\r\n\tvoid setInfiNotFull( Position pos );\r\n\r\n\tunsigned int getJob();\r\n\tbool finishJob( unsigned int jobID );\r\n\tbool giveBackJob( unsigned int jobID );\r\n\tQSharedPointer<Job> getJob( unsigned int jobID );\r\n\tbool hasJobID( unsigned int jobID ) const;\r\n\r\n\tQList<unsigned int> allStockpiles()\r\n\t{\r\n\t\treturn m_stockpiles.keys();\r\n\t}\r\n\tQList<unsigned int>& allStockpilesOrdered()\r\n\t{\r\n\t\treturn m_stockpilesOrdered;\r\n\t}\r\n\r\n\tunsigned int maxPriority();\r\n\tvoid setPriority( unsigned int stockpileID, int priority );\r\n\tvoid movePriorityUp( unsigned int stockpileID );\r\n\tvoid movePriorityDown( unsigned int stockpileID );\r\n\tvoid movePriorityTop( unsigned int stockpileID );\r\n\tvoid movePriorityBottom( unsigned int stockpileID );\r\n\r\n\tbool allowsPull( unsigned int stockpileID );\r\n\r\n\tbool hasPriority( unsigned int stockpileID, unsigned int stockpileID2 );\r\n\r\n\tQString name( unsigned int id );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQMap<unsigned int, Stockpile*> m_stockpiles;\r\n\tQList<unsigned int> m_stockpilesOrdered;\r\n\tQHash<unsigned int, unsigned int> m_allStockpileTiles;\r\n\r\n\tunsigned int m_lastAdded = 0;\r\n\r\nsignals:\r\n\tvoid signalSuspendStatusChanged( unsigned int stockpileUID );\r\n\tvoid signalStockpileDeleted( unsigned int stockpileUID );\r\n\tvoid signalStockpileAdded( unsigned int stockpileUID );\r\n\tvoid signalStockpileContentChanged( unsigned int stockpileUID );\r\n};\r\n"
  },
  {
    "path": "src/game/techtree.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"techtree.h\"\r\n\r\n#include \"../base/db.h\"\r\n\r\n#include <QDebug>\r\n#include <QQueue>\r\n#include <QSqlQuery>\r\n\r\nTechTree::TechTree( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nTechTree::~TechTree()\r\n{\r\n}\r\n\r\nvoid TechTree::create()\r\n{\r\n\tQHash<QString, int> itemLevels;\r\n\r\n\tfor ( auto id : DB::ids( \"BaseItems\" ) )\r\n\t{\r\n\t\titemLevels.insert( id, 1 );\r\n\t}\r\n\r\n\tQList<QString> crafts = DB::ids( \"Crafts\" );\r\n\r\n\tQQueue<QString> workQueue;\r\n\tfor ( auto craft : crafts )\r\n\t{\r\n\t\tworkQueue.enqueue( craft );\r\n\t}\r\n\tint breaker = 0;\r\n\twhile ( !workQueue.isEmpty() )\r\n\t{\r\n\t\tQString id = workQueue.dequeue();\r\n\t\tauto craft = DB::selectRow( \"Crafts\", id );\r\n\r\n\t\tif ( compsLowerLevel( id, itemLevels ) )\r\n\t\t{\r\n\t\t\tint level = levelPlusOne( id, itemLevels );\r\n\t\t\titemLevels.insert( craft.value( \"ItemID\" ).toString(), level );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tworkQueue.enqueue( id );\r\n\t\t}\r\n\r\n\t\t++breaker;\r\n\t\tif ( breaker == 100000 )\r\n\t\t{\r\n\t\t\tqDebug() << \"breaker reached\";\r\n\t\t\tqDebug() << \"workqueue size:\" << workQueue.size();\r\n\t\t\twhile ( !workQueue.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tQString id = workQueue.dequeue();\r\n\t\t\t\tqDebug() << id;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tqDebug() << \"####################################################\";\r\n\tint maxLevel = 0;\r\n\tfor ( auto key : itemLevels.keys() )\r\n\t{\r\n\t\tmaxLevel = qMax( maxLevel, itemLevels[key] );\r\n\t}\r\n\tint currentLevel = 1;\r\n\tauto keys        = itemLevels.keys();\r\n\tkeys.sort();\r\n\r\n\twhile ( currentLevel <= maxLevel )\r\n\t{\r\n\t\t//qDebug() << \"-->\" << currentLevel;\r\n\t\tfor ( auto key : keys )\r\n\t\t{\r\n\t\t\tif ( currentLevel == itemLevels[key] )\r\n\t\t\t{\r\n\t\t\t\tqDebug() << currentLevel << key;\r\n\t\t\t}\r\n\t\t}\r\n\t\t++currentLevel;\r\n\t}\r\n\tqDebug() << \"####################################################\";\r\n\tfor ( auto key : keys )\r\n\t{\r\n\t\tqDebug() << itemLevels[key] << key;\r\n\r\n\t\tbool ok;\r\n\t\tDB::execQuery3( \"UPDATE Items SET \\\"VALUE\\\" = \\\"\" + QString::number( itemLevels[key] ) + \"\\\" WHERE ID = \\\"\" + key + \"\\\"\", ok );\r\n\t}\r\n\tqDebug() << \"####################################################\";\r\n}\r\n\r\nbool TechTree::compsLowerLevel( QString craftID, QHash<QString, int>& itemLevels )\r\n{\r\n\tfor ( auto row : DB::selectRows( \"Crafts_Components\", craftID ) )\r\n\t{\r\n\t\tif ( !itemLevels.contains( row.value( \"ItemID\" ).toString() ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nint TechTree::levelPlusOne( QString craftID, QHash<QString, int>& itemLevels )\r\n{\r\n\tint level = 0;\r\n\tfor ( auto row : DB::selectRows( \"Crafts_Components\", craftID ) )\r\n\t{\r\n\t\tlevel = qMax( level, itemLevels.value( row.value( \"ItemID\" ).toString() ) * row.value( \"Amount\" ).toInt() );\r\n\t}\r\n\treturn level + 1;\r\n}"
  },
  {
    "path": "src/game/techtree.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMap>\r\n#include <QObject>\r\n#include <QSet>\r\n\r\nstruct TTNode\r\n{\r\n\tchar level = 0;\r\n\tQString itemSID;\r\n\tQString craftID;\r\n\r\n\tQSet<QString> parents;\r\n\tQSet<QString> childs;\r\n};\r\n\r\nclass TechTree : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tTechTree( QObject* parent = 0 );\r\n\t~TechTree();\r\n\r\n\tvoid create();\r\n\r\nprivate:\r\n\tbool compsLowerLevel( QString craftID, QHash<QString, int>& itemLevels );\r\n\tint levelPlusOne( QString craftID, QHash<QString, int>& itemLevels );\r\n\r\n\tQMap<QString, TTNode> m_items;\r\n};\r\n"
  },
  {
    "path": "src/game/workshop.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"workshop.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n\r\n#include \"../game/game.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n\r\n#include \"../game/workshopmanager.h\"\r\n\r\n#include \"../game/job.h\"\r\n#include \"../game/pasture.h\"\r\n#include \"../game/stockpile.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n\r\nWorkshopProperties::WorkshopProperties( QVariantMap& in )\r\n{\r\n\ttype     = in.value( \"Type\" ).toString();\r\n\trotation = in.value( \"Rotation\" ).toInt();\r\n\tpos      = Position( in.value( \"Pos\" ) );\r\n\tposIn    = Position( in.value( \"PosIn\" ) );\r\n\tposOut   = Position( in.value( \"PosOut\" ) );\r\n\r\n\towner           = in.value( \"Owner\" ).toUInt();\r\n\tlinkedStockpile = in.value( \"LinkedStockpile\" ).toUInt();\r\n\r\n\ttoDestroy = in.value( \"ToDestroy\" ).toBool();\r\n\tcanDelete = in.value( \"CanDelete\" ).toBool();\r\n\r\n\tbutcherExcess  = in.value( \"ButcherExcess\" ).toBool();\r\n\tbutcherCorpses = in.value( \"ButcherCorpses\" ).toBool();\r\n\tfish           = in.value( \"Fish\" ).toBool();\r\n\tprocessFish    = in.value( \"ProcessFish\" ).toBool();\r\n\r\n\tshowMaterials    = in.value( \"ShowMaterials\" ).toBool();\r\n\tshowListControls = in.value( \"ShowListControls\" ).toBool();\r\n\tacceptGenerated  = in.value( \"AcceptGenerated\" ).toBool();\r\n\tcraftIngredients = in.value( \"CraftIngredients\" ).toBool();\r\n\r\n\tsourceItems = in.value( \"SourceItems\" ).toList();\r\n\titemsToSell = in.value( \"ItemsToSell\" ).toList();\r\n\r\n\tauto dbws = DB::workshop( type );\r\n\tif( dbws )\r\n\t{\r\n\t\tgui = dbws->GUI;\r\n\t\tnoAutoGenerate = dbws->NoAutoGenerate;\r\n\t\tcrafts = dbws->Crafts;\r\n\t}\r\n}\r\n\r\nvoid WorkshopProperties::serialize( QVariantMap& out )\r\n{\r\n\tout.insert( \"Type\", type );\r\n\tout.insert( \"Rotation\", rotation );\r\n\tout.insert( \"Pos\", pos.toString() );\r\n\tout.insert( \"PosIn\", posIn.toString() );\r\n\tout.insert( \"PosOut\", posOut.toString() );\r\n\r\n\tout.insert( \"Owner\", owner );\r\n\tout.insert( \"LinkedStockpile\", linkedStockpile );\r\n\r\n\tout.insert( \"ToDestroy\", toDestroy );\r\n\tout.insert( \"CanDelete\", canDelete );\r\n\r\n\tout.insert( \"ButcherExcess\", butcherExcess );\r\n\tout.insert( \"ButcherCorpses\", butcherCorpses );\r\n\tout.insert( \"Fish\", fish );\r\n\tout.insert( \"ProcessFish\", processFish );\r\n\r\n\tout.insert( \"ShowMaterials\", showMaterials );\r\n\tout.insert( \"ShowListControls\", showListControls );\r\n\tout.insert( \"AcceptGenerated\", acceptGenerated );\r\n\tout.insert( \"CraftIngredients\", craftIngredients );\r\n\r\n\tout.insert( \"SourceItems\", sourceItems );\r\n\tout.insert( \"ItemsToSell\", itemsToSell );\r\n}\r\n\r\nCraftJob::CraftJob( QVariantMap& in )\r\n{\r\n\t// Restore IDs\r\n\tid            = in.value( \"JobDefID\" ).toUInt();\r\n\tcraftID       = in.value( \"CraftID\" ).toString();\r\n\r\n\t// Restore user config\r\n\r\n\tQString sMode   = in.value( \"Mode\" ).toString();\r\n\tif ( sMode == \"Craft#\" )\r\n\t\tmode = CraftMode::CraftNumber;\r\n\telse if ( sMode == \"CraftTo\" )\r\n\t\tmode = CraftMode::CraftTo;\r\n\telse\r\n\t\tmode = CraftMode::Repeat;\r\n\r\n\tnumItemsToCraft = in.value( \"Amount\" ).toInt();\r\n\r\n\talreadyCrafted = in.value( \"CraftNumberValue\" ).toInt();\r\n\r\n\tauto vReqItems = in.value( \"RequiredItems\" ).toList();\r\n\r\n\tfor ( auto vri : vReqItems )\r\n\t{\r\n\t\tauto vrm = vri.toMap();\r\n\t\tInputItem ii { vrm.value( \"ItemID\" ).toString(), vrm.value( \"MaterialID\" ).toString(), vrm.value( \"Amount\" ).toInt(), vrm.value( \"RequireSame\" ).toBool() };\r\n\t\trequiredItems.append( ii );\r\n\t}\r\n\r\n\tmoveToBackWhenDone = in.value( \"MoveToBackWhenDone\" ).toBool();\r\n\tpaused             = in.value( \"Suspended\" ).toBool();\r\n\r\n\t// Fetch config state from DB\r\n\tauto row           = DB::selectRow( \"Crafts\", craftID );\r\n\titemSID            = row.value( \"ItemID\" ).toString();\r\n\tconversionMaterial = row.value( \"ConversionMaterial\" ).toString();\r\n\tresultMaterial     = row.value( \"ResultMaterial\" ).toString();\r\n\titemsPerCraft      = row.value( \"Amount\" ).toInt();\r\n\tproductionTime     = row.value( \"ProductionTime\" ).toInt();\r\n\tskillID            = row.value( \"SkillID\" ).toString();\r\n}\r\n\r\nvoid CraftJob::serialize( QVariantMap& out )\r\n{\r\n\tout.insert( \"JobDefID\", id );\r\n\tout.insert( \"CraftID\", craftID );\r\n\r\n\tout.insert( \"Amount\", numItemsToCraft );\r\n\tswitch ( mode )\r\n\t{\r\n\t\tcase CraftMode::CraftNumber:\r\n\t\t\tout.insert( \"Mode\", \"Craft#\" );\r\n\t\t\tbreak;\r\n\t\tcase CraftMode::CraftTo:\r\n\t\t\tout.insert( \"Mode\", \"CraftTo\" );\r\n\t\t\tbreak;\r\n\t\tcase CraftMode::Repeat:\r\n\t\t\tout.insert( \"Mode\", \"Repeat\" );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tout.insert( \"CraftNumberValue\", alreadyCrafted );\r\n\r\n\tQVariantList vReqItems;\r\n\tfor ( auto ri : requiredItems )\r\n\t{\r\n\t\tQVariantMap vmi;\r\n\t\tvmi.insert( \"ItemID\", ri.itemSID );\r\n\t\tvmi.insert( \"MaterialID\", ri.materialSID );\r\n\t\tvmi.insert( \"Amount\", ri.amount );\r\n\t\tvmi.insert( \"RequireSame\", ri.requireSame );\r\n\t\tvReqItems.append( vmi );\r\n\t}\r\n\tout.insert( \"RequiredItems\", vReqItems );\r\n\r\n\tout.insert( \"MoveToBackWhenDone\", moveToBackWhenDone );\r\n\tout.insert( \"Suspended\", paused );\r\n}\r\n\r\nWorkshop::Workshop( QString type, Position& pos, int rotation, Game* game ) :\r\n\tWorldObject( game )\r\n{\r\n\tm_properties.type     = type;\r\n\tm_properties.rotation = rotation;\r\n\tm_properties.pos      = pos;\r\n\tm_name                = S::s( \"$WorkshopName_\" + type );\r\n\r\n\tauto dbws = DB::workshop( type );\r\n\tif( dbws )\r\n\t{\r\n\t\tauto& spl = dbws->components;\r\n\r\n\t\tfor ( auto sp : spl )\r\n\t\t{\r\n\t\t\tPosition offset;\r\n\t\t\toffset   = sp.Offset;\r\n\t\t\tint rotX = offset.x;\r\n\t\t\tint rotY = offset.y;\r\n\t\t\tswitch ( rotation )\r\n\t\t\t{\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\toffset.x = -1 * rotY;\r\n\t\t\t\t\toffset.y = rotX;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\toffset.x = -1 * rotX;\r\n\t\t\t\t\toffset.y = -1 * rotY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\toffset.x = rotY;\r\n\t\t\t\t\toffset.y = -1 * rotX;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tPosition constrPos( pos + offset );\r\n\t\t\tm_tiles.insert( constrPos.toInt(), constrPos );\r\n\t\t}\r\n\r\n\t\tm_properties.gui = dbws->GUI;\r\n\t\tm_properties.noAutoGenerate = dbws->NoAutoGenerate;\r\n\t\tm_properties.crafts = dbws->Crafts;\r\n\r\n\t\tPosition posIn  = dbws->InputTile;\r\n\t\tPosition posOut = dbws->OutputTile;\r\n\r\n\t\tint inX  = posIn.x;\r\n\t\tint inY  = posIn.y;\r\n\t\tint outX = posOut.x;\r\n\t\tint outY = posOut.y;\r\n\t\tswitch ( rotation )\r\n\t\t{\r\n\t\t\tcase 1:\r\n\t\t\t\tposIn.x  = -1 * inY;\r\n\t\t\t\tposIn.y  = inX;\r\n\t\t\t\tposOut.x = -1 * outY;\r\n\t\t\t\tposOut.y = outX;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tposIn.x  = -1 * inX;\r\n\t\t\t\tposIn.y  = -1 * inY;\r\n\t\t\t\tposOut.x = -1 * outX;\r\n\t\t\t\tposOut.y = -1 * outY;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tposIn.x  = inY;\r\n\t\t\t\tposIn.y  = -1 * inX;\r\n\t\t\t\tposOut.x = outY;\r\n\t\t\t\tposOut.y = -1 * outX;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tposIn  = pos + posIn;\r\n\t\tposOut = pos + posOut;\r\n\r\n\t\tm_properties.posIn  = posIn;\r\n\t\tm_properties.posOut = posOut;\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// this should never be reached\r\n\t}\r\n}\r\n\r\nWorkshop::~Workshop()\r\n{\r\n}\r\n\r\nWorkshop::Workshop( QVariantMap vals, Game* game ) :\r\n\tWorldObject( vals, game ),\r\n\tm_properties( vals )\r\n{\r\n\tQVariantList vtl = vals.value( \"Tiles\" ).toList();\r\n\tfor ( auto vt : vtl )\r\n\t{\r\n\t\tPosition pos( vt );\r\n\t\tm_tiles.insert( pos.toInt(), pos );\r\n\t}\r\n\r\n\tQVariantList vjl = vals.value( \"JobQueue\" ).toList();\r\n\tfor ( auto vj : vjl )\r\n\t{\r\n\t\tQVariantMap vjm = vj.toMap();\r\n\t\tCraftJob cj( vjm );\r\n\t\tm_jobList.append( cj );\r\n\t}\r\n\tm_currentJobID = vals.value( \"CurrentJobID\" ).toUInt();\r\n\tif( m_currentJobID )\r\n\t{\r\n\t\tauto job = g->jm()->getJob( m_currentJobID );\r\n\t\tif( job )\r\n\t\t{\r\n\t\t\tm_currentCraftJobID = job->craftJobID();\r\n\t\t\tm_job = job;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_currentJobID = 0;\r\n\t\t\tm_currentCraftJobID = 0;\r\n\t\t}\r\n\t}\r\n\r\n\tm_spriteComposition = vals.value( \"Sprites\" ).toList();\r\n}\r\n\r\nQVariant Workshop::serialize()\r\n{\r\n\tQVariantMap out;\r\n\tWorldObject::serialize( out );\r\n\tm_properties.serialize( out );\r\n\r\n\tQVariantList tiles;\r\n\tfor ( auto tp : m_tiles )\r\n\t{\r\n\t\tQString ps = tp.toString();\r\n\t\ttiles.append( ps );\r\n\t}\r\n\tout.insert( \"Tiles\", tiles );\r\n\r\n\tQVariantList VLJobQueue;\r\n\tfor ( auto cj : m_jobList )\r\n\t{\r\n\t\tQVariantMap vmj;\r\n\t\tcj.serialize( vmj );\r\n\t\tVLJobQueue.append( vmj );\r\n\t}\r\n\tout.insert( \"JobQueue\", VLJobQueue );\r\n\r\n\tout.insert( \"Sprites\", m_spriteComposition );\r\n\r\n\tout.insert( \"CurrentJobID\", m_currentJobID );\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid Workshop::onTick( quint64 tick )\r\n{\r\n\tif ( m_properties.toDestroy )\r\n\t{\r\n\t\tif ( !m_job && !m_fishingJob )\r\n\t\t{\r\n\t\t\tm_properties.canDelete = true;\r\n\t\t\t//destroy\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( !m_active )\r\n\t{\r\n\t\tQSharedPointer<Job> spJob = m_job.toStrongRef();\r\n\t\tif ( spJob )\r\n\t\t{\r\n\t\t\tg->jm()->deleteJob( spJob->id() );\r\n\t\t\tm_currentCraftJobID = 0;\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tcheckLinkedStockpile();\r\n\r\n\t// job has been finished in the job manager \r\n\tif( !m_job && m_currentCraftJobID )\r\n\t{\r\n\t\tif( finishJob( m_currentCraftJobID ) )\r\n\t\t{\r\n\t\t\tg->wsm()->emitJobListChanged( m_id );\r\n\t\t}\r\n\t\tm_currentCraftJobID = 0;\r\n\t\tm_currentJobID = 0;\r\n\t}\r\n\r\n\tfor ( auto& cj : m_autoCraftList )\r\n\t{\r\n\t\tm_jobList.push_front( cj );\r\n\t}\r\n\tm_autoCraftList.clear();\r\n\r\n\t// check if the emitted job is still possible\r\n\t// ressources may have been consumed by 3rd party\r\n\t{\r\n\t\tQSharedPointer<Job> spJob = m_job.toStrongRef();\r\n\t\tif ( spJob && !spJob->isWorked() )\r\n\t\t{\r\n\t\t\tfor ( auto& cj : m_jobList )\r\n\t\t\t{\r\n\t\t\t\tif ( cj.id == m_currentCraftJobID )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( !checkItemsAvailable( cj ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->jm()->deleteJob( spJob->id() );\r\n\t\t\t\t\t\tm_currentCraftJobID = 0;\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 ( !m_job && !m_jobList.empty() && outputTileFree() )\r\n\t{\r\n\t\tfor ( auto& cj : m_jobList )\r\n\t\t{\r\n\t\t\tif ( cj.mode == CraftMode::CraftTo )\r\n\t\t\t{\r\n\t\t\t\tQString materialID = \"any\";\r\n\r\n\t\t\t\tif ( cj.requiredItems.size() )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto ri    = cj.requiredItems.first();\r\n\t\t\t\t\tmaterialID = ri.materialSID;\r\n\r\n\t\t\t\t\tif ( !cj.conversionMaterial.isEmpty() && !cj.conversionMaterial.startsWith( \"$\" ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmaterialID = cj.conversionMaterial;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tint existing = g->inv()->itemCountWithInJob( cj.itemSID, materialID );\r\n\t\t\t\tif ( existing >= cj.numItemsToCraft )\r\n\t\t\t\t{\r\n\t\t\t\t\tcj.paused = true;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcj.paused = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( !cj.paused )\r\n\t\t\t{\r\n\t\t\t\tif( checkItemsAvailable( cj ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( createJobFromCraftJob( cj ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn;\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 ( !m_job && m_properties.type == \"Butcher\" && outputTileFree() )\r\n\t{\r\n\t\tm_job = createButcherJob();\r\n\t}\r\n\t\r\n\tif ( !m_fishingJob && m_properties.type == \"Fishery\" && outputTileFree() && m_properties.fish )\r\n\t{\r\n\t\tm_fishingJob = createFisherJob();\r\n\t}\r\n\r\n\tif ( !m_job && m_properties.type == \"Fishery\" && outputTileFree() && m_properties.processFish )\r\n\t{\r\n\t\tm_job = createFishButcherJob();\r\n\t}\r\n}\r\n\r\nbool Workshop::isOnTile( const Position& pos )\r\n{\r\n\treturn m_tiles.contains( pos.toInt() );\r\n}\r\n\r\nvoid Workshop::addJob( QString craftID, int mode, int number, QStringList mats )\r\n{\r\n\tCraftJob cj;\r\n\tcj.id              = GameState::createID();\r\n\tcj.craftID         = craftID;\r\n\tcj.mode            = (CraftMode)mode;\r\n\tcj.numItemsToCraft = number;\r\n\r\n\tauto row              = DB::selectRow( \"Crafts\", craftID );\r\n\tcj.itemSID            = row.value( \"ItemID\" ).toString();\r\n\tcj.conversionMaterial = row.value( \"ConversionMaterial\" ).toString();\r\n\tcj.resultMaterial     = row.value( \"ResultMaterial\" ).toString();\r\n\tcj.itemsPerCraft      = row.value( \"Amount\" ).toInt();\r\n\tcj.productionTime     = row.value( \"ProductionTime\" ).toInt();\r\n\tcj.skillID            = row.value( \"SkillID\" ).toString();\r\n\r\n\tauto rows = DB::selectRows( \"Crafts_Components\", craftID );\r\n\tif ( mats.size() != rows.size() )\r\n\t{\r\n\t\t//something went wrong, this should never happen, but if we are here it happened\r\n\t\tqDebug() << \"error creating craft job\";\r\n\t\treturn;\r\n\t}\r\n\tfor ( int i = 0; i < rows.size(); ++i )\r\n\t{\r\n\t\tauto compRow = rows[i];\r\n\t\tInputItem ii;\r\n\t\tii.itemSID     = compRow.value( \"ItemID\" ).toString();\r\n\t\tii.amount      = compRow.value( \"Amount\" ).toInt();\r\n\t\tii.materialSID = mats[i];\r\n\t\tii.requireSame = compRow.value( \"RequireSame\" ).toBool();\r\n\t\tcj.requiredItems.append( ii );\r\n\t}\r\n\tm_jobList.append( cj );\r\n}\r\n\r\nvoid Workshop::checkAutoGenerate( CraftJob cj )\r\n{\r\n\tif ( !m_active || m_properties.noAutoGenerate )\r\n\t\treturn;\r\n\tauto reqItems = cj.requiredItems;\r\n\t//int numToBuild = jm.value( \"CraftNumberValue\" ).toInt();\r\n\tfor ( auto ri : reqItems )\r\n\t{\r\n\t\tint avail = g->inv()->itemCount( ri.itemSID, ri.materialSID );\r\n\t\tif ( avail >= ri.amount )\r\n\t\t{\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tg->wsm()->autoGenCraftJob( ri.itemSID, ri.materialSID, ri.amount - avail );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Workshop::moveJob( unsigned int jobDefID, QString moveCmd )\r\n{\r\n\tfor ( int i = 0; i < m_jobList.size(); ++i )\r\n\t{\r\n\t\tif ( m_jobList[i].id == jobDefID )\r\n\t\t{\r\n\t\t\tif ( moveCmd == \"Top\" )\r\n\t\t\t{\r\n\t\t\t\tif ( i > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto cj = m_jobList.takeAt( i );\r\n\t\t\t\t\tm_jobList.push_front( cj );\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( moveCmd == \"Up\" )\r\n\t\t\t{\r\n\t\t\t\tif ( i > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_jobList.move( i, i - 1 );\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( moveCmd == \"Down\" )\r\n\t\t\t{\r\n\t\t\t\tif ( i < m_jobList.size() - 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_jobList.move( i, i + 1 );\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( moveCmd == \"Bottom\" )\r\n\t\t\t{\r\n\t\t\t\tif ( i < m_jobList.size() - 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto cj = m_jobList.takeAt( i );\r\n\t\t\t\t\tm_jobList.push_back( cj );\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\treturn false;\r\n}\r\n\r\nvoid Workshop::moveJob( int pos, int newPos )\r\n{\r\n\tm_jobList.move( pos, newPos );\r\n}\r\n\r\nbool Workshop::setJobParams( unsigned int craftJobID, int mode, int numToCraft, bool suspended, bool moveBack )\r\n{\r\n\tfor ( auto& cj : m_jobList )\r\n\t{\r\n\t\tif ( cj.id == craftJobID )\r\n\t\t{\r\n\t\t\tcj.mode               = (CraftMode)mode;\r\n\t\t\tcj.numItemsToCraft    = numToCraft;\r\n\t\t\tcj.paused             = suspended;\r\n\t\t\tcj.moveToBackWhenDone = moveBack;\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Workshop::setJobSuspended( unsigned int jobDefID, bool suspended )\r\n{\r\n\tfor ( auto& cj : m_jobList )\r\n\t{\r\n\t\tif ( cj.id == jobDefID )\r\n\t\t{\r\n\t\t\tcj.paused = suspended;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid Workshop::cancelJob( unsigned int jobDefID )\r\n{\r\n\tfor ( int i = 0; i < m_jobList.size(); ++i )\r\n\t{\r\n\t\tif ( m_jobList[i].id == jobDefID )\r\n\t\t{\r\n\t\t\tm_jobList.removeAt( i );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( m_job )\r\n\t{\r\n\t\tQSharedPointer<Job> spJob = m_job.toStrongRef();\r\n\t\tif ( spJob->craftJobID() == jobDefID )\r\n\t\t{\r\n\t\t\tQSharedPointer<Job> spJob = m_job.toStrongRef();\r\n\t\t\tg->jm()->deleteJob( spJob->id() );\r\n\t\t\tm_currentCraftJobID = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool Workshop::canCraft( QString itemSID, QString materialSID )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn false;\r\n\t//test if workshop is able to build item\r\n\tconst auto possibleCrafts = DBH::workshopPossibleCraftResults( type() );\r\n\tif ( !possibleCrafts.contains(itemSID) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst auto& possibleMaterials = possibleCrafts[itemSID];\r\n\r\n\tQString craftID;\r\n\tif ( materialSID != \"any\" )\r\n\t{\r\n\t\tQString matType = Global::util->materialType( materialSID );\r\n\t\tif ( !possibleMaterials.contains(matType ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tcraftID = possibleMaterials.value( matType );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcraftID = possibleMaterials.first();\r\n\t}\r\n\r\n\tif ( craftID.isEmpty() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool Workshop::autoCraft( QString itemSID, QString materialSID, int amount )\r\n{\r\n\tif ( !m_active )\r\n\t\treturn false;\r\n\t//test if workshop is able to build item\r\n\tconst auto possibleCrafts = DBH::workshopPossibleCraftResults( type() );\r\n\tif ( !possibleCrafts.contains(itemSID) )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tconst auto& possibleMaterials = possibleCrafts[itemSID];\r\n\r\n\tQString craftID;\r\n\tif ( materialSID != \"any\" )\r\n\t{\r\n\t\tQString matType = Global::util->materialType( materialSID );\r\n\t\tif ( !possibleMaterials.contains(matType ) )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tcraftID = possibleMaterials.value( matType );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tcraftID = possibleMaterials.first();\r\n\t}\r\n\r\n\tif ( craftID.isEmpty() )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\t// create job\r\n\tCraftJob cj;\r\n\tcj.id\t\t\t\t  = GameState::createID();\r\n\tcj.craftID            = craftID;\r\n\tcj.mode               = CraftMode::CraftNumber;\r\n\tcj.numItemsToCraft    = amount;\r\n\tcj.moveToBackWhenDone = false;\r\n\tcj.paused             = false;\r\n\r\n\tQVariantMap cm        = DB::selectRow( \"Crafts\", craftID );\r\n\tcj.itemSID            = cm.value( \"ItemID\" ).toString();\r\n\tcj.itemsPerCraft      = cm.value( \"Amount\" ).toInt();\r\n\tcj.conversionMaterial = cm.value( \"ConversionMaterial\" ).toString();\r\n\tcj.skillID            = cm.value( \"SkillID\" ).toString();\r\n\r\n\tauto components = DB::selectRows( \"Crafts_Components\", craftID );\r\n\r\n\tfor ( int i = 0; i < components.size(); ++i )\r\n\t{\r\n\t\tauto comp = components[i];\r\n\r\n\t\tQString materialID = materialSID;\r\n\t\tif ( i > 0 )\r\n\t\t{\r\n\t\t\tmaterialID = \"any\";\r\n\t\t}\r\n\t\tInputItem reqItem;\r\n\t\treqItem.itemSID     = comp.value( \"ItemID\" ).toString();\r\n\t\treqItem.materialSID = materialID;\r\n\t\treqItem.amount      = qMax( 1, comp.value( \"Amount\" ).toInt() );\r\n\t\treqItem.requireSame = comp.value( \"RequireSame\" ).toBool();\r\n\r\n\t\tcj.requiredItems.push_back( reqItem );\r\n\t}\r\n\r\n\tcheckAutoGenerate( cj );\r\n\r\n\tm_autoCraftList.push_back( cj );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool Workshop::hasCraftJob( const QString& itemSID, const QString& materialSID )\r\n{\r\n\tif( materialSID == \"any\" )\r\n\t{\r\n\t\tfor( const auto& cj : m_jobList )\r\n\t\t{\r\n\t\t\tif( cj.itemSID == itemSID )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor( const auto& cj : m_autoCraftList )\r\n\t\t{\r\n\t\t\tif( cj.itemSID == itemSID )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tfor( const auto& cj : m_jobList )\r\n\t\t{\r\n\t\t\tif( cj.itemSID == itemSID )\r\n\t\t\t{\r\n\t\t\t\tif( cj.requiredItems.size() )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst auto& reqItem = cj.requiredItems.first();\r\n\t\t\t\t\tif( reqItem.materialSID == materialSID )\r\n\t\t\t\t\t{\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\tfor( const auto& cj : m_autoCraftList )\r\n\t\t{\r\n\t\t\tif( cj.itemSID == itemSID )\r\n\t\t\t{\r\n\t\t\t\tif( cj.requiredItems.size() )\r\n\t\t\t\t{\r\n\t\t\t\t\tconst auto& reqItem = cj.requiredItems.first();\r\n\t\t\t\t\tif( reqItem.materialSID == materialSID )\r\n\t\t\t\t\t{\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\treturn false;\r\n}\r\n\r\nbool Workshop::createJobFromCraftJob( CraftJob& cj )\r\n{\r\n\tauto jobID = g->jm()->addJob( \"CraftAtWorkshop\", m_properties.pos, m_properties.rotation, true );\r\n\tauto job = g->jm()->getJob( jobID );\r\n\tif( job )\r\n\t{\r\n\t\tm_currentJobID = jobID;\r\n\t\tm_currentCraftJobID = cj.id;\r\n\t\tjob->setItem( cj.itemSID );\r\n\t\tjob->setConversionMaterial( cj.conversionMaterial );\r\n\t\tjob->setMaterial( cj.resultMaterial );\r\n\t\tjob->setAmount( cj.itemsPerCraft );\r\n\t\tjob->setRequiredSkill( cj.skillID );\r\n\t\tjob->setPosItemInput( m_properties.posIn );\r\n\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\t\tjob->setDescription( Global::util->itemName( cj.itemSID ) );\r\n\t\tjob->setCraftID( cj.craftID );\r\n\t\tjob->setCraftJobID( cj.id );\r\n\t\tfor ( auto ri : cj.requiredItems )\r\n\t\t{\r\n\t\t\tjob->addRequiredItem( ri.amount, ri.itemSID, ri.materialSID, {}, ri.requireSame );\r\n\t\t}\r\n\t\tm_job = job;\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nQSharedPointer<Job> Workshop::createButcherJob()\r\n{\r\n\tfor ( auto& pasture : g->fm()->allPastures() )\r\n\t{\r\n\t\tif ( g->pf()->checkConnectedRegions( pasture->firstPos(), m_properties.pos ) )\r\n\t\t{\r\n\t\t\tfor ( const auto& animalID : pasture->animals() )\r\n\t\t\t{\r\n\t\t\t\tauto animal = g->cm()->animal( animalID );\r\n\t\t\t\tif ( animal )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( animal->toButcher() && !animal->inJob() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( g->pf()->checkConnectedRegions( animal->getPos(), m_properties.pos ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tauto jobID = g->jm()->addJob( \"ButcherAnimal\", animal->getPos(), 0, true );\r\n\t\t\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\t\t\tif( job )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tjob->setAnimal( animalID );\r\n\t\t\t\t\t\t\t\tanimal->setInJob( job->id() );\r\n\t\t\t\t\t\t\t\tjob->setPos( animal->getPos() );\r\n\t\t\t\t\t\t\t\tjob->addPossibleWorkPosition( m_properties.pos );\r\n\t\t\t\t\t\t\t\tjob->setPosItemInput( m_properties.posIn );\r\n\t\t\t\t\t\t\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\t\t\t\t\t\t\t\treturn job;\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\tif ( m_properties.butcherExcess )\r\n\t{\r\n\t\tfor ( auto& a : g->cm()->animals() )\r\n\t\t{\r\n\t\t\tif ( a->isTame() && a->pastureID() == 0 && a->isAdult() && !a->toDestroy() && !a->isDead() && !a->inJob() )\r\n\t\t\t{\r\n\t\t\t\tif ( g->pf()->checkConnectedRegions( a->getPos(), m_properties.pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto jobID = g->jm()->addJob( \"ButcherAnimal\", a->getPos(), 0, true );\r\n\t\t\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\t\t\tif( job )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjob->setAnimal( a->id() );\r\n\t\t\t\t\t\ta->setInJob( job->id() );\r\n\t\t\t\t\t\tjob->setPos( a->getPos() );\r\n\t\t\t\t\t\tjob->addPossibleWorkPosition( m_properties.pos );\r\n\t\t\t\t\t\tjob->setPosItemInput( m_properties.posIn );\r\n\t\t\t\t\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\t\t\t\t\t\treturn job;\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 ( m_properties.butcherCorpses )\r\n\t{\r\n\t\tQString itemID = \"\";\r\n\t\tif ( g->inv()->itemCount( \"AnimalCorpse\", \"any\" ) > 0 )\r\n\t\t{\r\n\t\t\titemID = \"AnimalCorpse\";\r\n\t\t}\r\n\t\telse if ( g->inv()->itemCount( \"GoblinCorpse\", \"any\" ) > 0 )\r\n\t\t{\r\n\t\t\titemID = \"GoblinCorpse\";\r\n\t\t}\r\n\r\n\t\tif ( !itemID.isEmpty() )\r\n\t\t{\r\n\t\t\tauto jobID = g->jm()->addJob( \"ButcherCorpse\", m_properties.pos, 0, true );\r\n\t\t\tauto job = g->jm()->getJob( jobID );\r\n\t\t\tif( job )\r\n\t\t\t{\r\n\t\t\t\tjob->addPossibleWorkPosition( m_properties.pos );\r\n\t\t\t\tjob->setPos( m_properties.pos );\r\n\t\t\t\tjob->setPosItemInput( m_properties.posIn );\r\n\t\t\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\r\n\t\t\t\tint amount         = 1;\r\n\t\t\t\tQString materialID = \"any\";\r\n\t\t\t\tjob->addRequiredItem( amount, itemID, materialID, QStringList(), false );\r\n\r\n\t\t\t\treturn job;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQSharedPointer<Job> Workshop::createDyeSheepJob()\r\n{\r\n\tfor ( auto pair : m_toDye )\r\n\t{\r\n\t\tunsigned int animalID = pair.first;\r\n\t\tauto animal           = g->cm()->animal( animalID );\r\n\t\tif ( animal && !animal->inJob() )\r\n\t\t{\r\n\t\t\tif ( g->pf()->checkConnectedRegions( animal->getPos(), m_properties.pos ) )\r\n\t\t\t{\r\n\t\t\t\tQSharedPointer<Job> job( new Job() );\r\n\t\t\t\tjob->setType( \"DyeAnimal\" );\r\n\t\t\t\tjob->setRequiredSkill( \"Dyeing\" );\r\n\t\t\t\tjob->setAnimal( animalID );\r\n\t\t\t\tjob->addRequiredItem( 1, \"Dye\", pair.second, { \"Dye\" }, false );\r\n\t\t\t\tjob->setMaterial( pair.second );\r\n\t\t\t\tanimal->setInJob( job->id() );\r\n\t\t\t\tjob->setPos( animal->getPos() );\r\n\t\t\t\tjob->addPossibleWorkPosition( m_properties.pos );\r\n\t\t\t\tjob->setPosItemInput( m_properties.posIn );\r\n\t\t\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\r\n\t\t\t\treturn job;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQSharedPointer<Job> Workshop::createFisherJob()\r\n{\r\n\tPosition pos   = m_properties.posIn;\r\n\tint waterLevel = 0;\r\n\twaterLevel += g->w()->fluidLevel( pos );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( 0, -1, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( 1, -1, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( -1, -1, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( 0, 0, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( 1, 0, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( -1, 0, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( 0, 1, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( 1, 1, -1 ) );\r\n\twaterLevel += g->w()->fluidLevel( pos + Position( -1, 1, -1 ) );\r\n\r\n\tif ( waterLevel > 40 )\r\n\t{\r\n\t\tauto jobID = g->jm()->addJob( \"Fish\", pos, 0, true );\r\n\t\tauto job = g->jm()->getJob( jobID );\r\n\t\tif( job )\r\n\t\t{\r\n\t\t\tjob->setRequiredTool( \"FishingRod\", 0 );\r\n\t\t\tjob->addPossibleWorkPosition( pos );\r\n\t\t\tjob->setPosItemInput( pos );\r\n\t\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\t\t\treturn job;\r\n\t\t}\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nQSharedPointer<Job> Workshop::createFishButcherJob()\r\n{\r\n\tif ( g->inv()->itemCount( \"Fish\", \"any\" ) == 0 )\r\n\t{\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tauto jobID = g->jm()->addJob( \"ButcherFish\", m_properties.posOut, 0, true );\r\n\tauto job = g->jm()->getJob( jobID );\r\n\tif( job )\r\n\t{\r\n\t\tjob->setRequiredSkill( \"Fishing\" );\r\n\t\tjob->addPossibleWorkPosition( m_properties.pos );\r\n\t\tjob->setPos( m_properties.posOut );\r\n\t\tjob->setPosItemInput( m_properties.posOut );\r\n\t\tjob->setPosItemOutput( m_properties.posOut );\r\n\r\n\t\tQString itemID     = \"Fish\";\r\n\t\tint amount         = 1;\r\n\t\tQString materialID = \"any\";\r\n\t\tjob->addRequiredItem( amount, itemID, materialID, QStringList(), false );\r\n\r\n\t\treturn job;\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nbool Workshop::checkItemsAvailable( CraftJob& cj )\r\n{\r\n\t// restrictions are already determined at CraftJob creation\r\n\t//\r\n\tbool allFound = true;\r\n\tfor ( int i = 0; i < cj.requiredItems.size(); ++i )\r\n\t{\r\n\t\tauto& ri                 = cj.requiredItems[i];\r\n\r\n\t\tint count               = ri.amount;\r\n\t\tQString itemID          = ri.itemSID;\r\n\t\tQString materialID      = ri.materialSID;\r\n\t\tbool requireSame        = ri.requireSame;\r\n\r\n\t\tQList<unsigned int> items;\r\n\r\n\t\tif( materialID == \"any\" && requireSame )\r\n\t\t{\r\n\t\t\t// will always return 0 if item count is less than needed\r\n\t\t\tri.avail = 0;\r\n\t\t\tQList<QString> materials = g->inv()->materialsForItem( itemID, count );\r\n\t\t\tfor ( auto mat : materials )\r\n\t\t\t{\r\n\t\t\t\titems = g->inv()->getClosestItems( m_properties.posIn, true, itemID, mat, count );\r\n\t\t\t\tif ( items.size() < count )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tri.avail = items.size();\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\titems = g->inv()->getClosestItems( m_properties.posIn, true, itemID, materialID, count );\r\n\t\t\tri.avail = items.size();\r\n\t\t}\r\n\r\n\t\tif( ri.avail < ri.amount )\r\n\t\t{\r\n\t\t\tallFound = false;\r\n\t\t\tif( Global::craftable.contains( itemID ) )\r\n\t\t\t{\r\n\t\t\t\tg->wsm()->autoGenCraftJob( itemID, materialID, count - items.size() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn allFound;\r\n}\r\n\r\nbool Workshop::finishJob( unsigned int craftJobID )\r\n{\r\n\tif ( !m_jobList.empty() )\r\n\t{\r\n\t\t// check job conditions\r\n\t\tfor ( int i = 0; i < m_jobList.size(); ++i )\r\n\t\t{\r\n\t\t\tif ( craftJobID == m_jobList[i].id )\r\n\t\t\t{\r\n\t\t\t\tCraftJob cj = m_jobList.takeAt( i );\r\n\t\t\t\tcj.alreadyCrafted += cj.itemsPerCraft;\r\n\r\n\t\t\t\tif ( cj.mode == CraftMode::Repeat )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( cj.moveToBackWhenDone )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_jobList.push_back( cj );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_jobList.insert( i, cj );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( m_properties.craftIngredients )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcheckAutoGenerate( cj );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse if ( cj.mode == CraftMode::CraftNumber )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( cj.numItemsToCraft > cj.alreadyCrafted )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( cj.moveToBackWhenDone )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_jobList.push_back( cj );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tm_jobList.insert( i, cj );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( m_properties.craftIngredients )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcheckAutoGenerate( cj );\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\telse if ( cj.mode == CraftMode::CraftTo )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( cj.moveToBackWhenDone )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_jobList.push_back( cj );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_jobList.insert( i, cj );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tg->wsm()->emitJobListChanged( m_id );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid Workshop::destroy()\r\n{\r\n\tm_jobList.clear();\r\n\r\n\tif ( m_job )\r\n\t{\r\n\t\tQSharedPointer<Job> spJob = m_job.toStrongRef();\r\n\t\tspJob->setCanceled();\r\n\t}\r\n\tif ( m_fishingJob )\r\n\t{\r\n\t\tQSharedPointer<Job> spJob = m_fishingJob.toStrongRef();\r\n\t\tspJob->setCanceled();\r\n\t}\r\n\tm_properties.toDestroy = true;\r\n}\r\n\r\nbool Workshop::canDelete()\r\n{\r\n\treturn m_properties.canDelete;\r\n}\r\n\r\nvoid Workshop::setLinkedStockpile( bool link )\r\n{\r\n\tif ( link )\r\n\t{\r\n\t\tm_properties.linkedStockpile = getPossibleStockpile();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_properties.linkedStockpile = 0;\r\n\t}\r\n\tqDebug() << \"linked stockpile:\" << m_properties.linkedStockpile;\r\n}\r\n\r\nunsigned int Workshop::getPossibleStockpile()\r\n{\r\n\tconst Position candidates[]  = {\r\n\t\tm_properties.posIn.northOf(),\r\n\t\tm_properties.posIn.westOf(),\r\n\t\tm_properties.posIn.southOf(),\r\n\t\tm_properties.posIn.eastOf(),\r\n\t};\r\n\tPosition spPos;\r\n\tbool isStockpile = false;\r\n\r\n\tfor ( const auto& candidate : candidates )\r\n\t{\r\n\t\tif ( g->w()->getTileFlag( candidate ) & TileFlag::TF_STOCKPILE )\r\n\t\t{\r\n\t\t\tspPos       = candidate;\r\n\t\t\tisStockpile = true;\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( isStockpile )\r\n\t{\r\n\t\tStockpile* sp = g->spm()->getStockpileAtPos( spPos );\r\n\t\tif ( sp && sp->getFields().size() < 10 )\r\n\t\t{\r\n\t\t\tshort xMin = Global::dimX;\r\n\t\t\tshort yMin = Global::dimY;\r\n\t\t\tshort xMax = 0;\r\n\t\t\tshort yMax = 0;\r\n\r\n\t\t\tfor ( auto spField : sp->getFields() )\r\n\t\t\t{\r\n\t\t\t\tPosition pos = spField->pos;\r\n\t\t\t\txMin         = qMin( xMin, pos.x );\r\n\t\t\t\txMax         = qMax( xMax, pos.x );\r\n\t\t\t\tyMin         = qMin( yMin, pos.y );\r\n\t\t\t\tyMax         = qMax( yMax, pos.y );\r\n\t\t\t}\r\n\t\t\tif ( ( xMax - xMin ) < 3 && ( yMax - yMin ) < 3 )\r\n\t\t\t{\r\n\t\t\t\treturn sp->id();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nunsigned int Workshop::linkedStockpile()\r\n{\r\n\treturn m_properties.linkedStockpile;\r\n}\r\n\r\nbool Workshop::outputTileFree()\r\n{\r\n\tPosition pos = outputPos();\r\n\t//TODO make number configurable\r\n\r\n\tbool isFree = g->inv()->countItemsAtPos( pos ) < 20;\r\n\r\n\tif ( !isFree )\r\n\t{\r\n\t\tbool alreadySet = g->w()->getTileFlag( m_tiles.first() ) & TileFlag::TF_BLOCKED;\r\n\r\n\t\tif ( !alreadySet )\r\n\t\t{\r\n\t\t\tfor ( auto pos : m_tiles )\r\n\t\t\t{\r\n\t\t\t\tg->w()->setTileFlag( pos, TileFlag::TF_BLOCKED );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tbool alreadySet = g->w()->getTileFlag( m_tiles.first() ) & TileFlag::TF_BLOCKED;\r\n\r\n\t\tif ( alreadySet )\r\n\t\t{\r\n\t\t\tfor ( auto pos : m_tiles )\r\n\t\t\t{\r\n\t\t\t\tg->w()->clearTileFlag( pos, TileFlag::TF_BLOCKED );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn ( isFree );\r\n}\r\n\r\nvoid Workshop::setAcceptGenerated( bool accept )\r\n{\r\n\tm_properties.acceptGenerated = accept;\r\n}\r\n\r\nbool Workshop::isAcceptingGenerated()\r\n{\r\n\treturn m_properties.acceptGenerated && !m_properties.noAutoGenerate;\r\n}\r\n\r\nvoid Workshop::setAutoCraftMissing( bool autoCraft )\r\n{\r\n\tm_properties.craftIngredients = autoCraft;\r\n}\r\n\r\nbool Workshop::getAutoCraftMissing()\r\n{\r\n\treturn m_properties.craftIngredients;\r\n}\r\n\r\nvoid Workshop::setItemsToSell( QVariantList items )\r\n{\r\n\tm_properties.itemsToSell = items;\r\n}\r\n\r\nQVariantList Workshop::getItemsToSell()\r\n{\r\n\treturn m_properties.itemsToSell;\r\n}\r\n\r\nvoid Workshop::assignGnome( unsigned int gnomeID )\r\n{\r\n\tm_properties.owner = gnomeID;\r\n\tif ( gnomeID == 0 )\r\n\t{\r\n\t\t//m_properties.remove( \"TraderInventory\" );\r\n\t}\r\n}\r\n\r\nunsigned int Workshop::assignedGnome()\r\n{\r\n\treturn m_properties.owner;\r\n}\r\n\r\nint Workshop::rotation()\r\n{\r\n\treturn m_properties.rotation;\r\n}\r\n\r\nvoid Workshop::setSourceItems( QVariantList items )\r\n{\r\n\tfor ( auto item : items )\r\n\t{\r\n\t\tg->inv()->pickUpItem( item.toUInt(), m_id );\r\n\t\tg->inv()->setConstructed( item.toUInt(), true );\r\n\t}\r\n\tm_properties.sourceItems = items;\r\n}\r\n\r\nQVariantList Workshop::sourceItems()\r\n{\r\n\treturn m_properties.sourceItems;\r\n}\r\n\r\nbool Workshop::noAutoGenerate()\r\n{\r\n\treturn m_properties.noAutoGenerate;\r\n}\r\n\r\nvoid Workshop::checkLinkedStockpile()\r\n{\r\n\tif ( linkedStockpile() )\r\n\t{\r\n\t\tStockpile* sp = g->spm()->getStockpile( linkedStockpile() );\r\n\t\tif ( sp )\r\n\t\t{\r\n\t\t\tif ( sp->countFields() > 9 )\r\n\t\t\t{\r\n\t\t\t\tsetLinkedStockpile( 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsetLinkedStockpile( 0 );\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/game/workshop.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../game/worldobject.h\"\r\n#include \"../game/job.h\"\r\n\r\n#include <QMap>\r\n#include <QVariantMap>\r\n\r\nclass Job;\r\n\r\n#pragma region CraftQueue;\r\nenum class CraftMode : unsigned char\r\n{\r\n\tCraftNumber,\r\n\tCraftTo,\r\n\tRepeat\r\n};\r\n\r\nstruct InputItem\r\n{\r\n\tQString itemSID;\r\n\tQString materialSID;\r\n\tint amount = 0;\r\n\tbool requireSame = false;\r\n\tint avail = 0;\r\n};\r\n\r\nstruct CraftJob\r\n{\r\n\tunsigned int id    = 0; // unique id for this craft job\r\n\r\n\tQString craftID;       // craft definition in DB table Crafts\r\n\tQString itemSID;       // the item to craft\r\n\tint itemsPerCraft = 1; // some recipes produce more than one item per single craft\r\n\r\n\tint numItemsToCraft = 1;\r\n\tCraftMode mode      = CraftMode::CraftNumber;\r\n\tint alreadyCrafted  = 0;\r\n\r\n\tQString skillID; // skill needed to accept this craft job\r\n\r\n\tQList<InputItem> requiredItems; // defined in DB::Crafts_Components, material is selected in the gui\r\n\tQString conversionMaterial;\r\n\tQString resultMaterial;\r\n\r\n\tint productionTime = 50;\r\n\r\n\t// crafting queue control\r\n\tbool moveToBackWhenDone = false; //move this job to the back of the queue when one item is finished\r\n\tbool paused             = false;\r\n\r\n\tCraftJob() {};\r\n\tCraftJob( QVariantMap& in );\r\n\tvoid serialize( QVariantMap& out );\r\n};\r\n#pragma endregion CraftQueue;\r\n\r\n#pragma region Properties;\r\nstruct WorkshopProperties\r\n{\r\n\tQString type = \"\";\r\n\tint rotation = 0;\r\n\tPosition pos;\r\n\tPosition posIn;\r\n\tPosition posOut;\r\n\r\n\tunsigned int owner           = 0;\r\n\tunsigned int linkedStockpile = 0;\r\n\r\n\tbool toDestroy = false;\r\n\tbool canDelete = false;\r\n\r\n\tbool butcherExcess  = false;\r\n\tbool butcherCorpses = true;\r\n\tbool fish           = false;\r\n\tbool processFish    = false;\r\n\r\n\tbool showMaterials    = true;\r\n\tbool showListControls = true;\r\n\tbool acceptGenerated  = true;\r\n\tbool craftIngredients = true;\r\n\r\n\tQVariantList sourceItems;\r\n\tQVariantList itemsToSell;\r\n\r\n\t// not saved in game, always loaded from DB\r\n\tQString gui;\r\n\tbool noAutoGenerate = false;\r\n\tQStringList crafts;\r\n\r\n\tvoid serialize( QVariantMap& out );\r\n\tWorkshopProperties() {};\r\n\tWorkshopProperties( QVariantMap& in );\r\n};\r\n#pragma endregion Properties;\r\n\r\nclass Workshop : public WorldObject\r\n{\r\n\tfriend class WorkshopManager;\r\n\tQ_DISABLE_COPY_MOVE( Workshop )\r\npublic:\r\n\tWorkshop() = delete;\r\n\tWorkshop( QString type, Position& pos, int rotation, Game* game );\r\n\tWorkshop( QVariantMap values, Game* game );\r\n\t~Workshop();\r\n\r\n\tQVariant serialize();\r\n\r\n\tvoid onTick( quint64 tick );\r\n\r\n\tPosition pos()\r\n\t{\r\n\t\treturn m_properties.pos;\r\n\t}\r\n\tvoid setPos( Position& pos )\r\n\t{\r\n\t\tm_properties.pos = pos;\r\n\t}\r\n\r\n\tbool isOnTile( const Position& pos );\r\n\tQString type()\r\n\t{\r\n\t\treturn m_properties.type;\r\n\t}\r\n\r\n\tvoid addJob( QString craftID, int mode, int number, QStringList mats );\r\n\r\n\tvoid checkAutoGenerate( CraftJob cj );\r\n\r\n\tvoid setJobSuspended( unsigned int jobDefID, bool suspended );\r\n\tbool moveJob( unsigned int jobDefID, QString moveCmd );\r\n\tvoid moveJob( int pos, int newPos );\r\n\tbool autoCraft( QString itemSID, QString materialSID, int amount );\r\n\tbool canCraft( QString itemSID, QString materialSID );\r\n\r\n\tbool setJobParams( unsigned int craftJobID, int mode, int numToCraft, bool suspended, bool moveBack );\r\n\r\n\tbool createJobFromCraftJob( CraftJob& cj );\r\n\tQSharedPointer<Job> createButcherJob();\r\n\tQSharedPointer<Job> createDyeSheepJob();\r\n\tQSharedPointer<Job> createFisherJob();\r\n\tQSharedPointer<Job> createFishButcherJob();\r\n\r\n\tvoid setLinkedStockpile( bool link );\r\n\tunsigned int linkedStockpile();\r\n\r\n\tPosition inputPos()\r\n\t{\r\n\t\treturn m_properties.posIn;\r\n\t}\r\n\tPosition outputPos()\r\n\t{\r\n\t\treturn m_properties.posOut;\r\n\t}\r\n\r\n\tvoid setSprites( QVariantList sprites )\r\n\t{\r\n\t\tm_spriteComposition = sprites;\r\n\t}\r\n\tQVariantList sprites()\r\n\t{\r\n\t\treturn m_spriteComposition;\r\n\t}\r\n\r\n\tvoid destroy();\r\n\tbool canDelete();\r\n\r\n\tbool outputTileFree();\r\n\r\n\tQMap<unsigned int, Position>& tiles()\r\n\t{\r\n\t\treturn m_tiles;\r\n\t}\r\n\r\n\tQList<QPair<unsigned int, QString>>& toDyeList()\r\n\t{\r\n\t\treturn m_toDye;\r\n\t}\r\n\r\n\tvoid setButcherExcess( bool value )\r\n\t{\r\n\t\tm_properties.butcherExcess = value;\r\n\t}\r\n\tvoid setButcherCorpses( bool value )\r\n\t{\r\n\t\tm_properties.butcherCorpses = value;\r\n\t}\r\n\tbool butcherExcess()\r\n\t{\r\n\t\treturn m_properties.butcherExcess;\r\n\t}\r\n\tbool butcherCorpses()\r\n\t{\r\n\t\treturn m_properties.butcherCorpses;\r\n\t}\r\n\r\n\tvoid setFish( bool value )\r\n\t{\r\n\t\tm_properties.fish = value;\r\n\t}\r\n\tvoid setProcessFish( bool value )\r\n\t{\r\n\t\tm_properties.processFish = value;\r\n\t}\r\n\tbool fish()\r\n\t{\r\n\t\treturn m_properties.fish;\r\n\t}\r\n\tbool processFish()\r\n\t{\r\n\t\treturn m_properties.processFish;\r\n\t}\r\n\r\n\tQList<CraftJob> jobList()\r\n\t{\r\n\t\treturn m_jobList;\r\n\t}\r\n\r\n\tQString gui()\r\n\t{\r\n\t\treturn m_properties.gui;\r\n\t}\r\n\r\n\tconst QStringList& crafts()\r\n\t{\r\n\t\treturn m_properties.crafts;\r\n\t}\r\n\r\n\tvoid setAcceptGenerated( bool accept );\r\n\tbool isAcceptingGenerated();\r\n\r\n\tvoid setAutoCraftMissing( bool autoCraft );\r\n\tbool getAutoCraftMissing();\r\n\r\n\tvoid setItemsToSell( QVariantList items );\r\n\tQVariantList getItemsToSell();\r\n\r\n\tvoid assignGnome( unsigned int gnomeID );\r\n\tunsigned int assignedGnome();\r\n\r\n\tint rotation();\r\n\r\n\tvoid setSourceItems( QVariantList items );\r\n\tQVariantList sourceItems();\r\n\r\n\tvoid checkLinkedStockpile();\r\n\tunsigned int getPossibleStockpile();\r\n\r\n\tbool noAutoGenerate();\r\n\r\n\tvoid cancelJob( unsigned int jobDefID );\r\n\r\n\tbool hasCraftJob( const QString& itemSID, const QString& materialSID );\r\n\r\n\tint numJobs() { return m_jobList.size(); }\r\n\r\nprivate:\r\n\t//only access through workshop manager\r\n\tbool finishJob( unsigned int craftJobID );\r\n\r\n\tWorkshopProperties m_properties;\r\n\r\n\tQMap<unsigned int, Position> m_tiles;\r\n\tQList<CraftJob> m_jobList;\r\n\tQList<CraftJob> m_autoCraftList;\r\n\r\n\tQWeakPointer<Job> m_job;\r\n\tunsigned int m_currentCraftJobID = 0;\r\n\tunsigned int m_currentJobID = 0; // only needed to retrieve the job pointer after load\r\n\t\r\n\tQWeakPointer<Job> m_fishingJob;\r\n\r\n\tQVariantList m_spriteComposition;\r\n\r\n\tbool checkItemsAvailable( CraftJob& cj );\r\n\r\n\tQList<QPair<unsigned int, QString>> m_toDye;\r\n};\r\n"
  },
  {
    "path": "src/game/workshopmanager.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"workshopmanager.h\"\r\n#include \"game.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n\r\nWorkshopManager::WorkshopManager( Game* parent ) :\r\n\tg( parent ),\r\n\tQObject( parent )\r\n{\r\n}\r\n\r\nWorkshopManager::~WorkshopManager()\r\n{\r\n\tfor ( const auto& ws : m_workshops )\r\n\t{\r\n\t\tdelete ws;\r\n\t}\r\n}\r\n\r\nvoid WorkshopManager::onTick( quint64 tick )\r\n{\r\n\tif ( !m_toDelete.isEmpty() )\r\n\t{\r\n\t\tint tds = m_toDelete.size();\r\n\t\tfor ( int i = 0; i < tds; ++i )\r\n\t\t{\r\n\t\t\tunsigned int id = m_toDelete.dequeue();\r\n\t\t\tWorkshop* ws    = workshop( id );\r\n\t\t\tif ( ws->canDelete() )\r\n\t\t\t{\r\n\t\t\t\tfor ( int k = 0; k < m_workshops.size(); ++k )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( m_workshops[k]->id() == id )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_workshops.removeAt( k );\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\telse\r\n\t\t\t{\r\n\t\t\t\tm_toDelete.enqueue( id );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto& w : m_workshops )\r\n\t{\r\n\t\tw->onTick( tick );\r\n\t}\r\n}\r\n\r\nWorkshop* WorkshopManager::addWorkshop( QString type, Position& pos, int rotation )\r\n{\r\n\tWorkshop* w = new Workshop( type, pos, rotation, g );\r\n\tm_workshops.push_back( w );\r\n\r\n\treturn m_workshops.last();\r\n}\r\n\r\nvoid WorkshopManager::addWorkshop( QVariantMap vals )\r\n{\r\n\tWorkshop* w = new Workshop( vals, g );\r\n\tm_workshops.push_back( w );\r\n}\r\n\r\nbool WorkshopManager::isWorkshop( Position& pos )\r\n{\r\n\tfor ( const auto& w : m_workshops )\r\n\t{\r\n\t\tif ( w->isOnTile( pos ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nWorkshop* WorkshopManager::workshopAt( const Position& pos )\r\n{\r\n\tfor ( auto& w : m_workshops )\r\n\t{\r\n\t\tif ( w->isOnTile( pos ) )\r\n\t\t{\r\n\t\t\treturn w;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nWorkshop* WorkshopManager::workshop( unsigned int ID )\r\n{\r\n\tfor ( auto& w : m_workshops )\r\n\t{\r\n\t\tif ( w->id() == ID )\r\n\t\t{\r\n\t\t\treturn w;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid WorkshopManager::deleteWorkshop( unsigned int workshopID )\r\n{\r\n\tm_toDelete.push_back( workshopID );\r\n}\r\n\r\nbool WorkshopManager::autoGenCraftJob( QString itemSID, QString materialSID, int amount )\r\n{\r\n\tif( !craftJobExists( itemSID, materialSID ) )\r\n\t{\r\n\t\tQList<Workshop*> possibles;\r\n\t\tfor ( auto&& w : m_workshops )\r\n\t\t{\r\n\t\t\tif ( w->isAcceptingGenerated() )\r\n\t\t\t{\r\n\t\t\t\tif( w->canCraft( itemSID, materialSID ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tpossibles.append( w );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tauto compare = []( Workshop* a, Workshop* b) { return a->numJobs() < b->numJobs(); };\r\n\t\tstd::sort( std::begin( possibles ), std::end( possibles ), compare );\r\n\r\n\t\tfor ( auto&& w : possibles )\r\n\t\t{\r\n\t\t\tif ( w->autoCraft( itemSID, materialSID, amount ) )\r\n\t\t\t{\r\n\t\t\t\temit signalJobListChanged( w->id() );\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool WorkshopManager::craftJobExists( const QString& itemSID, const QString& materialSID )\r\n{\r\n\tfor ( const auto& w : m_workshops )\r\n\t{\r\n\t\tif ( w->isAcceptingGenerated() )\r\n\t\t{\r\n\t\t\tif ( w->hasCraftJob( itemSID, materialSID ) )\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid WorkshopManager::setPriority( unsigned int workshopID, int prio )\r\n{\r\n\tif( prio > 0 && prio < m_workshops.size() )\r\n\t{\r\n\t\tint current = 0;\r\n\t\tfor ( const auto& w : m_workshops )\r\n\t\t{\r\n\t\t\tif ( w->id() == workshopID )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\t++current;\r\n\t\t}\r\n\t\tm_workshops.move( current, prio );\r\n\t}\r\n}\r\n\r\nint WorkshopManager::priority( unsigned int workshopID )\r\n{\r\n\tint current = 0;\r\n\tfor ( const auto& w : m_workshops )\r\n\t{\r\n\t\tif ( w->id() == workshopID )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t++current;\r\n\t}\r\n\treturn current;\r\n}\r\n\r\nQList<Workshop*> WorkshopManager::getTrainingGrounds()\r\n{\r\n\tQList<Workshop*> out;\r\n\tfor ( auto& w : m_workshops )\r\n\t{\r\n\t\tif ( w->type() == \"MeleeTraining\" )\r\n\t\t{\r\n\t\t\tout.append( w );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n\r\nvoid WorkshopManager::emitJobListChanged( unsigned int workshopID )\r\n{\r\n\temit signalJobListChanged( workshopID );\r\n}"
  },
  {
    "path": "src/game/workshopmanager.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n\r\n#include \"workshop.h\"\r\n\r\n#include <QList>\r\n#include <QObject>\r\n#include <QQueue>\r\n\r\nclass Job;\r\nclass Game;\r\n\r\nclass WorkshopManager : public QObject\r\n{\r\n\tQ_OBJECT\r\n\tQ_DISABLE_COPY_MOVE( WorkshopManager )\r\npublic:\r\n\tWorkshopManager( Game* parent = 0 );\r\n\t~WorkshopManager();\r\n\r\n\tvoid onTick( quint64 tick );\r\n\tWorkshop* addWorkshop( QString type, Position& pos, int rotation );\r\n\tvoid addWorkshop( QVariantMap vals );\r\n\r\n\tbool isWorkshop( Position& pos );\r\n\tWorkshop* workshopAt( const Position& pos );\r\n\tWorkshop* workshop( unsigned int ID );\r\n\r\n\tQList<Workshop*>& workshops()\r\n\t{\r\n\t\treturn m_workshops;\r\n\t}\r\n\r\n\tvoid deleteWorkshop( unsigned int workshopID );\r\n\r\n\t//void setJobQueueJson( unsigned int workshopID, QVariantMap vals );\r\n\r\n\tbool autoGenCraftJob( QString itemSID, QString materialSID, int amount );\r\n\r\n\tint count()\r\n\t{\r\n\t\treturn m_workshops.size();\r\n\t}\r\n\r\n\tvoid setPriority( unsigned int workshopID, int prio );\r\n\tint priority( unsigned int workshopID );\r\n\tint maxPriority()\r\n\t{\r\n\t\treturn m_workshops.size();\r\n\t}\r\n\r\n\tQList<Workshop*> getTrainingGrounds();\r\n\r\n\tbool craftJobExists( const QString& itemSID, const QString& materialSID );\r\n\r\n\tvoid emitJobListChanged( unsigned int workshopID );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQList<Workshop*> m_workshops;\r\n\tQQueue<unsigned int> m_toDelete;\r\n\r\nsignals:\r\n\tvoid signalJobListChanged( unsigned int workshopID );\r\n};\r\n"
  },
  {
    "path": "src/game/world.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"world.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/position.h\"\r\n#include \"../base/util.h\"\r\n#include \"../base/vptr.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"../gui/eventconnector.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n#include <QVector3D>\r\n\r\n#include <random>\r\n#include <time.h>\r\n\r\nWorld::World( int dimX, int dimY, int dimZ, Game* game ) :\r\n\tg( game ),\r\n\tm_dimX( dimX ),\r\n\tm_dimY( dimY ),\r\n\tm_dimZ( dimZ ),\r\n\tm_regionMap( this )\r\n{\r\n\tm_constructionSID2ENUM.insert( \"Wall\", CID_WALL );\r\n\tm_constructionSID2ENUM.insert( \"FancyWall\", CID_FANCYWALL );\r\n\tm_constructionSID2ENUM.insert( \"Fence\", CID_FENCE );\r\n\tm_constructionSID2ENUM.insert( \"Floor\", CID_FLOOR );\r\n\tm_constructionSID2ENUM.insert( \"FancyFloor\", CID_FANCYFLOOR );\r\n\tm_constructionSID2ENUM.insert( \"WallFloor\", CID_WALLFLOOR );\r\n\tm_constructionSID2ENUM.insert( \"Stairs\", CID_STAIRS );\r\n\tm_constructionSID2ENUM.insert( \"Ramp\", CID_RAMP );\r\n\tm_constructionSID2ENUM.insert( \"RampCorner\", CID_RAMPCORNER );\r\n\tm_constructionSID2ENUM.insert( \"Item\", CID_ITEM );\r\n\tm_constructionSID2ENUM.insert( \"Workshop\", CID_WORKSHOP );\r\n\r\n\tm_constrItemSID2ENUM.insert( \"Containers\", CI_STORAGE );\r\n\tm_constrItemSID2ENUM.insert( \"Furniture\", CI_FURNITURE );\r\n\tm_constrItemSID2ENUM.insert( \"Lights\", CI_LIGHT );\r\n\tm_constrItemSID2ENUM.insert( \"Doors\", CI_DOOR );\r\n\tm_constrItemSID2ENUM.insert( \"AlarmBell\", CI_ALARMBELL );\r\n\tm_constrItemSID2ENUM.insert( \"Farm\", CI_FARMUTIL );\r\n\tm_constrItemSID2ENUM.insert( \"Mechanism\", CI_MECHANISM );\r\n\tm_constrItemSID2ENUM.insert( \"Hydraulics\", CI_HYDRAULICS );\r\n}\r\n\r\nWorld::~World()\r\n{\r\n}\r\n\r\nvoid World::init()\r\n{\r\n\tqDebug() << \"World::init\";\r\n\r\n\tm_dimX = Global::dimX;\r\n\tm_dimY = Global::dimY;\r\n\tm_dimZ = Global::dimZ;\r\n\r\n\tm_lightMap.init();\r\n\tinitWater();\r\n\tinitGrassUpdateList();\r\n}\r\n\r\nvoid World::initWater()\r\n{\r\n\tm_water.clear();\r\n\r\n\tfor ( int z = m_dimZ - 2; z >= 0; --z )\r\n\t{\r\n\t\tfor ( int y = 0; y < m_dimY; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 0; x < m_dimX; ++x )\r\n\t\t\t{\r\n\t\t\t\tTile& here = getTile( x, y, z );\r\n\r\n\t\t\t\tif ( here.flags & TileFlag::TF_AQUIFIER )\r\n\t\t\t\t{\r\n\t\t\t\t\taddAquifier( Position( x, y, z ) );\r\n\t\t\t\t}\r\n\t\t\t\tif ( here.flags & TileFlag::TF_DEAQUIFIER )\r\n\t\t\t\t{\r\n\t\t\t\t\taddDeaquifier( Position( x, y, z ) );\r\n\t\t\t\t}\r\n\r\n\t\t\t\there.pressure = 0;\r\n\t\t\t\tif ( here.fluidLevel > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( (bool)( here.wallType & WT_SOLIDWALL ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\there.fluidLevel = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tPosition pos( x, y, z );\r\n\t\t\t\t\t\tm_water.insert( pos.toInt() );\r\n\r\n\t\t\t\t\t\tTile& above = getTile( pos.aboveOf() );\r\n\t\t\t\t\t\tif (\r\n\t\t\t\t\t\t\tabove.fluidLevel > 0 && here.fluidLevel == 10 && !(bool)( above.floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\there.pressure = above.pressure + 1;\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\r\nvoid World::afterLoad()\r\n{\r\n\tqDebug() << \"World::afterLoad\";\r\n\tm_dimX = Global::dimX;\r\n\tm_dimY = Global::dimY;\r\n\tm_dimZ = Global::dimZ;\r\n\r\n\tm_regionMap.initRegions();\r\n\tm_lightMap.init();\r\n\tinitGrassUpdateList();\r\n\tinitWater();\r\n}\r\n\r\nvoid World::setFloorSprite( unsigned short x, unsigned short y, unsigned short z, const unsigned int spriteUID )\r\n{\r\n\tgetTile( x, y, z ).floorSpriteUID = spriteUID;\r\n\taddToUpdateList( x, y, z );\r\n}\r\n\r\nvoid World::setFloorSprite( Position pos, unsigned int spriteUID )\r\n{\r\n\tgetTile( pos ).floorSpriteUID = spriteUID;\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::setWallSprite( unsigned short x, unsigned short y, unsigned short z, unsigned int spriteUID, unsigned char rotation )\r\n{\r\n\tunsigned int UID           = Position( x, y, z ).toInt();\r\n\tm_world[UID].wallSpriteUID = spriteUID;\r\n\tm_world[UID].wallRotation  = rotation;\r\n\taddToUpdateList( UID );\r\n}\r\n\r\nvoid World::setWallSprite( Position pos, unsigned int spriteUID, unsigned char rotation )\r\n{\r\n\tunsigned int UID           = pos.toInt();\r\n\tm_world[UID].wallSpriteUID = spriteUID;\r\n\tm_world[UID].wallRotation  = rotation;\r\n\taddToUpdateList( UID );\r\n}\r\n\r\nvoid World::setWallSprite( unsigned int tileID, unsigned int spriteUID )\r\n{\r\n\tm_world[tileID].wallSpriteUID = spriteUID;\r\n}\r\n\r\nvoid World::setItemSprite( unsigned short x, unsigned short y, unsigned short z, unsigned int spriteUID, unsigned char rotation )\r\n{\r\n\tunsigned int UID           = Position( x, y, z ).toInt();\r\n\tm_world[UID].itemSpriteUID = spriteUID;\r\n\t//m_world[UID].wallRotation = rotation;\r\n\taddToUpdateList( UID );\r\n}\r\n\r\nvoid World::setItemSprite( Position pos, unsigned int spriteUID, unsigned char rotation )\r\n{\r\n\tunsigned int UID           = pos.toInt();\r\n\tm_world[UID].itemSpriteUID = spriteUID;\r\n\t//m_world[UID].wallRotation = rotation;\r\n\taddToUpdateList( UID );\r\n}\r\n\r\nvoid World::setFloorSprite( unsigned int tileID, unsigned int spriteUID )\r\n{\r\n\tm_world[tileID].wallSpriteUID = spriteUID;\r\n\taddToUpdateList( tileID );\r\n}\r\n\r\nvoid World::setJobSprite( unsigned int tileID, unsigned int spriteUID, unsigned char rotation, bool floor, unsigned int jobID, bool busy )\r\n{\r\n\tPosition pos( tileID );\r\n\tsetJobSprite( pos, spriteUID, rotation, floor, jobID, busy );\r\n}\r\n\r\nvoid World::setJobSprite( Position pos, unsigned int spriteUID, unsigned char rotation, bool floor, unsigned int jobID, bool busy )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\tsetTileFlag( pos, floor ? TileFlag::TF_JOB_FLOOR : TileFlag::TF_JOB_WALL );\r\n\tif ( busy )\r\n\t{\r\n\t\tif ( floor )\r\n\t\t\tsetTileFlag( pos, TileFlag::TF_JOB_BUSY_FLOOR );\r\n\t\telse\r\n\t\t\tsetTileFlag( pos, TileFlag::TF_JOB_BUSY_WALL );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( floor )\r\n\t\t\tclearTileFlag( pos, TileFlag::TF_JOB_BUSY_FLOOR );\r\n\t\telse\r\n\t\t\tclearTileFlag( pos, TileFlag::TF_JOB_BUSY_WALL );\r\n\t}\r\n\r\n\tQVariantMap s;\r\n\ts.insert( \"Pos\", pos.toString() );\r\n\ts.insert( \"Rot\", rotation );\r\n\ts.insert( \"JobID\", jobID );\r\n\ts.insert( \"SpriteUID\", spriteUID );\r\n\r\n\tif ( !m_jobSprites.contains( pos.toInt() ) )\r\n\t{\r\n\t\tQVariantMap entry;\r\n\t\tm_jobSprites.insert( pos.toInt(), entry );\r\n\t}\r\n\tif ( floor )\r\n\t{\r\n\t\tm_jobSprites[pos.toInt()].insert( \"Floor\", s );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_jobSprites[pos.toInt()].insert( \"Wall\", s );\r\n\t}\r\n\r\n\taddToUpdateList( pos.toInt() );\r\n}\r\n\r\nvoid World::clearJobSprite( Position pos, bool floor )\r\n{\r\n\tif ( m_jobSprites.contains( pos.toInt() ) )\r\n\t{\r\n\t\tif ( floor )\r\n\t\t{\r\n\t\t\tm_jobSprites[pos.toInt()].remove( \"Floor\" );\r\n\t\t\tclearTileFlag( pos, TileFlag::TF_JOB_FLOOR + TileFlag::TF_JOB_BUSY_FLOOR );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_jobSprites[pos.toInt()].remove( \"Wall\" );\r\n\t\t\tclearTileFlag( pos, TileFlag::TF_JOB_WALL + TileFlag::TF_JOB_BUSY_WALL );\r\n\t\t}\r\n\t}\r\n\tif ( m_jobSprites[pos.toInt()].isEmpty() )\r\n\t{\r\n\t\tm_jobSprites.remove( pos.toInt() );\r\n\t}\r\n\taddToUpdateList( pos.toInt() );\r\n}\r\n\r\nvoid World::setTileFlag( unsigned short x, unsigned short y, unsigned short z, TileFlag flag )\r\n{\r\n\tPosition pos( x, y, z );\r\n\tsetTileFlag( pos, flag );\r\n}\r\n\r\nvoid World::setTileFlag( Position pos, TileFlag flag )\r\n{\r\n\tunsigned int tid = pos.toInt();\r\n\tTile& tile       = getTile( tid );\r\n\ttile.flags += flag;\r\n\r\n\tif ( flag & TileFlag::TF_WALKABLE )\r\n\t{\r\n\t\tm_regionMap.updatePosition( pos );\r\n\t}\r\n\taddToUpdateList( pos.toInt() );\r\n}\r\n\r\nvoid World::clearTileFlag( Position pos, TileFlag flag )\r\n{\r\n\tunsigned int tid = pos.toInt();\r\n\tTile& tile       = getTile( tid );\r\n\ttile.flags -= flag;\r\n\r\n\tif ( flag & TileFlag::TF_WALKABLE )\r\n\t{\r\n\t\tm_regionMap.updatePosition( pos );\r\n\r\n\t\tg->fm()->removeTile( pos, true, true, false );\r\n\t\tg->spm()->removeTile( pos );\r\n\t\tg->rm()->removeTile( pos );\r\n\t}\r\n\taddToUpdateList( pos.toInt() );\r\n}\r\n\r\nvoid World::updateFenceSprite( Position pos )\r\n{\r\n\tQVariantMap constr;\r\n\tif ( m_wallConstructions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tconstr = m_wallConstructions.value( pos.toInt() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tQString suffix          = \"Rot\";\r\n\tQString constructionSID = constr.value( \"ConstructionID\" ).toString();\r\n\r\n\tif ( m_wallConstructions.contains( pos.northOf().toInt() ) )\r\n\t{\r\n\t\tQVariantMap nc = m_wallConstructions.value( pos.northOf().toInt() );\r\n\t\tif ( nc.value( \"ConstructionID\" ).toString() == constructionSID )\r\n\t\t{\r\n\t\t\tsuffix += \"N\";\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_wallConstructions.contains( pos.eastOf().toInt() ) )\r\n\t{\r\n\t\tQVariantMap nc = m_wallConstructions.value( pos.eastOf().toInt() );\r\n\t\tif ( nc.value( \"ConstructionID\" ).toString() == constructionSID )\r\n\t\t{\r\n\t\t\tsuffix += \"E\";\r\n\t\t}\r\n\t}\r\n\tif ( m_wallConstructions.contains( pos.southOf().toInt() ) )\r\n\t{\r\n\t\tQVariantMap nc = m_wallConstructions.value( pos.southOf().toInt() );\r\n\t\tif ( nc.value( \"ConstructionID\" ).toString() == constructionSID )\r\n\t\t{\r\n\t\t\tsuffix += \"S\";\r\n\t\t}\r\n\t}\r\n\tif ( m_wallConstructions.contains( pos.westOf().toInt() ) )\r\n\t{\r\n\t\tQVariantMap nc = m_wallConstructions.value( pos.westOf().toInt() );\r\n\t\tif ( nc.value( \"ConstructionID\" ).toString() == constructionSID )\r\n\t\t{\r\n\t\t\tsuffix += \"W\";\r\n\t\t}\r\n\t}\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", constructionSID );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tPosition offset;\r\n\t\toffset = Position( sp.value( \"Offset\" ).toString() );\r\n\t\tPosition constrPos( pos + offset );\r\n\t\tunsigned int tid       = constrPos.toInt();\r\n\t\tTile& tile             = getTile( tid );\r\n\t\tQString materialID     = DBH::materialSID( tile.wallMaterial );\r\n\t\tQString spriteSID      = sp.value( \"SpriteID\" ).toString() + suffix;\r\n\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, { materialID } )->uID;\r\n\r\n\t\ttile.wallSpriteUID = spriteUID;\r\n\t}\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::updatePipeSprite( Position pos )\r\n{\r\n\tQVariantMap constr;\r\n\tif ( m_wallConstructions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tconstr = m_wallConstructions.value( pos.toInt() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tQString suffix = \"Rot\";\r\n\r\n\tunsigned int itemUID = constr.value( \"Item\" ).toUInt();\r\n\tQString itemSID      = g->inv()->itemSID( itemUID );\r\n\r\n\tif ( itemSID.startsWith( \"Pump\" ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( getTileFlag( pos.northOf() ) & TileFlag::TF_PIPE )\r\n\t{\r\n\t\tsuffix += \"N\";\r\n\t}\r\n\tif ( getTileFlag( pos.eastOf() ) & TileFlag::TF_PIPE )\r\n\t{\r\n\t\tsuffix += \"E\";\r\n\t}\r\n\tif ( getTileFlag( pos.southOf() ) & TileFlag::TF_PIPE )\r\n\t{\r\n\t\tsuffix += \"S\";\r\n\t}\r\n\tif ( getTileFlag( pos.westOf() ) & TileFlag::TF_PIPE )\r\n\t{\r\n\t\tsuffix += \"W\";\r\n\t}\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", itemSID );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tPosition offset;\r\n\t\toffset = Position( sp.value( \"Offset\" ).toString() );\r\n\t\tPosition constrPos( pos + offset );\r\n\t\tunsigned int tid       = constrPos.toInt();\r\n\t\tTile& tile             = getTile( tid );\r\n\t\tQString materialID     = DBH::materialSID( tile.wallMaterial );\r\n\t\tQString spriteSID      = sp.value( \"SpriteID\" ).toString() + suffix;\r\n\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, { materialID } )->uID;\r\n\r\n\t\ttile.wallSpriteUID = spriteUID;\r\n\t}\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::addLoadedSprites( QVariantMap vals )\r\n{\r\n\tTile& tile = getTile( Position( vals.value( \"Pos\" ) ) );\r\n\r\n\tif ( vals.value( \"IsFloor\" ).toBool() )\r\n\t{\r\n\t\ttile.floorSpriteUID = vals.value( \"UID\" ).toUInt();\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttile.wallSpriteUID = vals.value( \"UID\" ).toUInt();\r\n\t}\r\n\t//Util::string2Tile( tile, vals.value( \"OldTileVals\" ).toString() );\r\n}\r\n\r\nvoid World::expelTileItems( Position pos, Position& to )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\t//do we even have to move anything?\r\n\tPositionEntry pe;\r\n\tif ( g->inv()->getObjectsAtPosition( pos, pe ) )\r\n\t{\r\n\t\t//check if tile is now blocked for items and creatures\r\n\t\tif ( tile.wallType & WallType::WT_MOVEBLOCKING || !isWalkable( pos ) )\r\n\t\t{\r\n\t\t\tfor ( auto i : pe )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->moveItemToPos( i, to );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid World::expelTileInhabitants( Position pos, Position& to )\r\n{\r\n\t//qDebug() << \"expel from \" << pos.toString();\r\n\tTile& tile = getTile( pos );\r\n\t// check if someone is on the tile\r\n\tif ( m_creaturePositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\t//check if tile is now blocked for items and creatures\r\n\t\tif ( (bool)( tile.wallType & WallType::WT_MOVEBLOCKING ) || !isWalkable( pos ) )\r\n\t\t{\r\n\t\t\tg->gm()->forceMoveGnomes( pos, to );\r\n\t\t\tg->cm()->forceMoveAnimals( pos, to );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid World::plantTree( Position pos, QString type, bool fullyGrown )\r\n{\r\n\tPlant plant_( pos, type, fullyGrown, g );\r\n\tm_plants.insert( pos.toInt(), plant_ );\r\n\r\n\tgetTile( pos ).wallSpriteUID = m_plants[pos.toInt()].getSprite()->uID;\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::plantMushroom( Position pos, QString type, bool fullyGrown )\r\n{\r\n\tPlant plant_( pos, type, fullyGrown, g );\r\n\tm_plants.insert( pos.toInt(), plant_ );\r\n\r\n\tTile& tile = getTile( pos );\r\n\tif( plant_.hasAlpha() )\r\n\t{\r\n\t\tsetTileFlag( pos, TileFlag::TF_TRANSPARENT );\r\n\t}\r\n\ttile.wallSpriteUID = m_plants[pos.toInt()].getSprite()->uID;\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::plant( Position pos, unsigned int baseItem )\r\n{\r\n\tQStringList plants = DB::ids( \"Plants\", \"Type\", \"Plant\" );\r\n\tfor ( auto plant : plants )\r\n\t{\r\n\t\tif ( DB::select( \"Material\", \"Plants\", plant ).toString() == g->inv()->materialSID( baseItem ) )\r\n\t\t{\r\n\t\t\tPlant plant_( pos, plant, false, g );\r\n\t\t\tm_plants.insert( pos.toInt(), plant_ );\r\n\t\t\tgetTile( pos ).wallSpriteUID = m_plants[pos.toInt()].getSprite()->uID;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid World::addPlant( Plant plant )\r\n{\r\n\tPosition pos = plant.getPos();\r\n\tm_plants.insert( pos.toInt(), plant );\r\n\t//getTile( pos ).wallSpriteUID = m_plants[pos.toInt()].getSprite();\r\n}\r\n\r\nvoid World::removePlant( Position pos )\r\n{\r\n\tif ( m_plants.contains( pos.toInt() ) )\r\n\t{\r\n\t\tgetTile( pos ).wallType      = WallType::WT_NOWALL;\r\n\t\tgetTile( pos ).wallSpriteUID = 0;\r\n\t\tm_plants.remove( pos.toInt() );\r\n\t\tgetTile( pos ).wallSpriteUID = 0;\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n}\r\n\r\nvoid World::removePlant( Plant plant )\r\n{\r\n\tm_plants.remove( plant.getPos().toInt() );\r\n}\r\n\r\nbool World::reduceOneGrowLevel( Position pos )\r\n{\r\n\tif ( m_plants.contains( pos.toInt() ) )\r\n\t{\r\n\t\tif ( m_plants[pos.toInt()].reduceOneGrowLevel() )\r\n\t\t{\r\n\t\t\tremovePlant( pos );\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid World::removeCreatureFromPosition( Position pos, unsigned int creatureID )\r\n{\r\n\tif ( m_creaturePositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tif ( m_creaturePositions[pos.toInt()].size() == 1 )\r\n\t\t{\r\n\t\t\tm_creaturePositions.remove( pos.toInt() );\r\n\t\t\tg->mcm()->updateCreaturesAtPos( pos, 0 );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tQList<unsigned int>& cl = m_creaturePositions[pos.toInt()];\r\n\t\t\tcl.removeAll( creatureID );\r\n\t\t\tg->mcm()->updateCreaturesAtPos( pos, m_creaturePositions[pos.toInt()].size() );\r\n\t\t}\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n}\r\n\r\nvoid World::insertCreatureAtPosition( Position pos, unsigned int creatureID )\r\n{\r\n\tif ( m_creaturePositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tm_creaturePositions[pos.toInt()].push_back( creatureID );\r\n\t\tg->mcm()->updateCreaturesAtPos( pos, m_creaturePositions[pos.toInt()].size() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tQList<unsigned int> cl( { creatureID } );\r\n\t\tm_creaturePositions.insert( pos.toInt(), cl );\r\n\t\tg->mcm()->updateCreaturesAtPos( pos, 1 );\r\n\t}\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::processGrass()\r\n{\r\n\tQList<Position> toRemove;\r\n\tunsigned short dirtUID = Global::dirtUID;\r\n\tfor ( auto pi : m_grassCandidatePositions )\r\n\t{\r\n\t\tif ( m_grass.contains( pi ) )\r\n\t\t{\r\n\t\t\ttoRemove.append( pi );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tPosition p( pi );\r\n\r\n\t\t\tif ( rand() % 300 > 298 )\r\n\t\t\t{\r\n\t\t\t\tTile& tile = getTile( p );\r\n\t\t\t\tif ( tile.floorMaterial == dirtUID && tile.floorType & FT_SOLIDFLOOR && tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( tile.wallType & WT_RAMP && tile.wallMaterial == dirtUID )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tsetTileFlag( p, TileFlag::TF_GRASS );\r\n\t\t\t\t\t\tcreateRamp( p );\r\n\t\t\t\t\t\taddToUpdateList( p );\r\n\r\n\t\t\t\t\t\tauto pa = p.aboveOf();\r\n\t\t\t\t\t\taddToUpdateList( pa );\r\n\r\n\t\t\t\t\t\tisGrassCandidate( pa.northOf() );\r\n\t\t\t\t\t\tisGrassCandidate( pa.eastOf() );\r\n\t\t\t\t\t\tisGrassCandidate( pa.southOf() );\r\n\t\t\t\t\t\tisGrassCandidate( pa.westOf() );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcreateGrass( p );\r\n\t\t\t\t\t\taddToUpdateList( p );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\ttoRemove.append( p );\r\n\r\n\t\t\t\tisGrassCandidate( p.northOf() );\r\n\t\t\t\tisGrassCandidate( p.eastOf() );\r\n\t\t\t\tisGrassCandidate( p.southOf() );\r\n\t\t\t\tisGrassCandidate( p.westOf() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor ( auto p : toRemove )\r\n\t{\r\n\t\tm_grassCandidatePositions.remove( p.toInt() );\r\n\t}\r\n}\r\n\r\nvoid World::initGrassUpdateList()\r\n{\r\n\tm_grass.clear();\r\n\tm_grassCandidatePositions.clear();\r\n\r\n\tfor ( int z = m_dimZ - 2; z >= 0; --z )\r\n\t{\r\n\t\tfor ( int y = 0; y < m_dimY; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 0; x < m_dimX; ++x )\r\n\t\t\t{\r\n\t\t\t\tTile& here = getTile( x, y, z );\r\n\t\t\t\tif ( (bool)( here.flags & TileFlag::TF_GRASS ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tPosition pos( x, y, z );\r\n\t\t\t\t\tm_grass.insert( pos );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( auto p : m_grass )\r\n\t{\r\n\t\tisGrassCandidate( p.northOf() );\r\n\t\tisGrassCandidate( p.eastOf() );\r\n\t\tisGrassCandidate( p.southOf() );\r\n\t\tisGrassCandidate( p.westOf() );\r\n\t}\r\n}\r\n\r\nvoid World::isGrassCandidate( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\r\n\tif ( ( tile.floorType & FT_SOLIDFLOOR ) && ( tile.floorMaterial == Global::dirtUID ) && ( ( tile.wallType == WT_NOWALL ) || ( tile.wallType == WT_RAMP ) ) && !m_grass.contains( pos.toInt() ) )\r\n\t{\r\n\t\tm_grassCandidatePositions.insert( pos.toInt() );\r\n\t}\r\n}\r\n\r\nvoid World::addGrassCandidate( Position pos )\r\n{\r\n\tisGrassCandidate( pos );\r\n}\r\n\r\nvoid World::removeGrass( Position pos )\r\n{\r\n\tclearTileFlag( pos, TileFlag::TF_GRASS );\r\n\r\n\tif ( m_grass.contains( pos.toInt() ) )\r\n\t{\r\n\t\tm_grass.remove( pos.toInt() );\r\n\r\n\t\tTile& tile           = getTile( pos );\r\n\t\ttile.vegetationLevel = 0;\r\n\t\tQString materialSID  = DBH::materialSID( tile.floorMaterial );\r\n\r\n\t\tif ( tile.floorType & FT_SOLIDFLOOR && materialSID == \"Dirt\" )\r\n\t\t{\r\n\t\t\t//if( Global::debugMode ) qDebug() << \"add grass candidate at \" << pos.toString();\r\n\t\t\ttile.floorSpriteUID = g->sf()->createSprite( \"RoughFloor\", { \"Dirt\" } )->uID;\r\n\t\t\tm_grassCandidatePositions.insert( pos.toInt() );\r\n\t\t}\r\n\t}\r\n\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::createGrass( Position pos )\r\n{\r\n\tauto tf = getTileFlag( pos );\r\n\tif ( tf & TileFlag::TF_TILLED )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tTile& tile          = getTile( pos );\r\n\ttile.floorSpriteUID = g->sf()->createSprite( \"GrassWithDetail\", { \"Grass\", \"None\" } )->uID;\r\n\r\n\tm_grass.insert( pos );\r\n\tsetTileFlag( pos, TileFlag::TF_GRASS );\r\n\ttile.vegetationLevel = 100;\r\n}\r\n\r\nvoid World::addWater( Position pos, unsigned char level )\r\n{\r\n\tif ( !m_water.count( pos.toInt() ) )\r\n\t{\r\n\t\tm_water.insert( pos.toInt() );\r\n\r\n\t\tTile& tile      = getTile( pos );\r\n\t\ttile.fluidLevel = level;\r\n\t\ttile.flags += TileFlag::TF_WATER;\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n}\r\n\r\nvoid World::changeFluidLevel( Position pos, int diff )\r\n{\r\n\tTile& tile         = getTile( pos );\r\n\tint effectiveLevel = tile.fluidLevel + tile.pressure + diff;\r\n\ttile.pressure      = qMax( 0, effectiveLevel - 10 );\r\n\ttile.fluidLevel    = qMin( 10, effectiveLevel );\r\n\tm_water.insert( pos.toInt() );\r\n\ttile.flags += TileFlag::TF_WATER;\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::addAquifier( Position pos )\r\n{\r\n\tm_aquifiers.append( pos );\r\n\tm_water.insert( pos.toInt() );\r\n\tTile& tile = getTile( pos );\r\n\ttile.flags += TileFlag::TF_WATER;\r\n\ttile.flags += TileFlag::TF_AQUIFIER;\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::addDeaquifier( Position pos )\r\n{\r\n\tm_deaquifiers.append( pos );\r\n\tTile& tile = getTile( pos );\r\n\ttile.flags += TileFlag::TF_DEAQUIFIER;\r\n}\r\n\r\nvoid World::processWater()\r\n{\r\n\t// Batch updates\r\n\tQVector<unsigned int> waterUpdates;\r\n\t// Expecting to see every tile again\r\n\twaterUpdates.reserve( m_aquifiers.size() + m_deaquifiers.size() );\r\n\r\n\t// Add / remove 1 water per tick and aquifier / deaquifier\r\n\tfor ( const auto& pos : m_aquifiers )\r\n\t{\r\n\t\tTile& tile = getTile( pos );\r\n\t\tif ( tile.pressure == 0 && tile.fluidLevel < 10)\r\n\t\t{\r\n\t\t\ttile.fluidLevel++;\r\n\t\t\ttile.flags += TileFlag::TF_WATER;\r\n\t\t\twaterUpdates.append( pos.toInt() );\r\n\t\t}\r\n\t\tm_water.insert( pos.toInt() );\r\n\t}\r\n\tfor ( const auto& pos : m_deaquifiers )\r\n\t{\r\n\t\tTile& tile = getTile( pos );\r\n\t\tif ( tile.fluidLevel > 0 )\r\n\t\t{\r\n\t\t\tif ( tile.pressure > 0 )\r\n\t\t\t{\r\n\t\t\t\ttile.pressure--;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttile.fluidLevel--;\r\n\t\t\t}\r\n\t\t\tif ( tile.fluidLevel == 0 )\r\n\t\t\t{\r\n\t\t\t\ttile.flow = WF_NOFLOW;\r\n\t\t\t\ttile.flags -= TileFlag::TF_WATER;\r\n\t\t\t\tm_water.erase( pos.toInt() );\r\n\t\t\t}\r\n\t\t\twaterUpdates.append( pos.toInt() );\r\n\t\t}\r\n\t}\r\n\r\n\t// Batch submit water tile updates\r\n\taddToUpdateList( waterUpdates );\r\n\twaterUpdates.clear();\r\n\r\n\tprocessWaterFlow();\r\n}\r\n\r\nstruct Neighbors\r\n{\r\n#ifdef _WIN32\r\n\t__forceinline Neighbors( unsigned int pos )\r\n#else\r\n\tinline Neighbors( unsigned int pos )\r\n#endif\r\n\t{\r\n\t\tconst unsigned int pitchY = Global::dimX;\r\n\t\tconst unsigned int pitchZ = pitchY * Global::dimY;\r\n\r\n\t\tconst unsigned int maxZ = pitchZ * ( Global::dimZ - 1 );\r\n\r\n\t\tconst auto plane = pos % pitchZ;\r\n\t\tconst auto row   = pos % pitchY;\r\n\r\n\t\tabove = pos < maxZ ? pos + pitchZ : 0;\r\n\t\tbelow = pos > pitchZ ? pos - pitchZ : 0;\r\n\t\tnorth = plane > pitchY * 2 ? pos - pitchY : 0;\r\n\t\tsouth = plane < pitchZ - 2 * pitchY ? pos + pitchY : 0;\r\n\t\teast  = row < pitchY - 2 ? pos + 1 : 0;\r\n\t\twest  = row > 1 ? pos - 1 : 0;\r\n\t}\r\n\tunsigned int above;\r\n\tunsigned int below;\r\n\tunsigned int north;\r\n\tunsigned int south;\r\n\tunsigned int east;\r\n\tunsigned int west;\r\n};\r\n\r\nvoid World::processWaterFlow()\r\n{\r\n\t// Batch newly tracked water tiles\r\n\tQSet<unsigned int> newWater;\r\n\tQSet<unsigned int> removedWater;\r\n\r\n\tQVector<unsigned int> drain;\r\n\tQVector<unsigned int> flood;\r\n\r\n\t// Random numbers are expensive, and rand() only delivers 15bit of entropy per call\r\n\tauto seedBase = rand() ^ rand() << 10 ^ rand() << 20;\r\n\tfor ( const auto& currentPos : m_water )\r\n\t{\r\n\t\tTile& here = getTile( currentPos );\r\n\r\n\t\tif ( (bool)( here.wallType & WallType::WT_MOVEBLOCKING ) )\r\n\t\t{\r\n\t\t\t// Bogus, this should not be in water list\r\n\t\t\there.flow       = WF_NOFLOW;\r\n\t\t\there.pressure   = 0;\r\n\t\t\there.fluidLevel = 0;\r\n\t\t\there.flags -= TileFlag::TF_WATER;\r\n\t\t}\r\n\r\n\t\tif ( here.fluidLevel > 0 )\r\n\t\t{\r\n\t\t\t// Just barely random enough not to be obvious\r\n\t\t\tconst auto seed = ( currentPos ^ currentPos << 16 ^ seedBase ) % 2147483647;\r\n\r\n\t\t\tif ( here.fluidLevel <= 2 && (bool)( here.floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t{\r\n\t\t\t\t// Low fluid level on solid floor never moves, only may evaporate\r\n\t\t\t\tif ( ( seed % 1000 ) == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\there.flow = WF_EVAP;\r\n\t\t\t\t\tdrain.append( currentPos );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\there.flow = WF_NOFLOW;\r\n\t\t\t\t}\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tconst Neighbors neighbors( currentPos );\r\n\r\n\t\t\tconst unsigned int candidates[7] = {\r\n\t\t\t\tneighbors.north,\r\n\t\t\t\tneighbors.south,\r\n\t\t\t\tneighbors.east,\r\n\t\t\t\tneighbors.west,\r\n\t\t\t\tcurrentPos,\r\n\t\t\t\tneighbors.above,\r\n\t\t\t\tneighbors.below,\r\n\t\t\t};\r\n\t\t\tconstexpr WaterFlow direction[7] = {\r\n\t\t\t\tWF_NORTH,\r\n\t\t\t\tWF_SOUTH,\r\n\t\t\t\tWF_EAST,\r\n\t\t\t\tWF_WEST,\r\n\t\t\t\tWF_NOFLOW,\r\n\t\t\t\tWF_UP,\r\n\t\t\t\tWF_DOWN\r\n\t\t\t};\r\n\t\t\tenum index : size_t\r\n\t\t\t{\r\n\t\t\t\tnorth = 0,\r\n\t\t\t\tsouth,\r\n\t\t\t\teast,\r\n\t\t\t\twest,\r\n\t\t\t\tcenter,\r\n\t\t\t\tup,\r\n\t\t\t\tdown\r\n\t\t\t};\r\n\r\n\t\t\t// Compute pressure for passable directions\r\n\t\t\tconstexpr int invalidPressure = INT_MAX;\r\n\t\t\tint pressure[7];\r\n\t\t\tfor ( size_t i = north; i <= center; i++ )\r\n\t\t\t{\r\n\t\t\t\tconst Tile& there = getTile( candidates[i] );\r\n\t\t\t\tif ( candidates[i] && !(bool)( there.wallType & WallType::WT_MOVEBLOCKING ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tpressure[i] = there.pressure + there.fluidLevel;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpressure[i] = invalidPressure;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t{\r\n\t\t\t\tconst Tile& there = getTile( candidates[up] );\r\n\t\t\t\tif ( candidates[up] && !(bool)( there.wallType & WallType::WT_MOVEBLOCKING ) && !(bool)( there.floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tpressure[up] = there.pressure + there.fluidLevel;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpressure[up] = invalidPressure;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t{\r\n\t\t\t\tconst Tile& there = getTile( candidates[down] );\r\n\t\t\t\tif ( candidates[down] && !(bool)( there.wallType & WallType::WT_MOVEBLOCKING ) && !(bool)( here.floorType & FloorType::FT_SOLIDFLOOR ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tpressure[down] = there.pressure + there.fluidLevel;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tpressure[down] = invalidPressure;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Flow down if no back-pressure\r\n\t\t\tif ( pressure[down] != invalidPressure && pressure[down] <= pressure[center] || pressure[down] < 10 )\r\n\t\t\t{\r\n\t\t\t\there.flow += WF_DOWN;\r\n\t\t\t\tdrain.append( currentPos );\r\n\t\t\t\tflood.append( neighbors.below );\r\n\t\t\t\tpressure[center]--;\r\n\t\t\t\tpressure[up]++;\r\n\t\t\t}\r\n\r\n\t\t\t// Decide whether to enter instable states this frame\r\n\t\t\t// In an unstable state, distribution can reverse right in the next frame\r\n\t\t\t// Still need to allow it occasionally to relax gradients\r\n\t\t\tconst int preventInstability = seed % 127 == 0 ? 0 : 1;\r\n\t\t\t{\r\n\t\t\t\tconst bool waterAbove = pressure[up] != invalidPressure && pressure[up] != 0;\r\n\t\t\t\tfor ( size_t i = 0; i < 4; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\t// First order of sampled directions is randomized ...\r\n\t\t\t\t\tconst size_t j = ( i + seed ) % 4;\r\n\t\t\t\t\t// Prevent flow to side if that would cause vacuum\r\n\t\t\t\t\tconst bool vacuum = waterAbove && pressure[center] == 10;\r\n\t\t\t\t\tif ( pressure[j] != invalidPressure && ( pressure[center] > pressure[j] + preventInstability ) && !vacuum )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdrain.append( currentPos );\r\n\t\t\t\t\t\tflood.append( candidates[j] );\r\n\t\t\t\t\t\there.flow += direction[j];\r\n\t\t\t\t\t\tpressure[center]--;\r\n\t\t\t\t\t\tpressure[j]++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Only if nothing else worked, flow upwards\r\n\t\t\tif ( pressure[up] != invalidPressure && ( pressure[center] > 10 ) && ( pressure[center] > pressure[up] + preventInstability + 1 ) )\r\n\t\t\t{\r\n\t\t\t\there.flow += WF_UP;\r\n\t\t\t\tdrain.append( currentPos );\r\n\t\t\t\tflood.append( neighbors.above );\r\n\t\t\t\tpressure[center]--;\r\n\t\t\t\tpressure[up]++;\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t// Collecting tiles which should no longer had been tracked\r\n\t\t\tremovedWater.insert( currentPos );\r\n\t\t}\r\n\t\there.flow = WF_NOFLOW;\r\n\t}\r\n\r\n\t// Batch updates\r\n\tQVector<unsigned int> waterUpdates;\r\n\t// Expecting to see every tile again\r\n\twaterUpdates.reserve( (int)m_water.size() );\r\n\r\n\t// Flood first\r\n\tfor ( const auto& pos : flood )\r\n\t{\r\n\t\tTile& here = getTile( pos );\r\n\t\tif ( here.fluidLevel == 0 )\r\n\t\t{\r\n\t\t\t// Track it, it's probably new\r\n\t\t\tnewWater.insert( pos );\r\n\t\t\there.flags += TileFlag::TF_WATER;\r\n\t\t}\r\n\t\tif ( here.fluidLevel < 10 )\r\n\t\t{\r\n\t\t\t++here.fluidLevel;\r\n\t\t\twaterUpdates.append( pos );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t++here.pressure;\r\n\t\t}\r\n\t}\r\n\r\n\t// Then apply drain\r\n\tfor ( const auto& pos : drain )\r\n\t{\r\n\t\tTile& here = getTile( pos );\r\n\t\tif ( here.pressure > 0 )\r\n\t\t{\r\n\t\t\t--here.pressure;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t--here.fluidLevel;\r\n\t\t\twaterUpdates.append( pos );\r\n\t\t}\r\n\t\tif ( here.fluidLevel == 0 )\r\n\t\t{\r\n\t\t\there.flow = WF_NOFLOW;\r\n\t\t\there.flags -= TileFlag::TF_WATER;\r\n\t\t\tremovedWater.insert( pos );\r\n\t\t}\r\n\t}\r\n\r\n\t// Batch submit water tile updates\r\n\taddToUpdateList( waterUpdates );\r\n\twaterUpdates.clear();\r\n\r\n\t// Append tracked new water tiles\r\n\tfor ( const auto& newPos : newWater )\r\n\t{\r\n\t\tm_water.insert( newPos );\r\n\t}\r\n\r\n\t// Remove empty tiles\r\n\tfor ( const auto& oldPos : removedWater )\r\n\t{\r\n\t\tauto it = m_water.find( oldPos );\r\n\t\tm_water.erase( it );\r\n\t}\r\n}\r\n\r\nvoid World::removeDesignation( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\tif ( tile.flags & TileFlag::TF_STOCKPILE )\r\n\t{\r\n\t\tg->spm()->removeTile( pos );\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n\telse if ( tile.flags & ( TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE ) )\r\n\t{\r\n\t\tg->fm()->removeTile( pos, true, true, true );\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n\telse if ( tile.flags & TileFlag::TF_ROOM )\r\n\t{\r\n\t\tg->rm()->removeTile( pos );\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n\telse if ( tile.flags & TileFlag::TF_NOPASS )\r\n\t{\r\n\t\tclearTileFlag( pos, TileFlag::TF_NOPASS );\r\n\t\tm_regionMap.updatePosition( pos );\r\n\t\taddToUpdateList( pos );\r\n\t}\r\n}\r\n\r\nQPair<unsigned short, unsigned short> World::mineWall( Position pos, Position& workPosition )\r\n{\r\n\tTile& tile                 = getTile( pos );\r\n\tunsigned short materialInt = tile.wallMaterial;\r\n\tunsigned short embeddedInt = tile.embeddedMaterial;\r\n\r\n\tif ( tile.wallType == WallType::WT_RAMP )\r\n\t{\r\n\t\tTile& tileAbove          = getTile( pos.aboveOf() );\r\n\t\ttileAbove.floorType      = FloorType::FT_NOFLOOR;\r\n\t\ttileAbove.floorMaterial  = 0;\r\n\t\ttileAbove.floorSpriteUID = 0;\r\n\t\tclearTileFlag( Position( pos.aboveOf() ), TileFlag::TF_WALKABLE );\r\n\t\tremoveGrass( pos );\r\n\r\n\t\tif ( m_creaturePositions.contains(  pos.aboveOf().toInt() ) )\r\n\t\t{\r\n\t\t\tg->gm()->forceMoveGnomes( pos.aboveOf(), pos );\r\n\t\t}\r\n\t\tg->inv()->gravity( pos.aboveOf() );\r\n\t}\r\n\r\n\ttile.wallType         = WallType::WT_NOWALL;\r\n\ttile.wallMaterial     = 0;\r\n\ttile.embeddedMaterial = 0;\r\n\ttile.wallSpriteUID    = 0;\r\n\ttile.itemSpriteUID    = 0;\r\n\ttile.flags += TileFlag::TF_WALKABLE;\r\n\r\n\tm_regionMap.updatePosition( pos );\r\n\tupdateLightsInRange( pos );\r\n\r\n\tupdateRampAtPos( pos.northOf() );\r\n\tupdateRampAtPos( pos.eastOf() );\r\n\tupdateRampAtPos( pos.southOf() );\r\n\tupdateRampAtPos( pos.westOf() );\r\n\r\n\tdiscover( pos );\r\n\r\n\tQString ncd = QString::number( pos.toInt() );\r\n\tncd += \";\";\r\n\tncd += Global::util->tile2String( tile );\r\n\r\n\treturn { materialInt, embeddedInt };\r\n}\r\n\r\nQPair<unsigned short, unsigned short> World::removeWall( Position pos, Position& workPosition )\r\n{\r\n\tTile& tile                 = getTile( pos );\r\n\tunsigned short materialInt = tile.wallMaterial;\r\n\tunsigned short embeddedInt = tile.embeddedMaterial;\r\n\r\n\tif ( tile.wallType == WallType::WT_RAMP )\r\n\t{\r\n\t\tTile& tileAbove          = getTile( pos.aboveOf() );\r\n\t\ttileAbove.floorType      = FloorType::FT_NOFLOOR;\r\n\t\ttileAbove.floorMaterial  = 0;\r\n\t\ttileAbove.floorSpriteUID = 0;\r\n\t\tclearTileFlag( Position( pos.aboveOf() ), TileFlag::TF_WALKABLE );\r\n\t\tremoveGrass( pos );\r\n\t}\r\n\r\n\ttile.wallType         = WallType::WT_NOWALL;\r\n\ttile.wallMaterial     = 0;\r\n\ttile.embeddedMaterial = 0;\r\n\ttile.wallSpriteUID    = 0;\r\n\ttile.itemSpriteUID    = 0;\r\n\ttile.flags += TileFlag::TF_WALKABLE;\r\n\r\n\tm_regionMap.updatePosition( pos );\r\n\tupdateLightsInRange( pos );\r\n\r\n\tdiscover( pos );\r\n\r\n\tQString ncd = QString::number( pos.toInt() );\r\n\tncd += \";\";\r\n\tncd += Global::util->tile2String( tile );\r\n\r\n\treturn { materialInt, embeddedInt };\r\n}\r\n\r\nvoid World::discover( Position pos )\r\n{\r\n\tdiscover( pos.x, pos.y, pos.z );\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::discover( int x, int y, int z )\r\n{\r\n\tclearTileFlag( Position( x - 1, y - 1, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x - 1, y, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x - 1, y + 1, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x, y - 1, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x, y, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x, y + 1, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x + 1, y - 1, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x + 1, y, z ), TileFlag::TF_UNDISCOVERED );\r\n\tclearTileFlag( Position( x + 1, y + 1, z ), TileFlag::TF_UNDISCOVERED );\r\n}\r\n\r\nunsigned short World::removeRamp( Position pos, Position workPosition )\r\n{\r\n\tTile& tile      = getTile( pos );\r\n\tTile& tileAbove = getTile( pos.aboveOf() );\r\n\r\n\tunsigned short materialInt = tile.wallMaterial;\r\n\t// delete current ramp\r\n\ttileAbove.floorType      = FloorType::FT_NOFLOOR;\r\n\ttileAbove.floorMaterial  = 0;\r\n\ttileAbove.floorSpriteUID = 0;\r\n\r\n\ttile.wallType      = WallType::WT_NOWALL;\r\n\ttile.wallMaterial  = 0;\r\n\ttile.wallSpriteUID = 0;\r\n\r\n\tupdateLightsInRange( pos );\r\n\r\n\tremoveGrass( pos );\r\n\r\n\treturn materialInt;\r\n}\r\n\r\nvoid World::updateRampAtPos( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\tif ( !( tile.wallType & WallType::WT_RAMP ) )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t//\tqDebug() << \"ramp at \" << pos.toString();\r\n\tTile& tileBelow = getTile( pos.belowOf() );\r\n\tTile& tileAbove = getTile( pos.aboveOf() );\r\n\r\n\tbool north = getTile( pos.northOf() ).wallType & WallType::WT_ROUGH;\r\n\tbool south = getTile( pos.southOf() ).wallType & WallType::WT_ROUGH;\r\n\tbool east  = getTile( pos.eastOf() ).wallType & WallType::WT_ROUGH;\r\n\tbool west  = getTile( pos.westOf() ).wallType & WallType::WT_ROUGH;\r\n\r\n\tint sum = (int)north + (int)south + (int)east + (int)west;\r\n\tif ( sum > 2 || sum == 0 )\r\n\t{\r\n\t\t// delete current ramp\r\n\t\ttileAbove.floorType      = FloorType::FT_NOFLOOR;\r\n\t\ttileAbove.floorMaterial  = 0;\r\n\t\ttileAbove.floorSpriteUID = 0;\r\n\r\n\t\ttile.wallType      = WallType::WT_NOWALL;\r\n\t\ttile.wallMaterial  = 0;\r\n\t\ttile.wallSpriteUID = 0;\r\n\r\n\t\tupdateWalkable( pos );\r\n\t\tupdateWalkable( pos.aboveOf() );\r\n\r\n\t\tremoveGrass( pos );\r\n\r\n\t\treturn;\r\n\t}\r\n\r\n\tQString mat = DBH::materialSID( tile.wallMaterial );\r\n\r\n\ttileAbove.floorType = FloorType::FT_RAMPTOP;\r\n\r\n\ttile.wallType = WallType::WT_RAMP;\r\n\ttile.flags += TileFlag::TF_WALKABLE;\r\n\r\n\tsetRampSprites( tile, tileAbove, sum, north, east, south, west, mat );\r\n\r\n\tupdateWalkable( pos );\r\n\tupdateWalkable( pos.aboveOf() );\r\n}\r\n\r\nunsigned short World::removeFloor( Position pos, Position extractTo )\r\n{\r\n\tTile& tile              = getTile( pos );\r\n\ttile.floorType          = FloorType::FT_NOFLOOR;\r\n\ttile.floorSpriteUID     = 0;\r\n\tunsigned short floorMat = tile.floorMaterial;\r\n\ttile.floorMaterial      = 0;\r\n\tclearTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\tm_regionMap.updatePosition( pos );\r\n\tremoveGrass( pos );\r\n\tremovePlant( pos );\r\n\t//g->inv()->gravity( pos );\r\n\r\n\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t{\r\n\t\tupdateSunlight( pos );\r\n\t}\r\n\r\n\tPositionEntry pe;\r\n\tif ( g->inv()->getObjectsAtPosition( pos, pe ) )\r\n\t{\r\n\t\tfor ( auto i : pe )\r\n\t\t{\r\n\t\t\tg->inv()->moveItemToPos( i, extractTo );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( m_creaturePositions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tg->gm()->forceMoveGnomes( pos, extractTo );\r\n\t}\r\n\t\r\n\tdiscover( pos.belowOf() );\r\n\r\n\taddToUpdateList( pos );\r\n\r\n\treturn floorMat;\r\n}\r\n\r\nvoid World::createRamp( int x, int y, int z, TerrainMaterial mat )\r\n{\r\n\tint offset        = z * m_dimX * m_dimY;\r\n\tTile& tileBelow   = m_world[x + y * m_dimX + ( z - 1 ) * m_dimX * m_dimY];\r\n\tTile& tileAbove   = m_world[x + y * m_dimX + ( z + 1 ) * m_dimX * m_dimY];\r\n\tTile& tile        = m_world[x + y * m_dimX + offset];\r\n\r\n\tif ( tileAbove.floorType == FloorType::FT_SOLIDFLOOR )\r\n\t\treturn;\r\n\tif ( tileBelow.wallType == WallType::WT_NOWALL )\r\n\t\treturn;\r\n\tif ( tile.wallType != WallType::WT_NOWALL )\r\n\t\treturn;\r\n\r\n\tunsigned short key = DBH::materialUID( mat.key );\r\n\r\n\tif ( ( tileBelow.wallType & WallType::WT_ROUGH ) && ( tile.wallType == WallType::WT_NOWALL ) && ( tile.floorType == FloorType::FT_NOFLOOR ) )\r\n\t{\r\n\t\ttile.floorType      = FloorType::FT_SOLIDFLOOR;\r\n\t\ttile.floorMaterial  = key;\r\n\t\ttile.floorSpriteUID = g->sf()->createSprite( mat.floor, { mat.key } )->uID;\r\n\t}\r\n\r\n\tbool north = m_world[x + ( y - 1 ) * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\tbool south = m_world[x + ( y + 1 ) * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\tbool east  = m_world[( x + 1 ) + y * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\tbool west  = m_world[( x - 1 ) + y * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\r\n\tint sum = (int)north + (int)south + (int)east + (int)west;\r\n\tif ( sum > 2 || sum == 0 )\r\n\t\treturn;\r\n\r\n\ttile.wallType     = ( WallType )( WallType::WT_RAMP );\r\n\ttile.wallMaterial = key;\r\n\ttile.flags += TileFlag::TF_WALKABLE;\r\n\tm_regionMap.updatePosition( Position( x, y, z ) );\r\n\r\n\ttileAbove.floorType     = FloorType::FT_RAMPTOP;\r\n\ttileAbove.floorMaterial = key;\r\n\r\n\tsetRampSprites( tile, tileAbove, sum, north, east, south, west, mat.key );\r\n}\r\n\r\nvoid World::createRamp( Position pos )\r\n{\r\n\tcreateRamp( pos.x, pos.y, pos.z );\r\n}\r\n\r\nvoid World::createRamp( int x, int y, int z )\r\n{\r\n\tint offset      = z * m_dimX * m_dimY;\r\n\tTile& tileBelow = m_world[x + y * m_dimX + ( z - 1 ) * m_dimX * m_dimY];\r\n\tTile& tileAbove = m_world[x + y * m_dimX + ( z + 1 ) * m_dimX * m_dimY];\r\n\tTile& tile      = m_world[x + y * m_dimX + offset];\r\n\tif ( tileAbove.floorType == FloorType::FT_SOLIDFLOOR )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tif ( tileBelow.wallType == WallType::WT_NOWALL )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tif ( tile.floorType != FloorType::FT_SOLIDFLOOR )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\t//if( tile.wallType != WallType::WT_NOWALL ) return;\r\n\tif ( ( tileBelow.wallType & WallType::WT_ROUGH ) && ( tile.wallType == WallType::WT_NOWALL ) && ( tile.floorType == FloorType::FT_NOFLOOR ) )\r\n\t{\r\n\t\ttile.floorType      = FloorType::FT_SOLIDFLOOR;\r\n\t\ttile.floorMaterial  = tileBelow.wallMaterial;\r\n\t\ttile.floorSpriteUID = g->sf()->createSprite( DB::select( \"FloorSprite\", \"TerrainMaterials\", DBH::materialSID( tileBelow.wallMaterial ) ).toString(), { DBH::materialSID( tileBelow.wallMaterial ) } )->uID;\r\n\t}\r\n\r\n\tbool north = m_world[x + ( y - 1 ) * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\tbool south = m_world[x + ( y + 1 ) * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\tbool east  = m_world[( x + 1 ) + y * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\tbool west  = m_world[( x - 1 ) + y * m_dimX + offset].wallType & WallType::WT_ROUGH;\r\n\r\n\tint sum = (int)north + (int)south + (int)east + (int)west;\r\n\r\n\tif ( sum > 2 || sum == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tunsigned int key  = 0;\r\n\tunsigned int nMat = m_world[x + ( y - 1 ) * m_dimX + offset].wallMaterial;\r\n\tunsigned int sMat = m_world[x + ( y + 1 ) * m_dimX + offset].wallMaterial;\r\n\tunsigned int eMat = m_world[( x + 1 ) + y * m_dimX + offset].wallMaterial;\r\n\tunsigned int wMat = m_world[( x - 1 ) + y * m_dimX + offset].wallMaterial;\r\n\r\n\tif ( sum == 1 )\r\n\t{\r\n\t\tkey = nMat | sMat | eMat | wMat;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( north )\r\n\t\t{\r\n\t\t\tif ( nMat == sMat || nMat == eMat || nMat == wMat )\r\n\t\t\t\tkey = nMat;\r\n\t\t}\r\n\t\tif ( south )\r\n\t\t{\r\n\t\t\tif ( sMat == eMat || sMat == wMat )\r\n\t\t\t\tkey = sMat;\r\n\t\t}\r\n\t\tif ( east )\r\n\t\t{\r\n\t\t\tif ( eMat == wMat )\r\n\t\t\t\tkey = eMat;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( key == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tkey            = tile.floorMaterial;\r\n\tQString matSID = DBH::materialSID( key );\r\n\r\n\ttile.wallType     = ( WallType )( WallType::WT_RAMP );\r\n\ttile.wallMaterial = key;\r\n\ttile.flags += TileFlag::TF_WALKABLE;\r\n\tm_regionMap.updatePosition( Position( x, y, z ) );\r\n\r\n\ttileAbove.floorType     = FloorType::FT_RAMPTOP;\r\n\ttileAbove.floorMaterial = key;\r\n\t\r\n\tsetRampSprites( tile, tileAbove, sum, north, east, south, west, matSID );\r\n}\r\n\r\nvoid World::createRamp( Position pos, QString materialSID )\r\n{\r\n\tcreateRamp( pos.x, pos.y, pos.z, materialSID );\r\n}\r\n\r\nvoid World::createRamp( int x, int y, int z, QString materialSID )\r\n{\r\n\tint offset      = z * m_dimX * m_dimY;\r\n\tTile& tileBelow = m_world[x + y * m_dimX + ( z - 1 ) * m_dimX * m_dimY];\r\n\tTile& tileAbove = m_world[x + y * m_dimX + ( z + 1 ) * m_dimX * m_dimY];\r\n\tTile& tile      = m_world[x + y * m_dimX + offset];\r\n\tif ( tileAbove.floorType == FloorType::FT_SOLIDFLOOR )\r\n\t\treturn;\r\n\t//if( tileBelow.wallType == WallType::WT_NOWALL ) return;\r\n\tif ( tile.floorType != FloorType::FT_SOLIDFLOOR )\r\n\t\treturn;\r\n\tif ( tile.wallType != WallType::WT_NOWALL )\r\n\t\treturn;\r\n\tif ( ( tileBelow.wallType & WallType::WT_ROUGH ) && ( tile.wallType == WallType::WT_NOWALL ) && ( tile.floorType == FloorType::FT_NOFLOOR ) )\r\n\t{\r\n\t\ttile.floorType      = FloorType::FT_SOLIDFLOOR;\r\n\t\ttile.floorMaterial  = tileBelow.wallMaterial;\r\n\t\ttile.floorSpriteUID = g->sf()->createSprite( DB::select( \"FloorSprite\", \"TerrainMaterials\", DBH::materialSID( tileBelow.wallMaterial ) ).toString(), { DBH::materialSID( tileBelow.wallMaterial ) } )->uID;\r\n\t}\r\n\r\n\tbool north = m_world[x + ( y - 1 ) * m_dimX + offset].wallType & WallType::WT_SOLIDWALL;\r\n\tbool south = m_world[x + ( y + 1 ) * m_dimX + offset].wallType & WallType::WT_SOLIDWALL;\r\n\tbool east  = m_world[( x + 1 ) + y * m_dimX + offset].wallType & WallType::WT_SOLIDWALL;\r\n\tbool west  = m_world[( x - 1 ) + y * m_dimX + offset].wallType & WallType::WT_SOLIDWALL;\r\n\r\n\tint sum = (int)north + (int)south + (int)east + (int)west;\r\n\r\n\tif ( sum > 2 || sum == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tunsigned int key = DBH::materialUID( materialSID );\r\n\r\n\ttile.wallType     = ( WallType )( WallType::WT_RAMP );\r\n\ttile.wallMaterial = key;\r\n\ttile.flags += TileFlag::TF_WALKABLE;\r\n\tremoveGrass( Position( x, y, z ) );\r\n\r\n\tm_regionMap.updatePosition( Position( x, y, z ) );\r\n\r\n\ttileAbove.floorType     = FloorType::FT_RAMPTOP;\r\n\ttileAbove.floorMaterial = key;\r\n\r\n\tsetRampSprites( tile, tileAbove, sum, north, east, south, west, materialSID );\r\n}\r\n\r\nvoid World::setRampSprites( Tile& tile, Tile& tileAbove, int sum, bool north, bool east, bool south, bool west, QString materialSID )\r\n{\r\n\tunsigned int ramp      = g->sf()->createSprite( \"Ramp\", { materialSID } )->uID;\r\n\tunsigned int top       = g->sf()->createSprite( \"RampTop\", { materialSID } )->uID;\r\n\tunsigned int corner    = g->sf()->createSprite( \"CornerRamp\", { materialSID } )->uID;\r\n\tunsigned int cornerTop = g->sf()->createSprite( \"CornerRampTop\", { materialSID } )->uID;\r\n\tunsigned int uRamp     = g->sf()->createSprite( \"URamp\", { materialSID } )->uID;\r\n\tunsigned int uRampTop  = g->sf()->createSprite( \"URampTop\", { materialSID } )->uID;\r\n\r\n\tif ( tile.flags & TileFlag::TF_GRASS )\r\n\t{\r\n\t\ttile.floorSpriteUID = g->sf()->createSprite( \"RoughFloor\", { \"Dirt\" } )->uID;\r\n\t\tramp                = g->sf()->createSprite( \"GrassSoilRamp\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\ttop                 = g->sf()->createSprite( \"GrassSoilRampTop\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tcorner              = g->sf()->createSprite( \"GrassSoilCornerRamp\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tcornerTop           = g->sf()->createSprite( \"GrassSoilCornerRampTop\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tuRamp               = g->sf()->createSprite( \"GrassSoilURamp\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tuRampTop            = g->sf()->createSprite( \"GrassSoilURampTop\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t{\r\n\t\t\ttileAbove.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( tile.flags & TileFlag::TF_BIOME_MUSHROOM )\r\n\t{\r\n\t\t//floorSpriteUID = g->sf()->createSprite( \"RoughFloor\", { \"Dirt\" } )->uID;\r\n\t\tramp      = g->sf()->createSprite( \"MushroomGrassSoilRamp\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\ttop       = g->sf()->createSprite( \"MushroomGrassSoilRampTop\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tcorner    = g->sf()->createSprite( \"MushroomGrassSoilCornerRamp\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tcornerTop = g->sf()->createSprite( \"MushroomGrassSoilCornerRampTop\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tuRamp     = g->sf()->createSprite( \"MushroomGrassSoilURamp\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t\tuRampTop  = g->sf()->createSprite( \"MushroomGrassSoilURampTop\", { \"Dirt\", \"Grass\" } )->uID;\r\n\t}\r\n\r\n\tif ( sum == 1 )\r\n\t{\r\n\t\tif ( north )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = ramp;\r\n\t\t\ttileAbove.floorSpriteUID = top;\r\n\t\t\ttile.wallRotation        = 1;\r\n\t\t\ttileAbove.floorRotation  = 1;\r\n\t\t}\r\n\t\telse if ( west )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = ramp;\r\n\t\t\ttileAbove.floorSpriteUID = top;\r\n\t\t\ttile.wallRotation        = 0;\r\n\t\t\ttileAbove.floorRotation  = 0;\r\n\t\t}\r\n\t\telse if ( east )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = ramp;\r\n\t\t\ttileAbove.floorSpriteUID = top;\r\n\t\t\ttile.wallRotation        = 2;\r\n\t\t\ttileAbove.floorRotation  = 2;\r\n\t\t}\r\n\t\telse // south\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = ramp;\r\n\t\t\ttileAbove.floorSpriteUID = top;\r\n\t\t\ttile.wallRotation        = 3;\r\n\t\t\ttileAbove.floorRotation  = 3;\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( north && west )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = corner;\r\n\t\t\ttileAbove.floorSpriteUID = cornerTop;\r\n\t\t\ttile.wallRotation        = 0;\r\n\t\t\ttileAbove.floorRotation  = 0;\r\n\t\t}\r\n\t\telse if ( north && east )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = corner;\r\n\t\t\ttileAbove.floorSpriteUID = cornerTop;\r\n\t\t\ttile.wallRotation        = 1;\r\n\t\t\ttileAbove.floorRotation  = 1;\r\n\t\t}\r\n\t\telse if ( south && west )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = corner;\r\n\t\t\ttileAbove.floorSpriteUID = cornerTop;\r\n\t\t\ttile.wallRotation        = 3;\r\n\t\t\ttileAbove.floorRotation  = 3;\r\n\t\t}\r\n\t\telse if ( south && east )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = corner;\r\n\t\t\ttileAbove.floorSpriteUID = cornerTop;\r\n\t\t\ttile.wallRotation        = 2;\r\n\t\t\ttileAbove.floorRotation  = 2;\r\n\t\t}\r\n\t\telse if ( north && south )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = uRamp;\r\n\t\t\ttileAbove.floorSpriteUID = uRampTop;\r\n\t\t\ttile.wallRotation        = 0;\r\n\t\t\ttileAbove.floorRotation  = 0;\r\n\t\t}\r\n\t\telse if ( west && east )\r\n\t\t{\r\n\t\t\ttile.wallSpriteUID       = uRamp;\r\n\t\t\ttileAbove.floorSpriteUID = uRampTop;\r\n\t\t\ttile.wallRotation        = 1;\r\n\t\t\ttileAbove.floorRotation  = 1;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid World::createRampOuterCorners( int x, int y, int z )\r\n{\r\n\tint offset = z * m_dimX * m_dimY;\r\n\tTile& tile = m_world[x + y * m_dimX + offset];\r\n\r\n\tif ( tile.wallType != WallType::WT_NOWALL )\r\n\t\treturn;\r\n\r\n\tbool north = m_world[x + ( y - 1 ) * m_dimX + offset].wallType & WallType::WT_RAMP;\r\n\tbool south = m_world[x + ( y + 1 ) * m_dimX + offset].wallType & WallType::WT_RAMP;\r\n\tbool east  = m_world[( x + 1 ) + y * m_dimX + offset].wallType & WallType::WT_RAMP;\r\n\tbool west  = m_world[( x - 1 ) + y * m_dimX + offset].wallType & WallType::WT_RAMP;\r\n\r\n\tint sum = (int)north + (int)south + (int)east + (int)west;\r\n\r\n\tif ( sum > 2 || sum == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tunsigned int key = tile.floorMaterial;\r\n\r\n\tQString matSID = DBH::materialSID( key );\r\n\r\n\tunsigned int corner = g->sf()->createSprite( \"OuterCornerRamp\", { matSID } )->uID;\r\n\r\n\tif ( tile.flags & TileFlag::TF_GRASS )\r\n\t{\r\n\t\tmatSID = \"Grass\";\r\n\t\tcorner = g->sf()->createSprite( \"GrassOuterCornerRamp\", { matSID } )->uID;\r\n\t}\r\n\r\n\ttile.wallType     = ( WallType )( WallType::WT_RAMPCORNER );\r\n\ttile.wallMaterial = tile.floorMaterial;\r\n\r\n\tif ( north && west )\r\n\t{\r\n\t\ttile.wallSpriteUID = corner;\r\n\t\ttile.wallRotation  = 0;\r\n\t}\r\n\tif ( north && east )\r\n\t{\r\n\t\ttile.wallSpriteUID = corner;\r\n\r\n\t\ttile.wallRotation = 1;\r\n\t}\r\n\tif ( south && west )\r\n\t{\r\n\t\ttile.wallSpriteUID = corner;\r\n\t\ttile.wallRotation  = 3;\r\n\t}\r\n\tif ( south && east )\r\n\t{\r\n\t\ttile.wallSpriteUID = corner;\r\n\t\ttile.wallRotation  = 2;\r\n\t}\r\n}\r\n\r\nvoid World::addToUpdateList( const unsigned int uID )\r\n{\r\n\tQMutexLocker lock( &m_updateMutex );\r\n\tm_updatedTiles.insert( uID );\r\n}\r\n\r\nvoid World::addToUpdateList( Position pos )\r\n{\r\n\tauto tileID = pos.toInt();\r\n\r\n\tQMutexLocker lock( &m_updateMutex );\r\n\tm_updatedTiles.insert( tileID );\r\n}\r\n\r\nvoid World::addToUpdateList( const unsigned short x, const unsigned short y, const unsigned short z )\r\n{\r\n\tauto tileID = Position( x, y, z ).toInt();\r\n\r\n\tQMutexLocker lock( &m_updateMutex );\r\n\tm_updatedTiles.insert( tileID );\r\n}\r\n\r\nvoid World::addToUpdateList( const QVector<unsigned int>& ul )\r\n{\r\n\tQMutexLocker lock( &m_updateMutex );\r\n\tfor ( auto tileID : ul )\r\n\t{\r\n\t\tm_updatedTiles.insert( tileID );\r\n\t}\r\n}\r\n\r\nvoid World::addToUpdateList( const QSet<unsigned int>& ul )\r\n{\r\n\tQMutexLocker lock( &m_updateMutex );\r\n\tm_updatedTiles += ul;\r\n}\r\n\r\nvoid World::setDoorLocked( unsigned int tileUID, bool lockGnome, bool lockMonster, bool lockAnimal )\r\n{\r\n\tPosition pos( tileUID );\r\n\r\n\tif ( lockGnome )\r\n\t{\r\n\t\tclearTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\t}\r\n\tif ( lockMonster )\r\n\t{\r\n\t\tclearTileFlag( pos, TileFlag::TF_WALKABLEMONSTERS );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetTileFlag( pos, TileFlag::TF_WALKABLEMONSTERS );\r\n\t}\r\n\tif ( lockAnimal )\r\n\t{\r\n\t\tclearTileFlag( pos, TileFlag::TF_WALKABLEANIMALS );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetTileFlag( pos, TileFlag::TF_WALKABLEANIMALS );\r\n\t}\r\n\tm_regionMap.updateConnectedRegions( pos );\r\n}\r\n\r\nvoid World::putLight( Position pos, int light )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\ttile.lightLevel += light;\r\n\taddToUpdateList( pos );\r\n}\r\n\r\nvoid World::putLight( const unsigned short x, const unsigned short y, const unsigned short z, int light )\r\n{\r\n\tTile& tile = getTile( x, y, z );\r\n\ttile.lightLevel += light;\r\n\taddToUpdateList( x, y, z );\r\n}\r\n\r\nvoid World::addLight( unsigned int id, Position pos, int intensity )\r\n{\r\n\tQSet<unsigned int> ul;\r\n\tm_lightMap.addLight( ul, m_world, id, pos, intensity );\r\n\taddToUpdateList( ul );\r\n}\r\n\r\nvoid World::removeLight( unsigned int id )\r\n{\r\n\tQSet<unsigned int> ul;\r\n\tm_lightMap.removeLight( ul, m_world, id );\r\n\taddToUpdateList( ul );\r\n}\r\n\r\nvoid World::moveLight( unsigned int id, Position pos, int intensity )\r\n{\r\n\tQSet<unsigned int> ul;\r\n\tm_lightMap.removeLight( ul, m_world, id );\r\n\tm_lightMap.addLight( ul, m_world, id, pos, intensity );\r\n\taddToUpdateList( ul );\r\n}\r\n\r\nvoid World::updateLightsInRange( Position pos )\r\n{\r\n\tQSet<unsigned int> ul;\r\n\tm_lightMap.updateLight( ul, m_world, pos );\r\n\taddToUpdateList( ul );\r\n}\r\n\r\nvoid World::updateSunlight( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\ttile.flags += TileFlag::TF_SUNLIGHT;\r\n\taddToUpdateList( pos );\r\n\tif ( pos.z > 0 && tile.floorType == FT_NOFLOOR )\r\n\t{\r\n\t\tupdateSunlight( pos.belowOf() );\r\n\t}\r\n}\r\n\r\nbool World::hasSunlight( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.flags & TileFlag::TF_SUNLIGHT;\r\n}\r\n\r\nbool World::hasGrass( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.flags & TileFlag::TF_GRASS;\r\n}\r\n\r\nbool World::hasMaxGrass( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.flags & TileFlag::TF_GRASS && tile.flags & TileFlag::TF_WALKABLE && tile.vegetationLevel == 100; //TODO bad fix, making tiles not walkable should remove designations\r\n}\r\n\r\nbool World::checkTrapGnomeFloor( Position pos, Position workPos )\r\n{\r\n\t// TODO just realized this function is garbage, needs to be fixed\r\n\t// check other 3 neighbors of pos\r\n\tPosition checkPos = pos.northOf();\r\n\tif ( checkPos != workPos )\r\n\t{\r\n\t\t// checkPos only has one walkable neighbor which is the tile we want to remove\r\n\t\tif ( walkableNeighbors( checkPos ) == 1 )\r\n\t\t{\r\n\t\t\t// checkIf Gnome is on tile\r\n\t\t\tif ( isWalkable( pos.eastOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.westOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.southOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.northOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\tcheckPos = pos.eastOf();\r\n\tif ( checkPos != workPos )\r\n\t{\r\n\t\t// checkPos only has one walkable neighbor which is the tile we want to remove\r\n\t\tif ( walkableNeighbors( checkPos ) == 1 )\r\n\t\t{\r\n\t\t\t// checkIf Gnome is on tile\r\n\t\t\tif ( isWalkable( pos.eastOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.westOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.southOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.northOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\tcheckPos = pos.southOf();\r\n\tif ( checkPos != workPos )\r\n\t{\r\n\t\t// checkPos only has one walkable neighbor which is the tile we want to remove\r\n\t\tif ( walkableNeighbors( checkPos ) == 1 )\r\n\t\t{\r\n\t\t\t// checkIf Gnome is on tile\r\n\t\t\tif ( isWalkable( pos.eastOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.westOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.southOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.northOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\tcheckPos = pos.westOf();\r\n\tif ( checkPos != workPos )\r\n\t{\r\n\t\t// checkPos only has one walkable neighbor which is the tile we want to remove\r\n\t\tif ( walkableNeighbors( checkPos ) == 1 )\r\n\t\t{\r\n\t\t\t// checkIf Gnome is on tile\r\n\t\t\tif ( isWalkable( pos.eastOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.westOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.southOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t\tif ( isWalkable( pos.northOf() ) && g->gm()->gnomesAtPosition( pos.eastOf() ).size() > 0 )\r\n\t\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nvoid World::setWallSpriteAnim( Position pos, bool anim )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\tif ( anim )\r\n\t{\r\n\t\ttile.wallSpriteUID |= 0x00040000;\r\n\t}\r\n\telse\r\n\t{\r\n\t\ttile.wallSpriteUID &= 0xFFFBFFFF;\r\n\t}\r\n\taddToUpdateList( pos );\r\n}\r\n"
  },
  {
    "path": "src/game/world.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef WORLD_H_\r\n#define WORLD_H_\r\n\r\n#include \"../base/enums.h\"\r\n#include \"../base/lightmap.h\"\r\n#include \"../base/regionmap.h\"\r\n#include \"../base/tile.h\"\r\n\r\n#include <QMutex>\r\n#include <QPixmap>\r\n#include <QSet>\r\n\r\n#include <set>\r\n#include <vector>\r\n\r\nclass Plant;\r\nclass Animal;\r\nclass Creature;\r\nclass Game;\r\n\r\nstruct Position;\r\nclass Sprite;\r\n\r\nenum CONSTRUCTION_ID\r\n{\r\n\tCID_WALL = 1,\r\n\tCID_FANCYWALL,\r\n\tCID_FENCE,\r\n\tCID_FLOOR,\r\n\tCID_FANCYFLOOR,\r\n\tCID_WALLFLOOR,\r\n\tCID_STAIRS,\r\n\tCID_RAMP,\r\n\tCID_RAMPCORNER,\r\n\tCID_ITEM,\r\n\tCID_WORKSHOP\r\n};\r\n\r\nenum CONSTR_ITEM_ID\r\n{\r\n\tCI_STORAGE = 1,\r\n\tCI_FURNITURE,\r\n\tCI_LIGHT,\r\n\tCI_LIGHTSHROOM,\r\n\tCI_DOOR,\r\n\tCI_ALARMBELL,\r\n\tCI_FARMUTIL,\r\n\tCI_MECHANISM,\r\n\tCI_UTILITY,\r\n\tCI_HYDRAULICS\r\n};\r\n\r\nclass World\r\n{\r\n\tQ_DISABLE_COPY_MOVE( World )\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tLightMap m_lightMap;\r\n\tRegionMap m_regionMap;\r\n\r\n\tQMutex m_updateMutex;\r\n\r\n\tint m_dimX = 1;\r\n\tint m_dimY = 1;\r\n\tint m_dimZ = 1;\r\n\r\n\tbool m_grassChanged = false;\r\n\r\n\tstd::vector<Tile> m_world;\r\n\r\n\tQMap<unsigned int, Plant> m_plants;\r\n\tQMap<unsigned int, QList<unsigned int>> m_creaturePositions;\r\n\tQMap<unsigned int, QVariantMap> m_wallConstructions;\r\n\tQMap<unsigned int, QVariantMap> m_floorConstructions;\r\n\tQSet<Position> m_grass;\r\n\tQSet<unsigned int> m_grassCandidatePositions;\r\n\tQMap<unsigned int, QVariantMap> m_jobSprites;\r\n\tstd::set<unsigned int> m_water;\r\n\tQList<Position> m_aquifiers;\r\n\tQList<Position> m_deaquifiers;\r\n\r\n\tQSet<unsigned int> m_updatedTiles;\r\n\r\n\tQMap<QString, CONSTRUCTION_ID> m_constructionSID2ENUM;\r\n\tQMap<QString, CONSTR_ITEM_ID> m_constrItemSID2ENUM;\r\n\r\n\tbool constructWall( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructFloor( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructFence( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructWallFloor( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructStairs( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructRamp( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructRampCorner( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo );\r\n\tbool constructPipe( QString type, Position pos, unsigned int itemUID );\r\n\tbool deconstructPipe( QVariantMap constr, Position pos, Position workPos );\r\n\r\n\t\r\n\r\npublic:\r\n\tWorld( int dimX, int dimY, int dimZ, Game* game );\r\n\t~World();\r\n\r\n\tvoid init();\r\n\tvoid initWater();\r\n\tvoid afterLoad();\r\n\r\n\tvoid processGrass();\r\n\tvoid removeGrass( Position pos );\r\n\tvoid createGrass( Position pos );\r\n\tvoid initGrassUpdateList();\r\n\tvoid isGrassCandidate( Position pos );\r\n\tvoid addGrassCandidate( Position pos );\r\n\tbool hasGrass( Position pos );\r\n\tbool hasMaxGrass( Position pos );\r\n\r\n\tLightMap& lightMap()\r\n\t{\r\n\t\treturn m_lightMap;\r\n\t}\r\n\tRegionMap& regionMap()\r\n\t{\r\n\t\treturn m_regionMap;\r\n\t}\r\n\r\n\tstd::vector<Tile>& world()\r\n\t{\r\n\t\treturn m_world;\r\n\t}\r\n\tQMap<unsigned int, QVariantMap>& wallConstructions()\r\n\t{\r\n\t\treturn m_wallConstructions;\r\n\t}\r\n\tQMap<unsigned int, QVariantMap>& floorConstructions()\r\n\t{\r\n\t\treturn m_floorConstructions;\r\n\t}\r\n\r\n\tvoid setWallSprite( unsigned short x, unsigned short y, unsigned short z, unsigned int spriteUID, unsigned char rotation = 0 );\r\n\tvoid setWallSprite( const Position pos, unsigned int spriteUID, unsigned char rotation = 0 );\r\n\r\n\tvoid setItemSprite( unsigned short x, unsigned short y, unsigned short z, unsigned int spriteUID, unsigned char rotation = 0 );\r\n\tvoid setItemSprite( const Position pos, unsigned int spriteUID, unsigned char rotation = 0 );\r\n\r\n\tvoid setFloorSprite( unsigned short x, unsigned short y, unsigned short z, unsigned int spriteUID );\r\n\tvoid setFloorSprite( const Position pos, unsigned int spriteUID );\r\n\r\n\tvoid setJobSprite( Position pos, unsigned int spriteUID, unsigned char rotation, bool floor, unsigned int jobID, bool busy );\r\n\tvoid clearJobSprite( Position pos, bool floor );\r\n\r\n\tvoid setWallSprite( unsigned int tileID, unsigned int spriteID );\r\n\tvoid setFloorSprite( unsigned int tileID, unsigned int spriteID );\r\n\tvoid setJobSprite( unsigned int tileID, unsigned int spriteID, unsigned char rotation, bool floor, unsigned int jobID, bool busy );\r\n\r\n\tQVariantMap jobSprite( Position pos );\r\n\tQVariantMap jobSprite( int x, int y, int z );\r\n\tQVariantMap jobSprite( unsigned int tileID );\r\n\tQMap<unsigned int, QVariantMap> jobSprites();\r\n\tvoid insertLoadedJobSprite( unsigned int key, QVariantMap entry );\r\n\tbool hasJob( Position pos );\r\n\tbool hasJob( int x, int y, int z );\r\n\tbool hasJob( unsigned int tileID );\r\n\r\n\tvoid setTileFlag( unsigned short x, unsigned short y, unsigned short z, TileFlag flag );\r\n\tvoid setTileFlag( Position pos, TileFlag flag );\r\n\r\n\tTileFlag getTileFlag( Position pos );\r\n\r\n\tvoid clearTileFlag( Position pos, TileFlag flag );\r\n\r\n\tvoid setWalkable( Position pos, bool value );\r\n\tvoid updateWalkable( Position pos );\r\n\r\n\tunsigned short wallMaterial( Position pos );\r\n\tunsigned short embeddedMaterial( Position pos );\r\n\tunsigned short floorMaterial( Position pos );\r\n\tWallType wallType( Position pos );\r\n\tFloorType floorType( Position pos );\r\n\r\n\tint walkableNeighbors( Position pos );\r\n\tQList<Position> connectedNeighbors( Position pos );\r\n\r\n\tQMap<unsigned int, Plant>& plants()\r\n\t{\r\n\t\treturn m_plants;\r\n\t}\r\n\r\n\t// returns true when construction succeeded, false otherwise\r\n\tbool construct( QString constructionSID, Position pos, int rotation, QList<unsigned int> itemUIDs, Position extractTo );\r\n\tbool constructItem( QString itemSID, Position pos, int rotation, QList<unsigned int> itemUIDs, Position extractTo );\r\n\tbool constructWorkshop( QString constructionSID, Position pos, int rotation, QList<unsigned int> itemUIDs, Position extractTo );\r\n\t// returns true when deconstruction succeeded, false otherwise\r\n\tbool deconstruct( Position pos, Position workPos, bool ignoreGravity );\r\n\tbool deconstruct2( QVariantMap constr, Position decPos, bool isFloor, Position workPos, bool ignoreGravity );\r\n\r\n\tvoid updateNavigation( QList<Position>& coords, Position extractTo );\r\n\r\n\tvoid updateFenceSprite( Position pos );\r\n\tvoid updatePipeSprite( Position pos );\r\n\tvoid addLoadedSprites( QVariantMap vals );\r\n\r\n\tvoid expelTileInhabitants( Position pos, Position& to );\r\n\tvoid expelTileItems( Position pos, Position& to );\r\n\r\n\tvoid plantTree( Position pos, QString type, bool fullyGrown = false );\r\n\tvoid plantMushroom( Position pos, QString type, bool fullyGrown = false );\r\n\tvoid plant( Position pos, unsigned int baseItem );\r\n\tvoid addPlant( Plant plant );\r\n\tvoid removePlant( Position pos );\r\n\tvoid removePlant( Plant plant );\r\n\tbool reduceOneGrowLevel( Position pos );\r\n\r\n\tQMap<unsigned int, QList<unsigned int>>& creaturePositions()\r\n\t{\r\n\t\treturn m_creaturePositions;\r\n\t}\r\n\tvoid removeCreatureFromPosition( Position pos, unsigned int creatureID );\r\n\tvoid insertCreatureAtPosition( Position pos, unsigned int creatureID );\r\n\tbool creatureAtPos( Position pos );\r\n\tbool creatureAtPos( unsigned int posID );\r\n\tCreature* firstCreatureAtPos( unsigned int posID, quint8& rotation );\r\n\r\n\tvoid addAquifier( Position pos );\r\n\tvoid addWater( Position pos, unsigned char level );\r\n\tvoid changeFluidLevel( Position pos, int diff );\r\n\tvoid addDeaquifier( Position pos );\r\n\tvoid processWater();\r\n\tvoid processWaterFlow();\r\n\r\n\tvoid removeDesignation( Position pos );\r\n\r\n\t// return materialUID\r\n\tQPair<unsigned short, unsigned short> mineWall( Position pos, Position& workPosition );\r\n\tQPair<unsigned short, unsigned short> removeWall( Position pos, Position& workPosition );\r\n\tunsigned short removeRamp( Position pos, Position workPosition );\r\n\tvoid updateRampAtPos( Position pos );\r\n\r\n\tvoid discover( Position pos );\r\n\tvoid discover( int x, int y, int z );\r\n\r\n\t// return materialUID\r\n\tunsigned short removeFloor( Position pos, Position extractTo );\r\n\r\n\tbool isWalkable( Position pos );\r\n\tbool isWalkableGnome( Position pos );\r\n\tbool isRamp( Position pos );\r\n\tvoid getFloorLevelBelow( Position& pos, bool setSunlight );\r\n\tbool isSolidFloor( Position pos );\r\n\r\n\tint fluidLevel( Position pos );\r\n\tint vegetationLevel( Position pos );\r\n\tvoid setVegetationLevel( Position pos, int level );\r\n\r\n\tvoid createRamp( int x, int y, int z, TerrainMaterial mat );\r\n\tvoid createRamp( Position pos );\r\n\tvoid createRamp( int x, int y, int z );\r\n\tvoid createRamp( Position pos, QString material );\r\n\tvoid createRamp( int x, int y, int z, QString material );\r\n\r\n\tvoid setRampSprites( Tile& tile, Tile& tileAbove, int sum, bool north, bool east, bool south, bool west, QString materialSID );\r\n\r\n\tvoid createRampOuterCorners( int x, int y, int z );\r\n\r\n\t// TODO make the tile getters all private\r\n\tTile& getTile( const unsigned short x, const unsigned short y, const unsigned short z );\r\n\t//Tile& getTile( Position pos );\r\n\tTile& getTile( const Position pos );\r\n\tconst Tile& getTile( const Position pos ) const;\r\n\tTile& getTile( const unsigned int id );\r\n\r\n\tbool noTree( const Position pos, const int xRange, const int yRange );\r\n\tbool noShroom( const Position pos, const int xRange, const int yRange );\r\n\r\n\tQSet<unsigned int> updatedTiles();\r\n\tvoid addToUpdateList( const unsigned int uID );\r\n\tvoid addToUpdateList( const Position pos );\r\n\tvoid addToUpdateList( const unsigned short x, const unsigned short y, const unsigned short z );\r\n\tvoid addToUpdateList( const QVector<unsigned int>& ul );\r\n\tvoid addToUpdateList( const QSet<unsigned int>& ul );\r\n\r\n\tvoid setDoorLocked( unsigned int tileUID, bool lockGnome, bool lockMonster, bool lockAnimal );\r\n\r\n\tvoid putLight( const Position pos, int light );\r\n\tvoid putLight( const unsigned short x, const unsigned short y, const unsigned short z, int light );\r\n\tvoid addLight( unsigned int id, Position pos, int intensity );\r\n\r\n\tvoid updateSunlight( Position pos );\r\n\tbool hasSunlight( Position pos );\r\n\tvoid updateLightsInRange( Position pos );\r\n\r\n\tvoid removeLight( unsigned int id );\r\n\r\n\tvoid moveLight( unsigned int id, Position pos, int intensity );\r\n\r\n\tvoid loadFloorConstructions( QVariantList list );\r\n\tvoid loadWallConstructions( QVariantList list );\r\n\r\n\tbool checkTrapGnomeFloor( Position pos, Position workPos );\r\n\r\n\tvoid spreadIndirectSunlight( Position pos );\r\n\tvoid checkIndirectSunlightForNeighbors( Position pos );\r\n\tvoid checkIndirectSunlight( Position pos );\r\n\r\n\tvoid setWallSpriteAnim( Position pos, bool anim );\r\n\r\n\tQString getDebugWallConstruction( Position pos );\r\n\tQString getDebugFloorConstruction( Position pos );\r\n\r\n\tunsigned int getFurnitureOnTile( Position pos );\r\n\r\n\tbool isLineOfSight( Position a, Position b ) const;\r\n};\r\n\r\n#endif /* WORLD_H_ */\r\n"
  },
  {
    "path": "src/game/worldconstructions.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/fluidmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"world.h\"\r\n\r\n//#include <QDebug>\r\n#include <QJsonDocument>\r\n\r\nconst int ROT_BIT  = 65536;\r\nconst int ANIM_BIT = 262144;\r\nconst int WALL_BIT = 524288;\r\n\r\nbool World::construct( QString constructionSID, Position pos, int rotation, QList<unsigned int> itemIDs, Position extractTo )\r\n{\r\n\tif ( itemIDs.empty() )\r\n\t{\r\n\t\t//qDebug() << \"World::construct() - source item list is empty!\";\r\n\t\treturn false;\r\n\t}\r\n\r\n\t//qDebug() << \"world::construct() \" << constructionSID << pos.toString() << rotation;\r\n\tQVariantMap con = DB::selectRow( \"Constructions\", constructionSID );\r\n\tQString type    = con.value( \"Type\" ).toString();\r\n\t\r\n\tint typeNum     = m_constructionSID2ENUM.value( type );\r\n\r\n\tQStringList materialSIDs;\r\n\tQVariantList materialUIDs;\r\n\tQVariantList itemUIDs;\r\n\tfor ( auto vItem : itemIDs )\r\n\t{\r\n\t\tif ( g->inv()->itemExists( vItem ) )\r\n\t\t{\r\n\t\t\tmaterialSIDs.append( g->inv()->materialSID( vItem ) );\r\n\t\t\tmaterialUIDs.append( g->inv()->materialUID( vItem ) );\r\n\t\t\titemUIDs.append( g->inv()->itemUID( vItem ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//qDebug() << \"Source item no longer exists!\" << vItem;\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\tbool result = false;\r\n\r\n\tswitch ( typeNum )\r\n\t{\r\n\t\tcase CID_WALL:\r\n\t\t\treturn constructWall( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_FANCYWALL:\r\n\t\t\treturn constructWall( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_FENCE:\r\n\t\t\treturn constructFence( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_FLOOR:\r\n\t\t\treturn constructFloor( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_FANCYFLOOR:\r\n\t\t\treturn constructFloor( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_STAIRS:\r\n\t\t\treturn constructStairs( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_RAMP:\r\n\t\t\treturn constructRamp( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_RAMPCORNER:\r\n\t\t\treturn constructRampCorner( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t\t\tbreak;\r\n\t\tcase CID_WALLFLOOR:\r\n\t\t\treturn constructWallFloor( con, pos, rotation, itemUIDs, materialUIDs, materialSIDs, extractTo );\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n\r\nbool World::constructWall( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tQVariantMap spMap = sp;\r\n\t\tPosition offset( spMap.value( \"Offset\" ).toString() );\r\n\t\tPosition constrPos( pos + offset );\r\n\r\n\t\tTile& tile = getTile( constrPos );\r\n\r\n\t\tif ( tile.wallType & WallType::WT_ROUGH )\r\n\t\t{\r\n\t\t\tauto mats = mineWall( pos, extractTo );\r\n\t\t\tGlobal::util->createRawMaterialItem( extractTo, mats.first );\r\n\t\t\tGlobal::util->createRawMaterialItem( extractTo, mats.second );\r\n\t\t}\r\n\t\tif ( m_wallConstructions.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tdeconstruct( pos, extractTo, true );\r\n\t\t}\r\n\r\n\t\tQString spriteSID      = spMap.value( \"SpriteID\" ).toString();\r\n\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, materialSIDs )->uID;\r\n\t\ttile.wallSpriteUID     = spriteUID;\r\n\r\n\t\tif ( con.value( \"NoConstruction\" ).toBool() )\r\n\t\t{\r\n\t\t\ttile.wallType = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_ROUGH | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttile.wallType = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING | WallType::WT_CONSTRUCTED );\r\n\r\n\t\t\tpositions.append( \"W\" );\r\n\t\t\tpositions.append( constrPos.toString() );\r\n\t\t}\r\n\r\n\t\ttile.wallMaterial     = materialUIDs.first().toUInt();\r\n\t\ttile.embeddedMaterial = 0;\r\n\t\ttile.itemSpriteUID    = 0;\r\n\t\ttile.wallRotation     = rotation;\r\n\t\tclearTileFlag( constrPos, TileFlag::TF_WALKABLE );\r\n\t\tremoveGrass( constrPos );\r\n\t\tif ( tile.lightLevel > 0 )\r\n\t\t{\r\n\t\t\tupdateLightsInRange( constrPos );\r\n\t\t}\r\n\t\tupdateCoords.push_back( constrPos );\r\n\t}\r\n\r\n\tif ( !con.value( \"NoConstruction\" ).toBool() )\r\n\t{\r\n\t\tQVariantMap constr;\r\n\t\tconstr.insert( \"Pos\", pos.toString() );\r\n\t\tif ( positions.size() > 2 )\r\n\t\t{\r\n\t\t\tconstr.insert( \"Positions\", positions );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tconstr.insert( \"T\", \"W\" );\r\n\t\t}\r\n\t\tconstr.insert( \"Items\", itemUIDs );\r\n\t\tconstr.insert( \"Materials\", materialUIDs );\r\n\r\n\t\tm_wallConstructions.insert( pos.toInt(), constr );\r\n\t}\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructFloor( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tQVariantMap spMap = sp;\r\n\t\tPosition offset( spMap.value( \"Offset\" ).toString() );\r\n\r\n\t\tPosition constrPos( pos + offset );\r\n\r\n\t\tTile& tile = getTile( constrPos );\r\n\r\n\t\tif ( (bool)( tile.floorType & FloorType::FT_SOLIDFLOOR ) && !(bool)( tile.floorType & FloorType::FT_CONSTRUCTION ) )\r\n\t\t{\r\n\t\t\tauto mat = floorMaterial( constrPos );\r\n\t\t\t//auto mats = removeFloor( pos, extractTo );\r\n\t\t\tGlobal::util->createRawMaterialItem( extractTo, mat );\r\n\t\t}\r\n\t\tif ( m_floorConstructions.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tauto constr = m_floorConstructions.value( pos.toInt() );\r\n\t\t\tm_floorConstructions.remove( pos.toInt() );\r\n\t\t\tdeconstruct2( constr, pos, true, extractTo, false );\r\n\t\t}\r\n\r\n\t\tQString spriteSID      = spMap.value( \"SpriteID\" ).toString();\r\n\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, materialSIDs )->uID;\r\n\r\n\t\ttile.floorSpriteUID = spriteUID;\r\n\t\tif ( con.value( \"NoConstruction\" ).toBool() )\r\n\t\t{\r\n\t\t\ttile.floorType = ( FloorType )( FloorType::FT_SOLIDFLOOR );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttile.floorType = ( FloorType )( FloorType::FT_SOLIDFLOOR | FloorType::FT_CONSTRUCTION );\r\n\r\n\t\t\tpositions.append( \"F\" );\r\n\t\t\tpositions.append( constrPos.toString() );\r\n\t\t}\r\n\r\n\t\ttile.floorMaterial = materialUIDs.first().toUInt();\r\n\t\ttile.floorRotation = rotation;\r\n\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\tremoveGrass( constrPos );\r\n\r\n\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t{\r\n\t\t\t//tile has sunlight, now we need to remove it below\r\n\t\t\tint z = constrPos.z - 1;\r\n\t\t\twhile ( z > 0 )\r\n\t\t\t{\r\n\t\t\t\tTile& tileBelow = getTile( constrPos.x, constrPos.y, z );\r\n\t\t\t\tif ( tileBelow.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t{\r\n\t\t\t\t\tclearTileFlag( Position( constrPos.x, constrPos.y, z ), TileFlag::TF_SUNLIGHT );\r\n\t\t\t\t\tcheckIndirectSunlightForNeighbors( Position( constrPos.x, constrPos.y, z ) );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t\t--z;\r\n\t\t\t}\r\n\t\t}\r\n\t\tupdateCoords.push_back( constrPos );\r\n\t}\r\n\r\n\tif ( !con.value( \"NoConstruction\" ).toBool() )\r\n\t{\r\n\t\tQVariantMap constr;\r\n\t\tconstr.insert( \"Pos\", pos.toString() );\r\n\t\tif ( positions.size() > 2 )\r\n\t\t{\r\n\t\t\tconstr.insert( \"Positions\", positions );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tconstr.insert( \"T\", \"F\" );\r\n\t\t}\r\n\t\tconstr.insert( \"Items\", itemUIDs );\r\n\t\tconstr.insert( \"Materials\", materialUIDs );\r\n\t\tm_floorConstructions.insert( pos.toInt(), constr );\r\n\t}\r\n\r\n\tisGrassCandidate( pos );\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructFence( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\tQString type;\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tPosition offset( sp.value( \"Offset\" ).toString() );\r\n\t\tPosition constrPos( pos + offset );\r\n\r\n\t\tpositions.append( \"W\" );\r\n\t\tpositions.append( constrPos.toString() );\r\n\r\n\t\tunsigned int tid = constrPos.toInt();\r\n\t\tTile& tile       = getTile( tid );\r\n\r\n\t\ttype = sp.value( \"Type\" ).toString();\r\n\r\n\t\tif ( type == \"Wall\" )\r\n\t\t{\r\n\t\t\ttile.wallType     = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING | WallType::WT_CONSTRUCTED );\r\n\t\t\ttile.wallMaterial = materialUIDs.first().toUInt();\r\n\t\t\ttile.wallRotation = 0;\r\n\t\t\tclearTileFlag( constrPos, TileFlag::TF_WALKABLE );\r\n\t\t\tif ( tile.lightLevel > 0 )\r\n\t\t\t{\r\n\t\t\t\tupdateLightsInRange( constrPos );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( type == \"WallSeeThrough\" )\r\n\t\t{\r\n\t\t\ttile.wallType     = ( WallType )( WallType::WT_MOVEBLOCKING | WallType::WT_CONSTRUCTED );\r\n\t\t\ttile.wallMaterial = materialUIDs.first().toUInt();\r\n\t\t\ttile.wallRotation = 0;\r\n\t\t\tclearTileFlag( constrPos, TileFlag::TF_WALKABLE );\r\n\t\t}\r\n\t\tupdateCoords.push_back( constrPos );\r\n\t}\r\n\r\n\tQVariantMap constr;\r\n\tconstr.insert( \"ConstructionID\", con.value( \"ID\" ).toString() );\r\n\tconstr.insert( \"Pos\", pos.toString() );\r\n\tif ( positions.size() > 2 )\r\n\t{\r\n\t\tconstr.insert( \"Positions\", positions );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tconstr.insert( \"T\", \"W\" );\r\n\t}\r\n\tconstr.insert( \"Items\", itemUIDs );\r\n\tconstr.insert( \"Materials\", materialUIDs );\r\n\r\n\tm_wallConstructions.insert( pos.toInt(), constr );\r\n\r\n\tupdateFenceSprite( pos );\r\n\tupdateFenceSprite( pos.northOf() );\r\n\tupdateFenceSprite( pos.eastOf() );\r\n\tupdateFenceSprite( pos.southOf() );\r\n\tupdateFenceSprite( pos.westOf() );\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructPipe( QString itemSID, Position pos, unsigned int itemUID )\r\n{\r\n\tQVariantMap constr;\r\n\tconstr.insert( \"ConstructionID\", \"Item\" );\r\n\tconstr.insert( \"Pos\", pos.toString() );\r\n\tconstr.insert( \"Item\", itemUID );\r\n\tconstr.insert( \"Type\", \"Hydraulics\" );\r\n\r\n\tm_wallConstructions.insert( pos.toInt(), constr );\r\n\r\n\tsetTileFlag( pos, TileFlag::TF_PIPE );\r\n\tTile& tile        = getTile( pos );\r\n\ttile.wallMaterial = g->inv()->materialUID( itemUID );\r\n\ttile.wallType     = WT_CONSTRUCTED;\r\n\r\n\tupdatePipeSprite( pos );\r\n\tupdatePipeSprite( pos.northOf() );\r\n\tupdatePipeSprite( pos.eastOf() );\r\n\tupdatePipeSprite( pos.southOf() );\r\n\tupdatePipeSprite( pos.westOf() );\r\n\r\n\tif ( itemSID == \"Pipe\" )\r\n\t{\r\n\t\tg->flm()->addPipe( pos, itemUID );\r\n\t}\r\n\telse if ( itemSID == \"PipeExit\" )\r\n\t{\r\n\t\tg->flm()->addOutput( pos, itemUID );\r\n\t}\r\n\telse if ( itemSID == \"Pump\" )\r\n\t{\r\n\t\tg->mcm()->installItem( itemUID, pos, 0 );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::deconstructPipe( QVariantMap constr, Position decPos, Position workPos )\r\n{\r\n\tTile& tile         = getTile( decPos );\r\n\ttile.wallType      = ( WallType )( WallType::WT_NOWALL );\r\n\ttile.wallSpriteUID = 0;\r\n\tclearTileFlag( decPos, TileFlag::TF_PIPE );\r\n\r\n\tupdatePipeSprite( decPos.northOf() );\r\n\tupdatePipeSprite( decPos.eastOf() );\r\n\tupdatePipeSprite( decPos.southOf() );\r\n\tupdatePipeSprite( decPos.westOf() );\r\n\r\n\tunsigned itemID = constr.value( \"Item\" ).toUInt();\r\n\tg->inv()->setConstructed( itemID, false );\r\n\tg->inv()->moveItemToPos( itemID, workPos );\r\n\r\n\tQString itemSID = g->inv()->itemSID( constr.value( \"Item\" ).toUInt() );\r\n\r\n\tg->flm()->removeAt( decPos );\r\n\r\n\tif ( itemSID == \"Pump\" )\r\n\t{\r\n\t\tg->mcm()->uninstallItem( constr.value( \"Item\" ).toUInt() );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructWallFloor( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tQVariantMap spMap = sp;\r\n\t\tPosition offset( spMap.value( \"Offset\" ).toString() );\r\n\r\n\t\tPosition constrPos( pos + offset );\r\n\r\n\t\tTile& tile = getTile( constrPos );\r\n\r\n\t\tQString spriteSID      = spMap.value( \"SpriteID\" ).toString();\r\n\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, materialSIDs )->uID;\r\n\r\n\t\tif ( spMap.value( \"Type\" ).toString() == \"Wall\" )\r\n\t\t{\r\n\t\t\tif ( con.value( \"NoConstruction\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\ttile.wallType = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_ROUGH | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttile.wallType = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING | WallType::WT_CONSTRUCTED );\r\n\r\n\t\t\t\tpositions.append( \"W\" );\r\n\t\t\t\tpositions.append( constrPos.toString() );\r\n\t\t\t}\r\n\r\n\t\t\ttile.wallSpriteUID = spriteUID;\r\n\t\t\ttile.wallMaterial  = materialUIDs.first().toUInt();\r\n\t\t\ttile.wallRotation  = rotation;\r\n\t\t\tclearTileFlag( constrPos, TileFlag::TF_WALKABLE );\r\n\t\t\tremoveGrass( constrPos );\r\n\t\t\tif ( tile.lightLevel > 0 )\r\n\t\t\t{\r\n\t\t\t\tupdateLightsInRange( constrPos );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse if ( spMap.value( \"Type\" ).toString() == \"Floor\" )\r\n\t\t{\r\n\t\t\ttile.floorSpriteUID = spriteUID;\r\n\t\t\tif ( con.value( \"NoConstruction\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\ttile.floorType = ( FloorType )( FloorType::FT_SOLIDFLOOR );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttile.floorType = ( FloorType )( FloorType::FT_SOLIDFLOOR | FloorType::FT_CONSTRUCTION );\r\n\r\n\t\t\t\tpositions.append( \"F\" );\r\n\t\t\t\tpositions.append( constrPos.toString() );\r\n\t\t\t}\r\n\r\n\t\t\ttile.floorSpriteUID = spriteUID;\r\n\t\t\ttile.floorMaterial  = materialUIDs.first().toUInt();\r\n\t\t\ttile.floorRotation  = rotation;\r\n\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\tremoveGrass( constrPos );\r\n\t\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t{\r\n\t\t\t\t//tile has sunlight, now we need to remove it below\r\n\t\t\t\tint z = constrPos.z - 1;\r\n\t\t\t\twhile ( z > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tTile& tileBelow = getTile( constrPos.x, constrPos.y, z );\r\n\t\t\t\t\tif ( tileBelow.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tclearTileFlag( Position( constrPos.x, constrPos.y, z ), TileFlag::TF_SUNLIGHT );\r\n\t\t\t\t\t\tcheckIndirectSunlightForNeighbors( Position( constrPos.x, constrPos.y, z ) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t--z;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tupdateCoords.push_back( constrPos );\r\n\t}\r\n\r\n\tif ( !con.value( \"NoConstruction\" ).toBool() )\r\n\t{\r\n\t\tQVariantMap constr;\r\n\t\tconstr.insert( \"Pos\", pos.toString() );\r\n\t\tconstr.insert( \"Positions\", positions );\r\n\t\tconstr.insert( \"Items\", itemUIDs );\r\n\t\tconstr.insert( \"Materials\", materialUIDs );\r\n\r\n\t\tfor ( int i = 0; i < positions.size(); i += 2 )\r\n\t\t{\r\n\t\t\tbool isWall = ( positions[i].toString() == \"W\" );\r\n\t\t\tPosition insertPos( positions[i + 1] );\r\n\t\t\tconstr.insert( \"Pos\", insertPos.toString() );\r\n\t\t\tif ( isWall )\r\n\t\t\t{\r\n\t\t\t\tm_wallConstructions.insert( insertPos.toInt(), constr );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_floorConstructions.insert( insertPos.toInt(), constr );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructStairs( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\tQString type;\r\n\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tPosition offset( sp.value( \"Offset\" ).toString() );\r\n\t\tPosition constrPos( pos + offset );\r\n\t\tunsigned int tid = constrPos.toInt();\r\n\t\tTile& tile       = getTile( tid );\r\n\r\n\t\tif ( sp.contains( \"Type\" ) )\r\n\t\t{\r\n\t\t\ttype                   = sp.value( \"Type\" ).toString();\r\n\t\t\tQString spriteSID      = sp.value( \"SpriteID\" ).toString();\r\n\t\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, materialSIDs )->uID;\r\n\r\n\t\t\tif ( type == \"StairsBottom\" )\r\n\t\t\t{\r\n\t\t\t\ttile.wallSpriteUID = spriteUID;\r\n\t\t\t\ttile.wallType      = ( WallType )( WallType::WT_STAIR | WallType::WT_CONSTRUCTED );\r\n\t\t\t\ttile.wallMaterial  = materialUIDs.first().toUInt();\r\n\t\t\t\ttile.wallRotation  = rotation;\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\tremoveGrass( constrPos );\r\n\t\t\t\tpositions.append( \"W\" );\r\n\t\t\t\tpositions.append( constrPos.toString() );\r\n\t\t\t}\r\n\t\t\telse if ( type == \"StairsTop\" )\r\n\t\t\t{\r\n\t\t\t\ttile.floorSpriteUID = spriteUID;\r\n\t\t\t\ttile.floorType      = ( FloorType )( FloorType::FT_STAIRTOP | FloorType::FT_CONSTRUCTION );\r\n\t\t\t\ttile.floorMaterial  = materialUIDs.first().toUInt();\r\n\t\t\t\ttile.floorRotation  = rotation;\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\ttile.wallType = WallType::WT_NOWALL;\r\n\t\t\t\tremoveGrass( constrPos );\r\n\t\t\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t{\r\n\t\t\t\t\tTile& tileBelow = getTile( constrPos.x, constrPos.y, constrPos.z - 1 );\r\n\t\t\t\t\ttileBelow.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t\t\t}\r\n\t\t\t\tpositions.append( \"F\" );\r\n\t\t\t\tpositions.append( constrPos.toString() );\r\n\t\t\t}\r\n\t\t\tupdateCoords.push_back( constrPos );\r\n\t\t}\r\n\t}\r\n\r\n\tQVariantMap constr;\r\n\tconstr.insert( \"ConstructionID\", con.value(\"ID\") );\r\n\tconstr.insert( \"Pos\", pos.toString() );\r\n\tconstr.insert( \"Positions\", positions );\r\n\tconstr.insert( \"Items\", itemUIDs );\r\n\tconstr.insert( \"Materials\", materialUIDs );\r\n\r\n\tfor ( int i = 0; i < positions.size(); i += 2 )\r\n\t{\r\n\t\tbool isWall = ( positions[i].toString() == \"W\" );\r\n\t\tPosition insertPos( positions[i + 1] );\r\n\t\tconstr.insert( \"Pos\", insertPos.toString() );\r\n\t\tif ( isWall )\r\n\t\t{\r\n\t\t\tm_wallConstructions.insert( insertPos.toInt(), constr );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_floorConstructions.insert( insertPos.toInt(), constr );\r\n\t\t}\r\n\t}\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructRamp( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\tQString type;\r\n\t/*\r\n\tif( Global::util->materialType( materialSIDs.first() ) == \"Soil\" || Global::util->materialType( materialSIDs.first() ) == \"Stone\" )\r\n\t{\r\n\t\tcreateRamp( pos, materialSIDs.first() );\r\n\t\tupdateCoords.append( pos );\r\n\t\tupdateNavigation( updateCoords, extractTo );\r\n\t\treturn true;\r\n\t}\r\n\t*/\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto sp : spl )\r\n\t{\r\n\t\tPosition offset( sp.value( \"Offset\" ).toString() );\r\n\t\tPosition constrPos( pos + offset );\r\n\t\tunsigned int tid = constrPos.toInt();\r\n\t\tTile& tile       = getTile( tid );\r\n\r\n\t\tif ( sp.contains( \"Type\" ) )\r\n\t\t{\r\n\t\t\ttype                   = sp.value( \"Type\" ).toString();\r\n\t\t\tQString spriteSID      = sp.value( \"SpriteID\" ).toString();\r\n\t\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, materialSIDs )->uID;\r\n\t\t\tremoveGrass( constrPos );\r\n\r\n\t\t\tif ( type == \"RampBottom\" )\r\n\t\t\t{\r\n\t\t\t\ttile.wallSpriteUID = spriteUID;\r\n\t\t\t\tif ( Global::util->materialType( materialSIDs.first() ) == \"Soil\" || Global::util->materialType( materialSIDs.first() ) == \"Stone\" )\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.wallType = ( WallType )( WallType::WT_RAMP );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.wallType = ( WallType )( WallType::WT_RAMP | WallType::WT_CONSTRUCTED );\r\n\t\t\t\t}\r\n\t\t\t\ttile.wallMaterial = materialUIDs.first().toUInt();\r\n\t\t\t\ttile.wallRotation = rotation;\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\tpositions.append( \"W\" );\r\n\t\t\t\tpositions.append( constrPos.toString() );\r\n\t\t\t}\r\n\t\t\tif ( type == \"RampTop\" )\r\n\t\t\t{\r\n\t\t\t\ttile.floorSpriteUID = spriteUID;\r\n\t\t\t\tif ( Global::util->materialType( materialSIDs.first() ) == \"Soil\" || Global::util->materialType( materialSIDs.first() ) == \"Stone\" )\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.floorType = ( FloorType )( FloorType::FT_RAMPTOP );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.floorType = ( FloorType )( FloorType::FT_RAMPTOP | FloorType::FT_CONSTRUCTION );\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttile.floorMaterial = materialUIDs.first().toUInt();\r\n\t\t\t\ttile.floorRotation = rotation;\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\ttile.wallType = WallType::WT_NOWALL;\r\n\t\t\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t{\r\n\t\t\t\t\tTile& tileBelow = getTile( constrPos.x, constrPos.y, constrPos.z - 1 );\r\n\t\t\t\t\ttileBelow.flags -= TileFlag::TF_SUNLIGHT;\r\n\t\t\t\t}\r\n\t\t\t\tpositions.append( \"F\" );\r\n\t\t\t\tpositions.append( constrPos.toString() );\r\n\t\t\t}\r\n\t\t\tupdateCoords.push_back( constrPos );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !( Global::util->materialType( materialSIDs.first() ) == \"Soil\" || Global::util->materialType( materialSIDs.first() ) == \"Stone\" ) )\r\n\t{\r\n\t\tQVariantMap constr;\r\n\t\tconstr.insert( \"Pos\", pos.toString() );\r\n\t\tconstr.insert( \"Positions\", positions );\r\n\t\tconstr.insert( \"Items\", itemUIDs );\r\n\t\tconstr.insert( \"Materials\", materialUIDs );\r\n\r\n\t\tfor ( int i = 0; i < positions.size(); i += 2 )\r\n\t\t{\r\n\t\t\tbool isWall = ( positions[i].toString() == \"W\" );\r\n\t\t\tPosition insertPos( positions[i + 1] );\r\n\t\t\tconstr.insert( \"Pos\", insertPos.toString() );\r\n\t\t\tif ( isWall )\r\n\t\t\t{\r\n\t\t\t\tm_wallConstructions.insert( insertPos.toInt(), constr );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_floorConstructions.insert( insertPos.toInt(), constr );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructWorkshop( QString constructionSID, Position pos, int rotation, QList<unsigned int> itemUIDs, Position extractTo )\r\n{\r\n\tauto dbws = DB::workshop( constructionSID );\r\n\tif( dbws )\r\n\t{\r\n\t\tQVariantList spriteComposition;\r\n\r\n\t\tauto cpl = dbws->components;\r\n\t\tfor ( auto cp : cpl )\r\n\t\t{\r\n\t\t\tPosition offset;\r\n\r\n\t\t\toffset   = cp.Offset;\r\n\t\t\tint rotX = offset.x;\r\n\t\t\tint rotY = offset.y;\r\n\t\t\tswitch ( rotation )\r\n\t\t\t{\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\toffset.x = -1 * rotY;\r\n\t\t\t\t\toffset.y = rotX;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\toffset.x = -1 * rotX;\r\n\t\t\t\t\toffset.y = -1 * rotY;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\toffset.x = rotY;\r\n\t\t\t\t\toffset.y = -1 * rotX;\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tPosition constrPos( pos + offset );\r\n\r\n\t\t\tunsigned int tid = constrPos.toInt();\r\n\t\t\tTile& tile       = getTile( tid );\r\n\t\t\taddToUpdateList( tid );\r\n\t\t\tQVariantMap scm;\r\n\t\t\tscm.insert( \"Pos\", constrPos.toString() );\r\n\r\n\t\t\tif ( cp.SpriteID.isEmpty() || cp.SpriteID == \"WorkshopInputIndicator\" )\r\n\t\t\t{\r\n\t\t\t\ttile.wallType = WallType::WT_CONSTRUCTED;\r\n\t\t\t\ttile.flags += TileFlag::TF_WORKSHOP;\r\n\t\t\t\tspriteComposition.append( scm );\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tQStringList materialIDs;\r\n\r\n\t\t\tif ( !cp.ItemID.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tQString baseItem = cp.ItemID;\r\n\r\n\t\t\t\tfor ( auto itemUID : itemUIDs )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( g->inv()->itemSID( itemUID ) == baseItem )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmaterialIDs.push_back( g->inv()->materialSID( itemUID ) );\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\telse if ( !cp.MaterialItem.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto matID : cp.MaterialItem.split( \"|\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tmaterialIDs.push_back( g->inv()->materialSID( itemUIDs[matID.toInt()] ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tmaterialIDs.push_back( \"None\" );\r\n\t\t\t}\r\n\t\t\tbool floor = cp.IsFloor;\r\n\t\t\tscm.insert( \"IsFloor\", floor );\r\n\r\n\t\t\tif ( floor )\r\n\t\t\t{\r\n\t\t\t\ttile.floorSpriteUID = g->sf()->createSprite( cp.SpriteID, materialIDs )->uID;\r\n\t\t\t\tscm.insert( \"UID\", tile.floorSpriteUID );\r\n\t\t\t\tspriteComposition.append( scm );\r\n\t\t\t\ttile.floorType = FT_SOLIDFLOOR;\r\n\t\t\t\tsetWalkable( constrPos, true );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSprite* sprite     = g->sf()->createSprite( cp.SpriteID, materialIDs );\r\n\t\t\t\ttile.wallSpriteUID = sprite->uID;\r\n\t\t\t\tsetWallSpriteAnim( constrPos, sprite->anim );\r\n\t\t\t\tscm.insert( \"UID\", tile.wallSpriteUID );\r\n\t\t\t\tspriteComposition.append( scm );\r\n\r\n\t\t\t\tif ( !cp.WallRotation.isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString rot = cp.WallRotation;\r\n\t\t\t\t\tif ( rot == \"FR\" )\r\n\t\t\t\t\t\ttile.wallRotation = 0;\r\n\t\t\t\t\telse if ( rot == \"FL\" )\r\n\t\t\t\t\t\ttile.wallRotation = 1;\r\n\t\t\t\t\telse if ( rot == \"BL\" )\r\n\t\t\t\t\t\ttile.wallRotation = 2;\r\n\t\t\t\t\telse if ( rot == \"BR\" )\r\n\t\t\t\t\t\ttile.wallRotation = 3;\r\n\t\t\t\t}\r\n\t\t\t\ttile.wallRotation = ( tile.wallRotation + rotation ) % 4;\r\n\t\t\t\ttile.wallType     = WallType::WT_CONSTRUCTED;\r\n\t\t\t}\r\n\t\t\ttile.flags += TileFlag::TF_WORKSHOP;\r\n\t\t}\r\n\r\n\t\tWorkshop* ws = g->wsm()->addWorkshop( dbws->ID, pos, rotation );\r\n\t\tws->setSourceItems( Util::uintList2Variant( itemUIDs ) );\r\n\t\tws->setSprites( spriteComposition );\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool World::constructRampCorner( QVariantMap& con, Position pos, int rotation, QVariantList itemUIDs, QVariantList materialUIDs, QStringList materialSIDs, Position extractTo )\r\n{\r\n\tQList<Position> updateCoords;\r\n\tQVariantList positions;\r\n\tauto spl = DB::selectRows( \"Constructions_Sprites\", \"ID\", con.value( \"ID\" ).toString() );\r\n\tfor ( auto spMap : spl )\r\n\t{\r\n\t\tPosition offset( spMap.value( \"Offset\" ).toString() );\r\n\r\n\t\tPosition constrPos( pos + offset );\r\n\r\n\t\tpositions.append( \"W\" );\r\n\t\tpositions.append( constrPos.toString() );\r\n\r\n\t\tTile& tile = getTile( constrPos );\r\n\r\n\t\tQString spriteSID = spMap.value( \"SpriteID\" ).toString();\r\n\r\n\t\tunsigned int spriteUID = g->sf()->createSprite( spriteSID, materialSIDs )->uID;\r\n\r\n\t\ttile.wallSpriteUID = spriteUID;\r\n\r\n\t\tif ( spMap.value( \"Type\" ).toString() == \"Wall\" )\r\n\t\t{\r\n\t\t\tif ( con.value( \"NoConstruction\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\ttile.wallType = ( WallType )( WallType::WT_RAMPCORNER );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttile.wallType = ( WallType )( WallType::WT_RAMPCORNER | WallType::WT_CONSTRUCTED );\r\n\t\t\t}\r\n\r\n\t\t\ttile.wallMaterial = materialUIDs.first().toUInt();\r\n\t\t\ttile.wallRotation = rotation;\r\n\t\t\tclearTileFlag( constrPos, TileFlag::TF_WALKABLE );\r\n\t\t\tremoveGrass( constrPos );\r\n\t\t\tif ( tile.lightLevel > 0 )\r\n\t\t\t{\r\n\t\t\t\tupdateLightsInRange( constrPos );\r\n\t\t\t}\r\n\t\t\tpositions.append( \"W\" );\r\n\t\t\tpositions.append( constrPos.toString() );\r\n\t\t}\r\n\t\telse if ( spMap.value( \"Type\" ).toString() == \"Floor\" )\r\n\t\t{\r\n\t\t\ttile.floorSpriteUID = spriteUID;\r\n\t\t\tif ( con.value( \"NoConstruction\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\ttile.floorType = ( FloorType )( FloorType::FT_RAMPTOP );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttile.floorType = ( FloorType )( FloorType::FT_RAMPTOP | FloorType::FT_CONSTRUCTION );\r\n\t\t\t}\r\n\r\n\t\t\ttile.floorMaterial = materialUIDs.first().toUInt();\r\n\t\t\ttile.floorRotation = rotation;\r\n\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\tremoveGrass( constrPos );\r\n\t\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t{\r\n\t\t\t\t//tile has sunlight, now we need to remove it below\r\n\t\t\t\tint z = constrPos.z - 1;\r\n\t\t\t\twhile ( z > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tTile& tileBelow = getTile( constrPos.x, constrPos.y, z );\r\n\t\t\t\t\tif ( tileBelow.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tclearTileFlag( Position( constrPos.x, constrPos.y, z ), TileFlag::TF_SUNLIGHT );\r\n\t\t\t\t\t\tcheckIndirectSunlightForNeighbors( Position( constrPos.x, constrPos.y, z ) );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t--z;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tpositions.append( \"F\" );\r\n\t\t\tpositions.append( constrPos.toString() );\r\n\t\t}\r\n\t\tupdateCoords.push_back( constrPos );\r\n\t}\r\n\r\n\tQVariantMap constr;\r\n\tconstr.insert( \"Pos\", pos.toString() );\r\n\tconstr.insert( \"Positions\", positions );\r\n\tconstr.insert( \"Items\", itemUIDs );\r\n\tconstr.insert( \"Materials\", materialUIDs );\r\n\r\n\tfor ( int i = 0; i < positions.size(); i += 2 )\r\n\t{\r\n\t\tbool isWall = ( positions[i].toString() == \"W\" );\r\n\t\tPosition insertPos( positions[i + 1] );\r\n\t\tconstr.insert( \"Pos\", insertPos.toString() );\r\n\t\tif ( isWall )\r\n\t\t{\r\n\t\t\tm_wallConstructions.insert( insertPos.toInt(), constr );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_floorConstructions.insert( insertPos.toInt(), constr );\r\n\t\t}\r\n\t}\r\n\r\n\tupdateNavigation( updateCoords, extractTo );\r\n\r\n\treturn true;\r\n}\r\n\r\nbool World::constructItem( QString itemSID, Position pos, int rotation, QList<unsigned int> items, Position extractTo )\r\n{\r\n\tif ( items.empty() )\r\n\t\treturn false;\r\n\r\n\tunsigned int itemID = items.first();\r\n\r\n\tQVariantMap constr;\r\n\r\n\tif ( g->inv()->itemSID( itemID ) != itemSID )\r\n\t{\r\n\t\t//qDebug() << \"create item from components before installing\";\r\n\t\tauto vItems = Global::util->uintList2Variant( items );\r\n\t\titemID      = g->inv()->createItem( pos, itemSID, vItems );\r\n\t\tconstr.insert( \"Items\", vItems );\r\n\t\tconstr.insert( \"FromParts\", true );\r\n\t\tfor ( auto item : items )\r\n\t\t{\r\n\t\t\tg->inv()->setConstructed( item, true );\r\n\t\t}\r\n\t}\r\n\r\n\tQString type  = DB::select( \"Category\", \"Items\", g->inv()->itemSID( itemID ) ).toString();\r\n\tQString group = DB::select( \"ItemGroup\", \"Items\", g->inv()->itemSID( itemID ) ).toString();\r\n\r\n\tTile& tile = getTile( pos );\r\n\r\n\tSprite* sprite = g->sf()->getSprite( g->inv()->spriteID( itemID ) );\r\n\r\n\tQString location = DB::select( \"Location\", \"Items_Tiles\", itemSID ).toString();\r\n\r\n\tif ( location == \"Wall\" )\r\n\t{\r\n\t\ttile.wallSpriteUID = sprite->uID;\r\n\t\ttile.wallRotation  = rotation;\r\n\t\ttile.wallType      = WallType::WT_CONSTRUCTED;\r\n\t\tif ( sprite->anim )\r\n\t\t{\r\n\t\t\t//qDebug() << \"set anim\";\r\n\t\t\ttile.wallSpriteUID += ANIM_BIT;\r\n\t\t}\r\n\t}\r\n\telse if ( location == \"Floor\" )\r\n\t{\r\n\t\ttile.floorSpriteUID = sprite->uID;\r\n\t\ttile.floorRotation  = rotation;\r\n\t\ttile.floorType      = FloorType::FT_CONSTRUCTION;\r\n\t\tif ( sprite->anim )\r\n\t\t{\r\n\t\t\ttile.floorSpriteUID += ANIM_BIT;\r\n\t\t}\r\n\t}\r\n\telse if ( location == \"HiddenFloor\" )\r\n\t{\r\n\t}\r\n\r\n\tg->inv()->setConstructed( itemID, true );\r\n\r\n\tunsigned int nextItem = g->inv()->getFirstObjectAtPosition( pos );\r\n\tif ( nextItem )\r\n\t{\r\n\t\tsetItemSprite( pos, g->inv()->spriteID( nextItem ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetItemSprite( pos, 0 );\r\n\t}\r\n\t//qDebug() << \"##\" << type << group << itemSID;\r\n\t// TODO remove this workaround\r\n\tif( itemSID == \"AlarmBell\" )\r\n\t{\r\n\t\tgroup = \"AlarmBell\";\r\n\t}\r\n\r\n\taddToUpdateList( pos );\r\n\tswitch ( m_constrItemSID2ENUM.value( type ) )\r\n\t{\r\n\t\tcase CI_STORAGE:\r\n\t\t\tg->spm()->addContainer( itemID, pos );\r\n\t\t\tbreak;\r\n\t\tcase CI_FURNITURE:\r\n\t\t\tg->rm()->addFurniture( itemID, pos );\r\n\t\t\tbreak;\r\n\t}\r\n\tswitch ( m_constrItemSID2ENUM.value( group ) )\r\n\t{\r\n\t\tcase CI_DOOR:\r\n\t\t\tsetTileFlag( pos, TileFlag::TF_DOOR );\r\n\t\t\tg->rm()->addDoor( pos, itemID, g->inv()->materialUID( itemID ) );\r\n\t\t\tbreak;\r\n\t\tcase CI_LIGHT:\r\n\t\t{\r\n\t\t\tint intensity = DB::select( \"LightIntensity\", \"Items\", g->inv()->itemSID( itemID ) ).toInt();\r\n\t\t\tconstr.insert( \"Light\", intensity );\r\n\t\t\tif ( intensity )\r\n\t\t\t{\r\n\t\t\t\taddLight( pos.toInt(), pos, intensity );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase CI_ALARMBELL:\r\n\t\t\tg->rm()->addFurniture( itemID, pos );\r\n\t\t\tbreak;\r\n\t\tcase CI_MECHANISM:\r\n\t\t\tg->mcm()->installItem( itemID, pos, rotation );\r\n\t\t\tbreak;\r\n\t\tcase CI_HYDRAULICS:\r\n\t\t\treturn constructPipe( itemSID, pos, itemID );\r\n\t\t\tbreak;\r\n\t\tcase CI_FARMUTIL:\r\n\t\t\tg->fm()->addUtil( pos, itemID );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tconstr.insert( \"ConstructionID\", \"Item\" );\r\n\tconstr.insert( \"Pos\", pos.toString() );\r\n\tconstr.insert( \"Rot\", rotation );\r\n\tconstr.insert( \"Item\", itemID );\r\n\tconstr.insert( \"Type\", type );\r\n\tconstr.insert( \"Group\", group );\r\n\r\n\tif ( location == \"Wall\" )\r\n\t{\r\n\t\tm_wallConstructions.insert( pos.toInt(), constr );\r\n\t}\r\n\telse if ( location == \"Floor\" || location == \"FloorHidden\" )\r\n\t{\r\n\t\tconstr.insert( \"Hidden\", location == \"FloorHidden\" );\r\n\t\tm_floorConstructions.insert( pos.toInt(), constr );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid World::updateNavigation( QList<Position>& coords, Position extractTo )\r\n{\r\n\tfor ( auto p : coords )\r\n\t{\r\n\t\texpelTileInhabitants( p, extractTo );\r\n\t\texpelTileItems( p, extractTo );\r\n\t}\r\n\r\n\tfor ( auto p : coords )\r\n\t{\r\n\t\tm_regionMap.updatePosition( p );\r\n\t}\r\n\tfor ( auto p : coords )\r\n\t{\r\n\t\tm_regionMap.updateConnectedRegions( p );\r\n\t}\r\n}\r\n\r\nbool World::deconstruct( Position decPos, Position workPos, bool ignoreGravity )\r\n{\r\n\tQVariantMap constr;\r\n\tif ( m_wallConstructions.contains( decPos.toInt() ) )\r\n\t{\r\n\t\tconstr = m_wallConstructions.value( decPos.toInt() );\r\n\t\tm_wallConstructions.remove( decPos.toInt() );\r\n\t\treturn deconstruct2( constr, decPos, false, workPos, ignoreGravity );\r\n\t}\r\n\telse if ( g->wsm()->isWorkshop( decPos ) )\r\n\t{\r\n\t\tWorkshop* ws     = g->wsm()->workshopAt( decPos );\r\n\t\tauto sourceItems = ws->sourceItems();\r\n\t\tws->destroy();\r\n\r\n\t\tQVariantList sprites = ws->sprites();\r\n\t\tfor ( auto spritevm : sprites )\r\n\t\t{\r\n\t\t\tPosition wsPos( spritevm.toMap().value( \"Pos\" ).toString() );\r\n\t\t\tunsigned int tid = wsPos.toInt();\r\n\t\t\tTile& tile       = getTile( tid );\r\n\t\t\t\r\n\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\tclearTileFlag( wsPos, TileFlag::TF_WORKSHOP );\r\n\t\t\ttile.wallType = WallType::WT_NOWALL;\r\n\r\n\t\t\tupdateWalkable( wsPos );\r\n\t\t\taddToUpdateList( wsPos );\r\n\t\t}\r\n\t\tfor ( auto vItem : sourceItems )\r\n\t\t{\r\n\t\t\tg->inv()->putDownItem( vItem.toUInt(), workPos );\r\n\t\t\tg->inv()->setConstructed( vItem.toUInt(), false );\r\n\t\t}\r\n\r\n\t\tg->wsm()->deleteWorkshop( ws->id() );\r\n\t\treturn true;\r\n\t}\r\n\telse if ( m_floorConstructions.contains( decPos.toInt() ) )\r\n\t{\r\n\t\tconstr = m_floorConstructions.value( decPos.toInt() );\r\n\t\tm_floorConstructions.remove( decPos.toInt() );\r\n\t\treturn deconstruct2( constr, decPos, true, workPos, ignoreGravity );\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n}\r\n\r\nbool World::deconstruct2( QVariantMap constr, Position decPos, bool isFloor, Position workPos, bool ignoreGravity )\r\n{\r\n\tqDebug() << \"deconstruct\" << decPos.toString() << isFloor;\r\n\tif ( constr.value( \"ConstructionID\" ).toString() == \"Item\" )\r\n\t{\r\n\t\tunsigned itemID = constr.value( \"Item\" ).toUInt();\r\n\r\n\t\tQString type  = constr.value( \"Type\" ).toString();\r\n\t\tQString group = constr.value( \"Group\" ).toString();\r\n\t\t// TODO remove this workaround\r\n\t\tif( g->inv()->itemSID( itemID ) == \"AlarmBell\" )\r\n\t\t{\r\n\t\t\tgroup = \"AlarmBell\";\r\n\t\t}\r\n\t\tswitch ( m_constrItemSID2ENUM.value( type ) )\r\n\t\t{\r\n\t\t\tcase CI_STORAGE:\r\n\t\t\t\tg->spm()->removeContainer( itemID, decPos );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CI_FURNITURE:\r\n\t\t\t\tg->rm()->removeFurniture( decPos );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CI_HYDRAULICS:\r\n\t\t\t\tdeconstructPipe( constr, decPos, workPos );\r\n\t\t}\r\n\t\tswitch ( m_constrItemSID2ENUM.value( group ) )\r\n\t\t{\r\n\t\t\tcase CI_DOOR:\r\n\t\t\t\tclearTileFlag( decPos, TileFlag::TF_DOOR );\r\n\t\t\t\tg->rm()->removeDoor( decPos );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CI_ALARMBELL:\r\n\t\t\t\tg->rm()->removeFurniture( decPos );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CI_LIGHT:\r\n\t\t\t{\r\n\t\t\t\tremoveLight( decPos.toInt() );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase CI_MECHANISM:\r\n\t\t\t\tg->mcm()->uninstallItem( itemID );\r\n\t\t\t\tbreak;\r\n\t\t\tcase CI_FARMUTIL:\r\n\t\t\t\tg->fm()->removeUtil( decPos );\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tTile& tile = getTile( decPos );\r\n\t\tif ( isFloor )\r\n\t\t{\r\n\t\t\t//if( m_constrItemSID2ENUM.value( group ) != CI_MECHANISM )\r\n\t\t\tif ( !constr.value( \"Hidden\" ).toBool() )\r\n\t\t\t{\r\n\t\t\t\ttile.floorType      = FT_NOFLOOR;\r\n\t\t\t\ttile.floorSpriteUID = 0;\r\n\t\t\t\tsetWalkable( decPos, false );\r\n\r\n\t\t\t\tif ( m_creaturePositions.contains( decPos.toInt() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->gm()->forceMoveGnomes( decPos, workPos );\r\n\t\t\t\t}\r\n\t\t\t\tdiscover( decPos.belowOf() );\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttile.wallType      = WT_NOWALL;\r\n\t\t\ttile.wallSpriteUID = 0;\r\n\t\t}\r\n\r\n\t\tif ( constr.value( \"FromParts\" ).toBool() )\r\n\t\t{\r\n\t\t\tfor ( auto vItem : constr.value( \"Items\" ).toList() )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->setConstructed( vItem.toUInt(), false );\r\n\t\t\t\tg->inv()->moveItemToPos( vItem.toUInt(), workPos );\r\n\t\t\t}\r\n\t\t\tg->inv()->destroyObject( itemID );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tg->inv()->setConstructed( itemID, false );\r\n\t\t\tg->inv()->moveItemToPos( itemID, workPos );\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\telse if ( constr.value( \"ConstructionID\" ).toString() == \"Scaffold\" )\r\n\t{\r\n\t\t//if construction above is scaffold\r\n\t\tif ( m_wallConstructions.contains( decPos.aboveOf().toInt() ) )\r\n\t\t{\r\n\t\t\tauto aboveConstr = m_wallConstructions.value( decPos.aboveOf().toInt() );\r\n\t\t\tif ( aboveConstr.value( \"ConstructionID\" ).toString() == \"Scaffold\" )\r\n\t\t\t{\r\n\t\t\t\tdeconstruct( decPos.aboveOf(), workPos, ignoreGravity );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( constr.value( \"ConstructionID\" ).toString().endsWith( \"Fence\" ) )\r\n\t{\r\n\t\tTile& tile         = getTile( decPos );\r\n\t\ttile.wallType      = ( WallType )( WallType::WT_NOWALL );\r\n\t\ttile.wallSpriteUID = 0;\r\n\t\tif ( tile.floorType != ( FloorType )( FloorType::FT_NOFLOOR ) )\r\n\t\t{\r\n\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t}\r\n\t\tupdateFenceSprite( decPos.northOf() );\r\n\t\tupdateFenceSprite( decPos.eastOf() );\r\n\t\tupdateFenceSprite( decPos.southOf() );\r\n\t\tupdateFenceSprite( decPos.westOf() );\r\n\t}\r\n\r\n\tQList<Position> updateCoords;\r\n\tif ( constr.contains( \"Positions\" ) )\r\n\t{\r\n\t\tauto posList = constr.value( \"Positions\" ).toList();\r\n\t\tfor ( int i = 0; i < posList.size(); i += 2 )\r\n\t\t{\r\n\t\t\tbool isWall = ( posList[i].toString() == \"W\" );\r\n\t\t\tPosition pos( posList[i + 1] );\r\n\t\t\tupdateCoords.append( pos );\r\n\r\n\t\t\tif ( isWall )\r\n\t\t\t{\r\n\t\t\t\tTile& tile         = getTile( pos );\r\n\t\t\t\ttile.wallType      = ( WallType )( WallType::WT_NOWALL );\r\n\t\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\t\ttile.wallMaterial  = 0;\r\n\t\t\t\tif ( tile.floorType != ( FloorType )( FloorType::FT_NOFLOOR ) )\r\n\t\t\t\t{\r\n\t\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tm_wallConstructions.remove( pos.toInt() );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tTile& tile          = getTile( pos );\r\n\t\t\t\ttile.floorType      = ( FloorType )( FloorType::FT_NOFLOOR );\r\n\t\t\t\ttile.floorSpriteUID = 0;\r\n\t\t\t\ttile.floorMaterial  = 0;\r\n\t\t\t\tclearTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\r\n\t\t\t\tPositionEntry pe;\r\n\t\t\t\tif ( g->inv()->getObjectsAtPosition( pos, pe ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto i : pe )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->moveItemToPos( i, workPos );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t/*\t\t\t\t\r\n\t\t\t\tif( !ignoreGravity )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->gravity( pos );\r\n\t\t\t\t}\r\n\t\t\t\t*/\r\n\t\t\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t\t{\r\n\t\t\t\t\tPosition tmpPos = pos;\r\n\t\t\t\t\tgetFloorLevelBelow( tmpPos, true );\r\n\t\t\t\t\tTile& tileBelow = getTile( tmpPos );\r\n\t\t\t\t\ttileBelow.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t\t\t\tcheckIndirectSunlightForNeighbors( tmpPos );\r\n\t\t\t\t\tdiscover( tmpPos );\r\n\t\t\t\t\taddToUpdateList( tmpPos );\r\n\t\t\t\t}\r\n\t\t\t\tm_floorConstructions.remove( pos.toInt() );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//Position pos( constr.value( \"Pos\" ) );\r\n\t\tbool isWall = constr.value( \"T\" ).toString() == \"W\";\r\n\t\tupdateCoords.append( decPos );\r\n\t\tTile& tile = getTile( decPos );\r\n\r\n\t\tif ( isWall )\r\n\t\t{\r\n\t\t\ttile.wallType      = ( WallType )( WallType::WT_NOWALL );\r\n\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\tif ( tile.floorType != ( FloorType )( FloorType::FT_NOFLOOR ) )\r\n\t\t\t{\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t}\r\n\t\t\tupdateLightsInRange( decPos );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttile.floorType      = ( FloorType )( FloorType::FT_NOFLOOR );\r\n\t\t\ttile.floorSpriteUID = 0;\r\n\t\t\tclearTileFlag( decPos, TileFlag::TF_WALKABLE );\r\n\r\n\t\t\tPositionEntry pe;\r\n\t\t\tif ( g->inv()->getObjectsAtPosition( decPos, pe ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto i : pe )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->moveItemToPos( i, workPos );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t/*\r\n\t\t\tif( !ignoreGravity )\r\n\t\t\t{\r\n\t\t\t\tg->inv()->gravity( decPos );\r\n\t\t\t}\r\n\t\t\t*/\r\n\r\n\t\t\tif ( m_creaturePositions.contains( decPos.toInt() ) )\r\n\t\t\t{\r\n\t\t\t\tg->gm()->forceMoveGnomes( decPos, workPos );\r\n\t\t\t}\r\n\t\t\tif ( tile.flags & TileFlag::TF_SUNLIGHT )\r\n\t\t\t{\r\n\t\t\t\tPosition tmpPos = decPos;\r\n\t\t\t\tgetFloorLevelBelow( tmpPos, true );\r\n\t\t\t\tTile& tileBelow = getTile( tmpPos );\r\n\t\t\t\ttileBelow.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t\t\tcheckIndirectSunlightForNeighbors( tmpPos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tQVariantList mats  = constr.value( \"Materials\" ).toList();\r\n\tQVariantList items = constr.value( \"Items\" ).toList();\r\n\tint i              = 0;\r\n\tfor ( auto item : items )\r\n\t{\r\n\t\tg->inv()->createItem( workPos, DBH::itemSID( item.toUInt() ), DBH::materialSID( mats[i].toUInt() ) );\r\n\t}\r\n\r\n\tfor ( auto updatePos : updateCoords )\r\n\t{\r\n\t\tm_regionMap.updatePosition( updatePos );\r\n\t\taddToUpdateList( updatePos );\r\n\t}\r\n\treturn true;\r\n}\r\n"
  },
  {
    "path": "src/game/worldgenerator.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"worldgenerator.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/enums.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/position.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturefactory.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/itemhistory.h\"\r\n#include \"../game/newgamesettings.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include <QApplication>\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n\r\nWorldGenerator::WorldGenerator( NewGameSettings* newGameSettings, Game* parent ) :\r\n\tg( parent ),\r\n\tngs( newGameSettings ),\r\n\tQObject(parent)\r\n{\r\n}\r\n\r\nWorldGenerator::~WorldGenerator()\r\n{\r\n}\r\n\r\nWorld* WorldGenerator::generateTopology()\r\n{\r\n\tm_dimX       = ngs->worldSize();\r\n\tm_dimY       = ngs->worldSize();\r\n\tm_dimZ       = ngs->zLevels();\r\n\tGlobal::dimX = ngs->worldSize();\r\n\tGlobal::dimY = ngs->worldSize();\r\n\tGlobal::dimZ = ngs->zLevels();\r\n\r\n\tw = new World( m_dimX, m_dimY, m_dimZ, g );\r\n\r\n\tqDebug() << \"creating world with size\" << m_dimX << m_dimY << m_dimZ;\r\n\r\n\tm_groundLevel = ngs->ground();\r\n\tm_fow         = Global::cfg->get( \"fow\" ).toBool();\r\n\r\n\tauto& world = w->world();\r\n\tworld.resize( m_dimX * m_dimY * m_dimZ, Tile() );\r\n\r\n\tfor ( auto& tile : world )\r\n\t{\r\n\t\ttile.fluidLevel = 0;\r\n\t\ttile.pressure   = 0;\r\n\t}\r\n\r\n\tm_mushroomLevel = m_dimZ - 70;\r\n\r\n\tm_seed = ngs->seed().toInt();\r\n\tm_random.SetSeed( m_seed );\r\n\tm_random.SetFrequency( (FN_DECIMAL)0.02 );\r\n\tm_random.SetFractalOctaves( 1 );\r\n\tm_random.SetFractalLacunarity( 2 );\r\n\tm_random.SetFractalGain( 0.5 );\r\n\tm_random.SetNoiseType( FastNoise::NoiseType::CubicFractal );\r\n\tm_random.SetFractalType( FastNoise::FractalType::Billow );\r\n\r\n\temit signalStatus( \"Create height map.\" );\r\n\tcreateHeightMap( m_dimX, m_dimY );\r\n\tinitMateralVectors();\r\n\r\n\t// resize world and fill stone layers\r\n\temit signalStatus( \"Set stone layers.\" );\r\n\tsetStoneLayers();\r\n\r\n\tif ( ngs->rivers() > 0 )\r\n\t{\r\n\t\tcreateRivers();\r\n\t}\r\n\r\n\tif ( ngs->oceanSize() > 0 )\r\n\t{\r\n\t\temit signalStatus( \"Create ocean front.\" );\r\n\t\tcreateOceanFront();\r\n\t}\r\n\r\n\t// set metal ores and gems\r\n\temit signalStatus( \"Create ore and gem veins.\" );\r\n\tsetMetalsAndGems();\r\n\t// set water and sand floor at water\r\n\temit signalStatus( \"Set water.\" );\r\n\tsetWater();\r\n\r\n\t// set sunlight and grass\r\n\temit signalStatus( \"Init sun light.\" );\r\n\tinitSunLight();\r\n\r\n\temit signalStatus( \"Create ramps.\" );\r\n\tcreateRamps();\r\n\r\n\tif ( !ngs->isPeaceful() )\r\n\t{\r\n\t\t//emit signalStatus( \"Place Lairs.\" );\r\n\t\t//placeLairs();\r\n\t}\r\n\r\n\temit signalStatus( \"Init world.\" );\r\n\tw->init();\r\n\r\n\tdiscoverAll();\r\n\tqDebug() << \"world generator - topology - done\";\r\n\treturn w;\r\n}\r\n\r\nvoid WorldGenerator::addLife()\r\n{\r\n\t// add plants and trees\r\n\temit signalStatus( \"Add plants and trees.\" );\r\n\taddPlantsAndTrees();\r\n\t// add animals\r\n\temit signalStatus( \"Add animals.\" );\r\n\taddAnimals();\r\n\t// add gnomes and starting items\r\n\temit signalStatus( \"Place embark items and gnomes.\" );\r\n\taddGnomesAndStartingItems();\r\n\r\n\tint maxVeinLength = m_dimX / 2;\r\n\r\n\tGameState::kingdomName = ngs->kingdomName();\r\n\r\n\tqDebug() << \"world generator - life - done\";\r\n\r\n\tw->regionMap().initRegions();\r\n}\r\n\r\nvoid WorldGenerator::initMateralVectors()\r\n{\r\n\tm_mats.clear();\r\n\tQList<QString> ids = DB::ids( \"TerrainMaterials\" );\r\n\r\n\tfor ( auto id : ids )\r\n\t{\r\n\t\tQVariantMap row = DB::selectRow( \"TerrainMaterials\", id );\r\n\t\tTerrainMaterial m;\r\n\t\tm.key       = id;\r\n\t\tm.rowid     = DBH::materialUID( id );\r\n\t\tm.type      = row[\"Type\"].toString();\r\n\t\tm.wall      = row[\"WallSprite\"].toString();\r\n\t\tm.shortwall = row[\"ShortWallSprite\"].toString();\r\n\t\tm.floor     = row[\"FloorSprite\"].toString();\r\n\t\tm.lowest    = row[\"Lowest\"].toInt();\r\n\t\tm.highest   = row[\"Highest\"].toInt();\r\n\t\tm_mats.push_back( m );\r\n\t}\r\n\tm_matsInLevel.clear();\r\n\tm_matsInLevel.resize( m_dimZ );\r\n\tTerrainMaterial mat;\r\n\r\n\tfor ( int z = 0; z < m_dimZ; ++z )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_mats.size(); ++i )\r\n\t\t{\r\n\t\t\tint levelUnderGround = z - m_groundLevel;\r\n\t\t\tm_matsInLevel[z]     = i;\r\n\t\t\tmat                  = m_mats[i];\r\n\t\t\tif ( levelUnderGround >= mat.lowest && levelUnderGround <= mat.highest )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::setStoneLayers()\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\tfor ( int z = 0; z < m_dimZ; ++z )\r\n\t{\r\n\t\tif ( timer.elapsed() > 3000 )\r\n\t\t{\r\n\t\t\temit signalStatus( \"Set stone layers...\" + QString::number( (int)( ( 100. / (float)m_dimZ ) * z ) ) + \"%\" );\r\n\t\t\ttimer.restart();\r\n\t\t}\r\n\t\tfillFloor( z, m_mats, m_matsInLevel );\r\n\t\tQCoreApplication::processEvents();\r\n\t}\r\n\r\n\tfor ( int z = 0; z < 7; ++z )\r\n\t{\r\n\t\tif ( timer.elapsed() > 3000 )\r\n\t\t{\r\n\t\t\temit signalStatus( \"Set stone layers...\" + QString::number( (int)( ( 100. / (float)m_dimZ ) * z ) ) + \"%\" );\r\n\t\t\ttimer.restart();\r\n\t\t}\r\n\t\tfillFloorMushroomBiome( z, m_mats, m_matsInLevel );\r\n\t\tQCoreApplication::processEvents();\r\n\t}\r\n}\r\n\r\n// set metal ores and gems\r\nvoid WorldGenerator::setMetalsAndGems()\r\n{\r\n\tQMap<QString, EmbeddedMaterial> embeddeds;\r\n\tQList<QString> eids = DB::ids( \"EmbeddedMaterials\" );\r\n\r\n\tfor ( auto id : eids )\r\n\t{\r\n\t\tQVariantMap row = DB::selectRow( \"EmbeddedMaterials\", id );\r\n\t\tEmbeddedMaterial m;\r\n\t\tm.key     = id;\r\n\t\tm.rowid   = DBH::materialUID( id );\r\n\t\tm.type    = row[\"Type\"].toString();\r\n\t\tm.wall    = row[\"WallSprite\"].toString();\r\n\t\tm.lowest  = row[\"Lowest\"].toInt();\r\n\t\tm.highest = row[\"Highest\"].toInt();\r\n\t\tembeddeds.insert( id, m );\r\n\t}\r\n\r\n\tint maxVeinLength = m_dimX / 4;\r\n\tauto& world       = w->world();\r\n\r\n\tfor ( int z = 0; z < m_groundLevel; ++z )\r\n\t{\r\n\t\tfor ( int i = 0; i < 20; ++i )\r\n\t\t{\r\n\t\t\tstd::vector<Position> pw = perlinWorm( z, i, maxVeinLength );\r\n\r\n\t\t\tif ( !pw.empty() )\r\n\t\t\t{\r\n\t\t\t\tPosition pos     = pw[0];\r\n\t\t\t\tQString embedded = getRandomEmbedded( pos.x, pos.y, pos.z, embeddeds );\r\n\t\t\t\tif ( !embedded.isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tint rowid = DBH::materialUID( embedded );\r\n\t\t\t\t\tfor ( auto pos : pw )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned short spriteUID = g->sf()->createSprite( embeddeds[embedded].wall, { embedded } )->uID;\r\n\r\n\t\t\t\t\t\tsetEmbedded3x3( world, pos, rowid, spriteUID );\r\n\t\t\t\t\t\t//clear3x3( world, pos );\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// set water and sand floor at water\r\nvoid WorldGenerator::setWater()\r\n{\r\n}\r\n// set sunlight and grass\r\nvoid WorldGenerator::initSunLight()\r\n{\r\n\tauto& world       = w->world();\r\n\r\n\tint sandRowid = DBH::materialUID( \"Sand\" );\r\n\tint dirtRowid = DBH::materialUID( \"Dirt\" );\r\n\r\n\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t{\r\n\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t{\r\n\t\t\tPosition pos( x, y, m_dimZ - 1 );\r\n\t\t\tw->getFloorLevelBelow( pos, true );\r\n\r\n\t\t\tTile& tile = world[x + y * m_dimX + pos.z * m_dimX * m_dimY];\r\n\r\n\t\t\tif ( ( tile.flags & TileFlag::TF_WATER ) && tile.floorType == FloorType::FT_SOLIDFLOOR )\r\n\t\t\t{\r\n\t\t\t\ttile.floorMaterial = sandRowid;\r\n\t\t\t\ttile.wallMaterial  = sandRowid;\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\ttile.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t\t\ttile.floorSpriteUID = g->sf()->createSprite( \"RoughFloor\", { \"Sand\" } )->uID;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\ttile.floorType     = FloorType::FT_SOLIDFLOOR;\r\n\t\t\t\ttile.floorMaterial = dirtRowid;\r\n\t\t\t\ttile.wallType      = WallType::WT_NOWALL;\r\n\t\t\t\ttile.wallMaterial  = 0;\r\n\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\r\n\t\t\t\t//tile.flags |= TileFlag::TF_GRASS;\r\n\t\t\t\ttile.flags += TileFlag::TF_SUNLIGHT;\r\n\r\n\t\t\t\tw->createGrass( pos );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tw->initGrassUpdateList();\r\n}\r\n// add plants and trees\r\nvoid WorldGenerator::addPlantsAndTrees()\r\n{\r\n\tQStringList allTrees     = DB::ids( \"Plants\", \"Type\", \"Tree\" );\r\n\tQStringList allMushrooms = DB::ids( \"Plants\", \"Type\", \"Mushroom\" );\r\n\tQStringList largeShrooms;\r\n\tQStringList smallShrooms;\r\n\r\n\tfor ( auto shroom : allMushrooms )\r\n\t{\r\n\t\tif ( DB::select( \"IsLarge\", \"Plants\", shroom ).toBool() )\r\n\t\t{\r\n\t\t\tlargeShrooms.append( shroom );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsmallShrooms.append( shroom );\r\n\t\t}\r\n\t}\r\n\r\n\tQStringList trees;\r\n\r\n\tfor ( auto tree : allTrees )\r\n\t{\r\n\t\tif ( ngs->isChecked( tree ) )\r\n\t\t{\r\n\t\t\ttrees.push_back( tree );\r\n\t\t}\r\n\t}\r\n\r\n\tQStringList allplants = DB::ids( \"Plants\", \"Type\", \"Plant\" );\r\n\tQStringList plants;\r\n\tfor ( auto plant : allplants )\r\n\t{\r\n\t\tif ( DB::select( \"AllowInWild\", \"Plants\", plant ).toBool() && ngs->isChecked( plant ) )\r\n\t\t{\r\n\t\t\tplants.push_back( plant );\r\n\t\t}\r\n\t}\r\n\r\n\tint x = m_dimX / 2;\r\n\tint y = m_dimY / 2;\r\n\r\n\tint treeDensity      = ngs->treeDensity();\r\n\tint plantDensity     = ngs->plantDensity();\r\n\tint startingZoneSize = ngs->startZone();\r\n\r\n\tbool shroomRejected = false;\r\n\r\n\tif ( treeDensity > 0 )\r\n\t{\r\n\t\ttreeDensity = 101 - treeDensity;\r\n\t\tfor ( int x_ = 3; x_ < m_dimX - 4; ++x_ )\r\n\t\t{\r\n\t\t\tfor ( int y_ = 3; y_ < m_dimY - 4; ++y_ )\r\n\t\t\t{\r\n\t\t\t\tPosition pos( x_, y_, m_mushroomLevel + 5 );\r\n\t\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\t\tint random = rand();\r\n\t\t\t\tif ( random % treeDensity == 0 || shroomRejected )\r\n\t\t\t\t{\r\n\t\t\t\t\tint ra = rand() % largeShrooms.size();\r\n\t\t\t\t\tif ( w->getTile( pos ).wallType == WallType::WT_NOWALL && Plant::testLayoutMulti( largeShrooms[ra], pos, g ) && !( w->getTileFlag( pos ) & TileFlag::TF_WATER ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tw->plantMushroom( pos, largeShrooms[ra], true );\r\n\t\t\t\t\t\tshroomRejected = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tshroomRejected = 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\tfor ( int x_ = 3; x_ < m_dimX - 4; ++x_ )\r\n\t\t{\r\n\t\t\tfor ( int y_ = 3; y_ < m_dimY - 4; ++y_ )\r\n\t\t\t{\r\n\t\t\t\tPosition pos( x_, y_, m_mushroomLevel + 5 );\r\n\t\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\t\tint random = rand();\r\n\t\t\t\tif ( random % treeDensity == 0 || shroomRejected )\r\n\t\t\t\t{\r\n\t\t\t\t\tint ra = rand() % smallShrooms.size();\r\n\t\t\t\t\tif ( w->getTile( pos ).wallType == WallType::WT_NOWALL && w->noShroom( pos, 2, 2 ) && !( w->getTileFlag( pos ) & TileFlag::TF_WATER ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tw->plantMushroom( pos, smallShrooms[ra], true );\r\n\t\t\t\t\t\tshroomRejected = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tshroomRejected = 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\tbool treeRejected = false;\r\n\r\n\tif ( treeDensity > 0 )\r\n\t{\r\n\t\tqDebug() << \"tree density \" << treeDensity;\r\n\t\t//treeDensity = 101 - treeDensity;\r\n\r\n\t\tfor ( int x_ = 2; x_ < m_dimX - 2; ++x_ )\r\n\t\t{\r\n\t\t\tfor ( int y_ = 2; y_ < m_dimY - 2; ++y_ )\r\n\t\t\t{\r\n\t\t\t\tif ( sqrt( ( x_ - x ) * ( x_ - x ) + ( y_ - y ) * ( y_ - y ) ) < startingZoneSize )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tPosition pos( x_, y_, m_dimZ - 2 );\r\n\t\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\t\tint random = rand();\r\n\t\t\t\tif ( random % treeDensity == 0 || treeRejected )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( trees.size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint ra = rand() % trees.size();\r\n\t\t\t\t\t\tif ( w->getTile( pos ).wallType == WallType::WT_NOWALL && Plant::testLayoutMulti( trees[ra], pos, g ) && !( w->getTileFlag( pos ) & TileFlag::TF_WATER ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tw->plantTree( pos, trees[ra], true );\r\n\t\t\t\t\t\t\ttreeRejected = false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttreeRejected = 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\tif ( plantDensity > 0 )\r\n\t{\r\n\t\tplantDensity = 101 - plantDensity;\r\n\t\tfor ( int x_ = 1; x_ < m_dimX - 1; ++x_ )\r\n\t\t{\r\n\t\t\tfor ( int y_ = 1; y_ < m_dimY - 1; ++y_ )\r\n\t\t\t{\r\n\t\t\t\tif ( sqrt( ( x_ - x ) * ( x_ - x ) + ( y_ - y ) * ( y_ - y ) ) < startingZoneSize )\r\n\t\t\t\t{\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tPosition pos( x_, y_, m_dimZ - 2 );\r\n\t\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\t\tint random = rand();\r\n\t\t\t\tif ( random % plantDensity == 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( plants.size() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint ra = rand() % plants.size();\r\n\t\t\t\t\t\tif ( w->getTile( pos ).wallType == WallType::WT_NOWALL && w->noTree( pos, 0, 0 ) && !( w->getTileFlag( pos ) & TileFlag::TF_WATER ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tPlant plant( pos, plants[ra], true, g );\r\n\t\t\t\t\t\t\tw->plants().insert( plant.getPos().toInt(), plant );\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// add animals\r\nvoid WorldGenerator::addAnimals()\r\n{\r\n\tint numAnimals = ngs->numWildAnimals();\r\n\tQStringList keys;\r\n\tQStringList waterKeys;\r\n\tQStringList mushroomKeys;\r\n\tauto ids = DB::ids( \"Animals\" );\r\n\tfor ( auto id : ids )\r\n\t{\r\n\t\tif ( ngs->isChecked( id ) )\r\n\t\t{\r\n\t\t\tif ( DB::select( \"Aquatic\", \"Animals\", id ).toBool() )\r\n\t\t\t{\r\n\t\t\t\twaterKeys.push_back( id );\r\n\t\t\t}\r\n\t\t\t/*\r\n\t\t\telse if( ta.select( key, \"Biome\" ).toString() == \"Mushroom\" )\r\n\t\t\t{\r\n\t\t\t\tmushroomKeys.push_back( key );\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( DB::select( \"Biome\", \"Animals\", id ).toString() != \"Mushroom\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tkeys.push_back( id );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tfor ( auto id : ids )\r\n\t{\r\n\t\tif ( DB::select( \"Biome\", \"Animals\", id ).toString() == \"Mushroom\" )\r\n\t\t{\r\n\t\t\tmushroomKeys.push_back( id );\r\n\t\t}\r\n\t}\r\n\r\n\tint numTypes      = keys.size();\r\n\tint numWaterTypes = waterKeys.size();\r\n\r\n\tint x_               = m_dimX / 2;\r\n\tint y_               = m_dimY / 2;\r\n\tint startingZoneSize = ngs->startZone();\r\n\r\n\tQMap<QString, int> countPerType;\r\n\r\n\tif ( numTypes > 0 )\r\n\t{\r\n\t\tint i         = 0;\r\n\t\tint numWolves = 0;\r\n\t\tint numFoxes  = 0;\r\n\t\twhile ( i < numAnimals )\r\n\t\t{\r\n\t\t\tint x = qMax( 2, ( rand() % m_dimX ) - 2 );\r\n\t\t\tint y = qMax( 2, ( rand() % m_dimY ) - 2 );\r\n\r\n\t\t\tPosition pos( x, y, m_dimZ - 2 );\r\n\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\tif ( !w->isWalkable( pos ) || ( sqrt( ( x_ - x ) * ( x_ - x ) + ( y_ - y ) * ( y_ - y ) ) < startingZoneSize ) )\r\n\t\t\t{\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( ( w->getTileFlag( pos ) & TileFlag::TF_WATER ) && w->fluidLevel( pos ) > 6 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( numWaterTypes > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tint randomType = rand() % ( numWaterTypes );\r\n\t\t\t\t\t\tQString type   = waterKeys[randomType];\r\n\r\n\t\t\t\t\t\tint count = countPerType.value( type );\r\n\t\t\t\t\t\tif ( count < ngs->globalMaxPerType() && count < ngs->maxAnimalsPerType( type ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, type, pos, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE, true, false );\r\n\t\t\t\t\t\t\tcountPerType.insert( type, count + 1 );\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\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tint randomType = rand() % ( numTypes );\r\n\t\t\t\t\tQString type   = keys[randomType];\r\n\r\n\t\t\t\t\tint count = countPerType.value( type );\r\n\r\n\t\t\t\t\tif ( count < ngs->globalMaxPerType() && count < ngs->maxAnimalsPerType( type ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, type, pos, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE, true, false );\r\n\t\t\t\t\t\tcountPerType.insert( type, count + 1 );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t++i;\r\n\t\t}\r\n\t}\r\n\r\n\tfor ( int x_ = 3; x_ < m_dimX - 3; ++x_ )\r\n\t{\r\n\t\tfor ( int y_ = 3; y_ < m_dimY - 3; ++y_ )\r\n\t\t{\r\n\t\t\tPosition pos( x_, y_, m_mushroomLevel + 5 );\r\n\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\tint random = rand();\r\n\t\t\tif ( random % 100 > 96 )\r\n\t\t\t{\r\n\t\t\t\tif ( w->isWalkable( pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tint randomType = rand() % ( mushroomKeys.size() );\r\n\t\t\t\t\tQString type   = mushroomKeys[randomType];\r\n\r\n\t\t\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, type, pos, rand() % 2 == 0 ? Gender::MALE : Gender::FEMALE, true, false );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t/*\r\n\tfor( int i = 0; i < 35000; ++i )\r\n\t{\r\n\t\tg->cm()->addAnimal( \"Badger\", Position( 20, 20, 100), Gender::MALE, true, false );\r\n\t}\r\n\t*/\r\n}\r\n// add gnomes and starting items\r\nvoid WorldGenerator::addGnomesAndStartingItems()\r\n{\r\n\tint num = ngs->numGnomes();\r\n\r\n\tQVector<Position> offsets;\r\n\toffsets.push_back( Position( 0, 0, 0 ) );\r\n\toffsets.push_back( Position( -1, 0, 0 ) );\r\n\toffsets.push_back( Position( 1, 0, 0 ) );\r\n\toffsets.push_back( Position( -1, -1, 0 ) );\r\n\toffsets.push_back( Position( 0, -1, 0 ) );\r\n\toffsets.push_back( Position( 1, -1, 0 ) );\r\n\toffsets.push_back( Position( -1, 1, 0 ) );\r\n\toffsets.push_back( Position( 0, 1, 0 ) );\r\n\toffsets.push_back( Position( 1, 1, 0 ) );\r\n\r\n\tint x = m_dimX / 2;\r\n\tint y = m_dimY / 2;\r\n\tPosition pos( x, y, m_dimZ - 2 );\r\n\r\n\tbool found = false;\r\n\tint size   = 0;\r\n\twhile ( !found && size < m_dimX / 2 - 5 )\r\n\t{\r\n\t\tfor ( int x = -size; x < size; ++x )\r\n\t\t{\r\n\t\t\tfor ( int y = -size; y < size; ++y )\r\n\t\t\t{\r\n\t\t\t\tfound             = true;\r\n\t\t\t\tPosition checkPos = pos;\r\n\t\t\t\tcheckPos.x        = pos.x + x;\r\n\t\t\t\tcheckPos.y        = pos.y + y;\r\n\t\t\t\tfor ( int i = 0; i < 9; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tPosition thisPos( checkPos + offsets[i % 9] );\r\n\t\t\t\t\tw->getFloorLevelBelow( thisPos, false );\r\n\t\t\t\t\tTile& tile = w->getTile( thisPos );\r\n\t\t\t\t\tif ( tile.fluidLevel > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfound = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif ( found )\r\n\t\t\t\t{\r\n\t\t\t\t\tpos = checkPos;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( found )\r\n\t\t\t{\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsize += 1;\r\n\t}\r\n\r\n\tpos.z = m_dimZ - 2;\r\n\t//w->getFloorLevelBelow( pos, false );\r\n\tGameState::origin = pos;\r\n\r\n\tfor ( int i = 0; i < num; ++i )\r\n\t{\r\n\t\tPosition thisPos( pos + offsets[i % 6] );\r\n\t\tw->getFloorLevelBelow( thisPos, false );\r\n\t\tg->gm()->addGnome( thisPos );\r\n\t\tGameState::viewLevel = thisPos.z + 5;\r\n\t}\r\n\r\n\tint id   = 0;\r\n\tauto sal = ngs->startingAnimals();\r\n\r\n\tfor ( auto sa : sal )\r\n\t{\r\n\t\tint amount = sa.amount;\r\n\t\tPosition thisPos( pos + offsets[( id % 3 ) + 6] );\r\n\t\tw->getFloorLevelBelow( thisPos, false );\r\n\r\n\t\tfor ( int i = 0; i < amount; ++i )\r\n\t\t{\r\n\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, sa.type, thisPos, sa.gender == \"Male\" ? Gender::MALE : Gender::FEMALE, true, true );\r\n\t\t}\r\n\t}\r\n\r\n\tauto sil = ngs->startingItems();\r\n\tfor ( auto si : sil )\r\n\t{\r\n\t\tif ( !si.mat2.isEmpty() ) //( type == \"CombinedItem\" )\r\n\t\t{\r\n\t\t\t//qDebug() << \"create combined item \" << entry.value( \"ItemID\" ).toString() << entry.value( \"Components\" );\r\n\t\t\tint amount = si.amount;\r\n\t\t\tPosition thisPos( pos + offsets[( id % 3 ) + 6] );\r\n\t\t\tw->getFloorLevelBelow( thisPos, false );\r\n\r\n\t\t\tQVariantMap row = DB::selectRow( \"Items\", si.itemSID );\r\n\r\n\t\t\tif ( DB::numRows( \"Items_Components\", si.itemSID ) > 1 )\r\n\t\t\t{\r\n\t\t\t\tauto comps = DB::selectRows( \"Items_Components\", si.itemSID );\r\n\r\n\t\t\t\tQString itemSID1 = comps.first().value( \"ItemID\" ).toString();\r\n\t\t\t\tQString itemSID2 = comps.last().value( \"ItemID\" ).toString();\r\n\r\n\t\t\t\tfor ( int i = 0; i < amount; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tQList<unsigned int> newComponents;\r\n\r\n\t\t\t\t\tnewComponents.append( g->inv()->createItem( pos, itemSID1, si.mat1 ) );\r\n\t\t\t\t\tnewComponents.append( g->inv()->createItem( pos, itemSID2, si.mat2 ) );\r\n\r\n\t\t\t\t\tg->inv()->createItem( thisPos, si.itemSID, newComponents );\r\n\r\n\t\t\t\t\tfor ( auto vItem : newComponents )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tg->inv()->destroyObject( vItem );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t//qDebug() << \"create combined item \" << entry.value( \"ItemID\" ).toString() << \" done\";\r\n\t\t}\r\n\r\n\t\telse\r\n\t\t{\r\n\t\t\tint amount        = si.amount;\r\n\t\t\tQString container = DB::select( \"AllowedContainers\", \"Items\", si.itemSID ).toString();\r\n\t\t\tPosition thisPos( pos + offsets[( id % 3 ) + 6] );\r\n\t\t\tw->getFloorLevelBelow( thisPos, false );\r\n\t\t\t/*\r\n\t\t\tif( !container.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tint capacity = DB::select( \"Capacity\", \"Containers\", container ).toInt();\r\n\r\n\t\t\t\twhile( amount > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tunsigned int containerUID = g->inv()->createItem( thisPos, container, getRandomMaterial( container ) );\r\n\t\t\t\t\t//unsigned int containerUID = g->inv()->createItem( thisPos, container, \"Birch\" );\r\n\t\t\t\t\tfor( int i = 0; i < qMin( amount, capacity ); ++i )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\tunsigned int itemInContainer = g->inv()->createItem( thisPos, entry.value( \"ItemID\" ).toString(), entry.value( \"MaterialID\" ).toString() );\r\n\t\t\t\t\t\tg->inv()->putItemInContainer( itemInContainer, containerUID );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tamount -= capacity;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse*/\r\n\t\t\t{\r\n\t\t\t\tfor ( int i = 0; i < amount; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tg->inv()->createItem( thisPos, si.itemSID, si.mat1 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t++id;\r\n\t}\r\n\tg->inv()->itemHistory()->finishStart();\r\n}\r\n\r\nQString WorldGenerator::getRandomMaterial( QString itemSID )\r\n{\r\n\tQVariantMap row = DB::selectRow( \"Items\", itemSID );\r\n\r\n\tQStringList out;\r\n\r\n\tif ( !row.value( \"AllowedMaterials\" ).toString().isEmpty() )\r\n\t{\r\n\t\tfor ( auto mat : row.value( \"AllowedMaterials\" ).toString().split( \"|\" ) )\r\n\t\t{\r\n\t\t\tout.append( mat );\r\n\t\t}\r\n\t}\r\n\tif ( !row.value( \"AllowedMaterialTypes\" ).toString().isEmpty() )\r\n\t{\r\n\t\tfor ( auto type : row.value( \"AllowedMaterialTypes\" ).toString().split( \"|\" ) )\r\n\t\t{\r\n\t\t\tfor ( auto mat : DB::ids( \"Materials\", \"Type\", type ) )\r\n\t\t\t{\r\n\t\t\t\tout.append( mat );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( out.size() )\r\n\t{\r\n\t\treturn out[rand() % out.size()];\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"None\";\r\n\t}\r\n}\r\n\r\n// heightmap values = -1 to 1\r\nvoid WorldGenerator::createHeightMap( int dimX, int dimY )\r\n{\r\n\tm_heightMap.resize( dimX * dimY * 4 );\r\n\tm_heightMap2.resize( dimX * dimY * 4 );\r\n\r\n\tfloat flatness = ngs->flatness();\r\n\r\n\tfor ( int x = 0; x < dimX * 2; ++x )\r\n\t{\r\n\t\tfor ( int y = 0; y < dimY * 2; ++y )\r\n\t\t{\r\n\t\t\tfloat value = m_random.GetPerlin( x, y );\r\n\t\t\t//m_min = qMin( value, m_min );\r\n\t\t\t//m_max = qMax( value, m_max );\r\n\t\t\tm_heightMap[x + y * dimX]  = value * flatness;\r\n\t\t\tm_heightMap2[x + y * dimX] = value;\r\n\t\t}\r\n\t}\r\n\t//qDebug() << \"heightMap min: \" << m_min << \"heightMap max: \" << m_max;\r\n}\r\n\r\nvoid WorldGenerator::fillFloorMushroomBiome( int zz, QVector<TerrainMaterial>& mats, QVector<int>& matsinLevel )\r\n{\r\n\tint baseLevel = m_mushroomLevel;\r\n\r\n\tint z = zz + baseLevel;\r\n\r\n\tauto& world = w->world();\r\n\r\n\tTerrainMaterial mat;\r\n\r\n\tunsigned short dirtMat = DBH::materialUID( \"Dirt\" );\r\n\tauto dirtSprite        = g->sf()->createSprite( \"MushroomGrassWithDetail\", { \"Grass\", \"None\" } )->uID;\r\n\r\n\tfor ( int y = 3; y < m_dimY - 3; ++y )\r\n\t{\r\n\t\tfor ( int x = 3; x < m_dimX - 3; ++x )\r\n\t\t{\r\n\t\t\tTile& tile          = world[x + y * m_dimX + z * m_dimX * m_dimY];\r\n\t\t\ttile.floorType      = FloorType::FT_NOFLOOR;\r\n\t\t\ttile.floorMaterial  = 0;\r\n\t\t\ttile.wallType       = WallType::WT_NOWALL;\r\n\t\t\ttile.wallMaterial   = 0;\r\n\t\t\ttile.floorSpriteUID = 0;\r\n\t\t\ttile.wallSpriteUID  = 0;\r\n\t\t\ttile.flags          = TileFlag::TF_NONE;\r\n\r\n\t\t\tif ( x == 0 || y == 0 || x == m_dimX - 1 || y == m_dimY - 1 )\r\n\t\t\t{\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//if( m_random.GetPerlinFractal( x, y, z ) > 0.00001 )\r\n\t\t\t\t//if( fBm( x, y, z ) )\r\n\t\t\t\tif ( zz - ( m_heightMap[x + m_dimX + y * m_dimX * 2] * 3. ) < 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tmat                = mats[matsinLevel[qMin( m_dimZ - 1, qMax( 0, z - m_heightMap[x + m_dimX + y * m_dimX * 2] ) )]];\r\n\t\t\t\t\tunsigned short key = mat.rowid;\r\n\r\n\t\t\t\t\ttile.floorType     = FloorType::FT_SOLIDFLOOR;\r\n\t\t\t\t\ttile.floorMaterial = key;\r\n\t\t\t\t\tif ( mat.floorSprite )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.floorSpriteUID = mat.floorSprite;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.floorSpriteUID                                                               = g->sf()->createSprite( mat.floor, { mat.key } )->uID;\r\n\t\t\t\t\t\tmat.floorSprite                                                                   = tile.floorSpriteUID;\r\n\t\t\t\t\t\tmats[matsinLevel[qMin( m_dimZ - 1, qMax( 0, z - m_heightMap[x + y * m_dimX] ) )]] = mat;\r\n\t\t\t\t\t}\r\n\t\t\t\t\ttile.wallType     = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_ROUGH | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING );\r\n\t\t\t\t\ttile.wallMaterial = key;\r\n\t\t\t\t\tif ( mat.wallSprite )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.wallSpriteUID = mat.wallSprite;\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.wallSpriteUID                                                                = g->sf()->createSprite( mat.wall, { mat.key } )->uID;\r\n\t\t\t\t\t\tmat.wallSprite                                                                    = tile.wallSpriteUID;\r\n\t\t\t\t\t\tmats[matsinLevel[qMin( m_dimZ - 1, qMax( 0, z - m_heightMap[x + y * m_dimX] ) )]] = mat;\r\n\t\t\t\t\t\tg->sf()->createSprite( mat.shortwall, { mat.key } )->uID;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( m_fow )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.flags += TileFlag::TF_UNDISCOVERED;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tTile& tileBelow = world[x + y * m_dimX + ( z - 1 ) * m_dimX * m_dimY];\r\n\t\t\t\t\tif ( tileBelow.wallType & WallType::WT_ROUGH )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.floorType      = FloorType::FT_SOLIDFLOOR;\r\n\t\t\t\t\t\ttile.floorMaterial  = dirtMat;\r\n\t\t\t\t\t\ttile.floorSpriteUID = g->sf()->createSprite( \"MushroomGrassWithDetail\", { \"Grass\", \"None\" } )->uID;\r\n\t\t\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\t\t\t//tile.flags |= TileFlag::TF_GRASS;\r\n\t\t\t\t\t\ttile.flags += TileFlag::TF_BIOME_MUSHROOM;\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 WorldGenerator::fillFloor( int z, QVector<TerrainMaterial>& mats, QVector<int>& matsinLevel )\r\n{\r\n\tauto& world = w->world();\r\n\r\n\tTerrainMaterial mat;\r\n\r\n\tfor ( int y = 0; y < m_dimY; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < m_dimX; ++x )\r\n\t\t{\r\n\t\t\tmat                = mats[matsinLevel[qMin( m_dimZ - 1, qMax( 0, z - m_heightMap[x + y * m_dimX] ) )]];\r\n\t\t\tunsigned short key = mat.rowid;\r\n\r\n\t\t\tTile& tile          = world[x + y * m_dimX + z * m_dimX * m_dimY];\r\n\t\t\ttile.floorType      = FloorType::FT_NOFLOOR;\r\n\t\t\ttile.floorMaterial  = 0;\r\n\t\t\ttile.wallType       = WallType::WT_NOWALL;\r\n\t\t\ttile.wallMaterial   = 0;\r\n\t\t\ttile.floorSpriteUID = 0;\r\n\t\t\ttile.wallSpriteUID  = 0;\r\n\t\t\ttile.flags          = TileFlag::TF_NONE;\r\n\r\n\t\t\tif ( x == 0 || y == 0 || x == m_dimX - 1 || y == m_dimY - 1 )\r\n\t\t\t{\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t//if( m_random.GetPerlinFractal( x, y, z ) > 0.00001 )\r\n\t\t\t\t//if( fBm( x, y, z ) )\r\n\t\t\t\tif ( z - m_heightMap[x + y * m_dimX] > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( mat.key != \"Air\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttile.floorType     = FloorType::FT_SOLIDFLOOR;\r\n\t\t\t\t\t\ttile.floorMaterial = key;\r\n\t\t\t\t\t\tif ( mat.floorSprite )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttile.floorSpriteUID = mat.floorSprite;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttile.floorSpriteUID                                                               = g->sf()->createSprite( mat.floor, { mat.key } )->uID;\r\n\t\t\t\t\t\t\tmat.floorSprite                                                                   = tile.floorSpriteUID;\r\n\t\t\t\t\t\t\tmats[matsinLevel[qMin( m_dimZ - 1, qMax( 0, z - m_heightMap[x + y * m_dimX] ) )]] = mat;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\ttile.wallType     = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_ROUGH | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING );\r\n\t\t\t\t\t\ttile.wallMaterial = key;\r\n\t\t\t\t\t\tif ( mat.wallSprite )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttile.wallSpriteUID = mat.wallSprite;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttile.wallSpriteUID                                                                = g->sf()->createSprite( mat.wall, { mat.key } )->uID;\r\n\t\t\t\t\t\t\tmat.wallSprite                                                                    = tile.wallSpriteUID;\r\n\t\t\t\t\t\t\tmats[matsinLevel[qMin( m_dimZ - 1, qMax( 0, z - m_heightMap[x + y * m_dimX] ) )]] = mat;\r\n\t\t\t\t\t\t\tg->sf()->createSprite( mat.shortwall, { mat.key } )->uID;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( m_fow )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttile.flags += TileFlag::TF_UNDISCOVERED;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tTile& tileBelow = world[x + y * m_dimX + ( z - 1 ) * m_dimX * m_dimY];\r\n\t\t\t\t\t\tif ( tileBelow.wallType & WallType::WT_ROUGH )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttile.floorType      = FloorType::FT_SOLIDFLOOR;\r\n\t\t\t\t\t\t\ttile.floorMaterial  = tileBelow.floorMaterial;\r\n\t\t\t\t\t\t\ttile.floorSpriteUID = tileBelow.floorSpriteUID;\r\n\t\t\t\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\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\r\nvoid WorldGenerator::discoverAll()\r\n{\r\n\tfor ( int z = m_dimZ - 2; z > 0; --z )\r\n\t{\r\n\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tif ( !( w->wallType( Position( x, y, z ) ) & WT_SOLIDWALL ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tw->discover( x, y, z );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::createRamps()\r\n{\r\n\tfor ( int z = m_dimZ - 2; z > 0; --z )\r\n\t{\r\n\t\tcreateRamp( z );\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::createRamp( int z )\r\n{\r\n\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t{\r\n\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t{\r\n\t\t\tw->createRamp( x, y, z );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool WorldGenerator::fBm( int x, int y, int z )\r\n{\r\n\tint fixedZ = qMin( m_dimZ - 1, qMax( 0, (int)z - m_heightMap[x + y * m_dimX] ) );\r\n\r\n\tif ( z > m_groundLevel - 6 && z < m_groundLevel )\r\n\t\treturn true;\r\n\r\n\tif ( z < m_groundLevel - 5 )\r\n\t{\r\n\t\treturn true;\r\n\r\n\t\t//float noise = abs( m_random.GetCubic( x, y, z ) ) * 5 ;\r\n\t\t//float compare = 0.1;\r\n\t\t//return ( noise > compare );\r\n\t}\r\n\telse if ( z < m_dimZ - 10 )\r\n\t{\r\n\t\treturn m_heightMap[x + y * m_dimX] > ( z - 98 );\r\n\t}\r\n\r\n\treturn false;\r\n}\r\n\r\nstd::vector<Position> WorldGenerator::perlinWorm( int z, int num, int maxLength )\r\n{\r\n\tstd::vector<Position> out;\r\n\r\n\tfloat noiseX = perlinRandWhiteNoise( z, num );\r\n\tfloat noiseY = perlinRandWhiteNoise( num, z );\r\n\r\n\tint x = ( m_dimX * noiseX ) - 1;\r\n\tint y = ( m_dimY * noiseY ) - 1;\r\n\r\n\tif ( x > 1 && x < m_dimX - 2 && y > 1 && y < m_dimY - 2 )\r\n\t{\r\n\t\tout.push_back( Position( x, y, z ) );\r\n\t}\r\n\r\n\tfloat noiseLength = perlinRandWhiteNoise( x, y );\r\n\tint length        = noiseLength * maxLength;\r\n\r\n\t// init direction\r\n\tint dir = qMax( 0, qMin( int( perlinRandWhiteNoise( x * 10, y * 10 ) * 9 ), 8 ) );\r\n\r\n\tfor ( int i = 0; i < length; ++i )\r\n\t{\r\n\t\t// do we change dir?\r\n\t\tif ( perlinRandWhiteNoise( x * i, y * i ) > 0.95 )\r\n\t\t{\r\n\t\t\t//if yes\r\n\t\t\tfloat rand    = perlinRandWhiteNoise( x * i * 2, y * i * 2 );\r\n\t\t\tint dirChange = round( rand );\r\n\t\t\tdir += dirChange;\r\n\t\t}\r\n\r\n\t\tif ( dir < 0 )\r\n\t\t\tdir = 7;\r\n\t\tif ( dir > 7 )\r\n\t\t\tdir = 0;\r\n\t\tswitch ( dir )\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tx -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tx -= 1;\r\n\t\t\t\ty -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\ty -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tx += 1;\r\n\t\t\t\ty -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 4:\r\n\t\t\t\tx += 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 5:\r\n\t\t\t\tx += 1;\r\n\t\t\t\ty += 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 6:\r\n\t\t\t\ty += 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 7:\r\n\t\t\t\tx -= 1;\r\n\t\t\t\ty += 1;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif ( x > 1 && x < m_dimX - 2 && y > 1 && y < m_dimY - 2 )\r\n\t\t{\r\n\t\t\tout.push_back( Position( x, y, z ) );\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nfloat WorldGenerator::perlinRandWhiteNoise( int x, int y, int z )\r\n{\r\n\tFastNoise fn;\r\n\tfn.SetSeed( m_seed );\r\n\tfn.SetFrequency( (FN_DECIMAL)0.02 );\r\n\tfn.SetNoiseType( FastNoise::NoiseType::WhiteNoise );\r\n\r\n\tif ( z == -1 )\r\n\t{\r\n\t\treturn ( fn.GetNoise( x, y ) + 1.0 ) / 2.;\r\n\t}\r\n\treturn ( fn.GetNoise( x, y, z ) + 1.0 ) / 2.;\r\n}\r\n\r\nvoid WorldGenerator::clear3x3( std::vector<Tile>& world, Position& pos )\r\n{\r\n\tfor ( int x = pos.x - 1; x < pos.x + 2; ++x )\r\n\t{\r\n\t\tfor ( int y = pos.y - 1; y < pos.y + 2; ++y )\r\n\t\t{\r\n\t\t\tTile& tile         = world[x + y * m_dimX + pos.z * m_dimX * m_dimY];\r\n\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\ttile.flags         = TileFlag::TF_WALKABLE;\r\n\t\t\ttile.wallType      = WallType::WT_NOWALL;\r\n\t\t\ttile.wallMaterial  = 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::setEmbedded3x3( std::vector<Tile>& world, Position& pos, unsigned short embeddedMaterial, unsigned short spriteID )\r\n{\r\n\t// TODO changed it to 2x2\r\n\tfor ( int x = pos.x - 1; x < pos.x + 1; ++x )\r\n\t{\r\n\t\tfor ( int y = pos.y - 1; y < pos.y + 1; ++y )\r\n\t\t{\r\n\t\t\tTile& tile = world[x + y * m_dimX + pos.z * m_dimX * m_dimY];\r\n\r\n\t\t\tif ( tile.wallType & WallType::WT_SOLIDWALL )\r\n\t\t\t{\r\n\t\t\t\ttile.embeddedMaterial = embeddedMaterial;\r\n\t\t\t\ttile.itemSpriteUID    = spriteID;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQString WorldGenerator::getRandomEmbedded( int x, int y, int z, QMap<QString, EmbeddedMaterial>& em )\r\n{\r\n\tQStringList possibles;\r\n\tfor ( auto key : em.keys() )\r\n\t{\r\n\t\tauto e = em.value( key );\r\n\t\tint zz = z - ngs->ground() + m_heightMap[x + y * m_dimX];\r\n\t\tif ( zz >= e.lowest && zz <= e.highest )\r\n\t\t{\r\n\t\t\tpossibles.push_back( e.key );\r\n\t\t}\r\n\t}\r\n\tif ( possibles.isEmpty() )\r\n\t{\r\n\t\treturn \"\";\r\n\t}\r\n\r\n\tint index = qMax( 0, qMin( (int)( perlinRandWhiteNoise( x, y ) * ( possibles.size() + 1 ) ), possibles.size() - 1 ) );\r\n\treturn possibles[index];\r\n}\r\n\r\nvoid WorldGenerator::createOceanFront()\r\n{\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\r\n\tauto& world = w->world();\r\n\r\n\tint size = ngs->oceanSize();\r\n\r\n\tint edge = rand() % 4;\r\n\r\n\tint xStart = 1;\r\n\tint yStart = 1;\r\n\tint maxX   = m_dimX - 2;\r\n\tint maxY   = m_dimY - 2;\r\n\tint xAdd   = 1;\r\n\tint yAdd   = 1;\r\n\r\n\tint sandRowID = DBH::materialUID( \"Sand\" );\r\n\r\n\tQVector<int> sizes;\r\n\tfor ( int i = 0; i < m_dimX; ++i )\r\n\t{\r\n\t\tsizes.push_back( size + ( m_heightMap2[i + 20 * m_dimX] * size ) );\r\n\t}\r\n\r\n\tswitch ( edge )\r\n\t{\r\n\t\tcase 0:\r\n\t\t{\r\n\t\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t\t{\r\n\t\t\t\tint ySize = sizes[y];\r\n\t\t\t\tfor ( int i = 0; i < ySize; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint x = xStart + i;\r\n\t\t\t\t\tdecreaseHeight( x, y, qMin( 10, ySize - i ) );\r\n\t\t\t\t\tsetSandFloor( x, y, sandRowID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tint z = 99; //getLowestZonXLine( xStart + size );\r\n\r\n\t\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t\t{\r\n\t\t\t\tint ySize = sizes[y];\r\n\t\t\t\tfor ( int i = 0; i < ySize; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint x = xStart + i;\r\n\t\t\t\t\tfillWater( x, y, z );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 1:\r\n\t\t{\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tsize = sizes[x];\r\n\t\t\t\tfor ( int i = 0; i < size; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint y = yStart + i;\r\n\t\t\t\t\tdecreaseHeight( x, y, qMin( 10, size - i ) );\r\n\t\t\t\t\tsetSandFloor( x, y, sandRowID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tint z = 99; //getLowestZonYLine( yStart + size );\r\n\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tsize = sizes[x];\r\n\t\t\t\tfor ( int i = 0; i < size; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint y = yStart + i;\r\n\t\t\t\t\tfillWater( x, y, z );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 2:\r\n\t\t{\r\n\t\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t\t{\r\n\t\t\t\tsize = sizes[y];\r\n\t\t\t\tfor ( int i = 0; i < size; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint x = maxX - i;\r\n\t\t\t\t\tdecreaseHeight( x, y, qMin( 10, size - i ) );\r\n\t\t\t\t\tsetSandFloor( x, y, sandRowID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tint z = 99; // getLowestZonXLine( maxX - size );\r\n\r\n\t\t\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t\t\t{\r\n\t\t\t\tsize = sizes[y];\r\n\t\t\t\tfor ( int i = 0; i < size; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint x = maxX - i;\r\n\t\t\t\t\tfillWater( x, y, z );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tcase 3:\r\n\t\t{\r\n\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tsize = sizes[x];\r\n\t\t\t\tfor ( int i = 0; i < size; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint y = maxY - i;\r\n\t\t\t\t\tdecreaseHeight( x, y, qMin( 10, size - i ) );\r\n\t\t\t\t\tsetSandFloor( x, y, sandRowID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tint z = 99; //getLowestZonYLine( maxY - size );\r\n\r\n\t\t\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t\t\t{\r\n\t\t\t\tsize = sizes[x];\r\n\t\t\t\tfor ( int i = 0; i < size; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tint y = maxY - i;\r\n\t\t\t\t\tfillWater( x, y, z );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::decreaseHeight( int x, int y, int diff )\r\n{\r\n\tPosition pos( x, y, m_dimZ - 1 );\r\n\tw->getFloorLevelBelow( pos, true );\r\n\r\n\tauto& world = w->world();\r\n\r\n\tfor ( int i = 0; i < diff; ++i )\r\n\t{\r\n\t\tif ( pos.z - i > 92 )\r\n\t\t{\r\n\t\t\tTile& tile = world[x + y * m_dimX + ( pos.z - i ) * m_dimX * m_dimY];\r\n\r\n\t\t\ttile.wallType      = WT_NOWALL;\r\n\t\t\ttile.wallMaterial  = 0;\r\n\t\t\ttile.flags         = TileFlag::TF_NONE;\r\n\t\t\ttile.wallSpriteUID = 0;\r\n\r\n\t\t\ttile.floorType      = FT_NOFLOOR;\r\n\t\t\ttile.floorMaterial  = 0;\r\n\t\t\ttile.floorSpriteUID = 0;\r\n\r\n\t\t\ttile.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t\t//w->addWater( Position( x, y, pos.z - i ), 8 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::setSandFloor( int x, int y, int sandRowID )\r\n{\r\n\tPosition pos( x, y, m_dimZ - 1 );\r\n\tw->getFloorLevelBelow( pos, true );\r\n\r\n\tTile& tile = w->world()[x + y * m_dimX + ( pos.z + 1 ) * m_dimX * m_dimY];\r\n\r\n\ttile.wallType      = WT_NOWALL;\r\n\ttile.wallMaterial  = 0;\r\n\ttile.flags         = TileFlag::TF_WATER;\r\n\ttile.wallSpriteUID = 0;\r\n\r\n\ttile.floorMaterial  = sandRowID;\r\n\ttile.floorType      = FT_SOLIDFLOOR;\r\n\ttile.floorSpriteUID = g->sf()->createSprite( \"RoughFloor\", { \"Sand\" } )->uID;\r\n\r\n\tTile& tile2          = w->world()[x + y * m_dimX + ( pos.z ) * m_dimX * m_dimY];\r\n\ttile2.wallType       = ( WallType )( WallType::WT_SOLIDWALL | WallType::WT_ROUGH | WallType::WT_VIEWBLOCKING | WallType::WT_MOVEBLOCKING );\r\n\ttile2.floorMaterial  = sandRowID;\r\n\ttile2.wallMaterial   = sandRowID;\r\n\ttile2.floorType      = FT_SOLIDFLOOR;\r\n\ttile2.wallSpriteUID  = g->sf()->createSprite( \"RoughWall\", { \"Sand\" } )->uID;\r\n\ttile2.floorSpriteUID = g->sf()->createSprite( \"RoughFloor\", { \"Sand\" } )->uID;\r\n}\r\n\r\nint WorldGenerator::getLowestZonXLine( int x )\r\n{\r\n\tshort maxZ = m_dimZ - 1;\r\n\tfor ( int y = 1; y < m_dimY - 1; ++y )\r\n\t{\r\n\t\tPosition pos( x, y, m_dimZ - 1 );\r\n\t\tw->getFloorLevelBelow( pos, false );\r\n\t\tmaxZ = qMin( maxZ, pos.z );\r\n\t}\r\n\treturn maxZ;\r\n}\r\n\r\nint WorldGenerator::getLowestZonYLine( int y )\r\n{\r\n\tshort maxZ = m_dimZ - 1;\r\n\tfor ( int x = 1; x < m_dimX - 1; ++x )\r\n\t{\r\n\t\tPosition pos( x, y, m_dimZ - 1 );\r\n\t\tw->getFloorLevelBelow( pos, false );\r\n\t\tmaxZ = qMin( maxZ, pos.z );\r\n\t}\r\n\treturn maxZ;\r\n}\r\n\r\nvoid WorldGenerator::fillWater( int x, int y, int z )\r\n{\r\n\twhile ( z > 1 )\r\n\t{\r\n\t\tTile& tile = w->world()[x + y * m_dimX + z * m_dimX * m_dimY];\r\n\t\tif ( !(bool)( tile.wallType & WT_SOLIDWALL ) )\r\n\t\t{\r\n\t\t\tw->addWater( Position( x, y, z ), 10 );\r\n\t\t}\r\n\r\n\t\tif ( (bool)( tile.floorType & FT_SOLIDFLOOR ) )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\t--z;\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::createRivers()\r\n{\r\n\tQList<std::vector<Position>> worms;\r\n\tauto& world = w->world();\r\n\r\n\tfor ( int i = 1; i < ngs->rivers() + 1; ++i )\r\n\t{\r\n\t\tint border = qMax( 0, qMin( int( perlinRandWhiteNoise( i * 10, i * 20 ) * 4 ), 3 ) );\r\n\t\tint offset = qMax( 10, qMin( int( perlinRandWhiteNoise( i * 15, i * 17 ) * m_dimX ), m_dimX - 10 ) );\r\n\r\n\t\tqDebug() << i << \": \" << border << offset;\r\n\r\n\t\tint dir = 0;\r\n\t\tPosition pos;\r\n\t\tswitch ( border )\r\n\t\t{\r\n\t\t\tcase 0: //west border\r\n\t\t\t\tdir = 4;\r\n\t\t\t\tpos = Position( 1, offset, m_dimZ - 1 );\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1: // north border\r\n\t\t\t\tpos = Position( offset, 1, m_dimZ - 1 );\r\n\t\t\t\tdir = 6;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2: // east border\r\n\t\t\t\tpos = Position( m_dimX - 2, offset, m_dimZ - 1 );\r\n\t\t\t\tdir = 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3: // sout border\r\n\t\t\t\tpos = Position( offset, m_dimY - 2, m_dimZ - 1 );\r\n\t\t\t\tdir = 2;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tworms.append( riverWorm( pos, dir, i, m_dimX * 3 ) );\r\n\t}\r\n\tQList<std::vector<Position>> worms2;\r\n\tfor ( auto worm : worms )\r\n\t{\r\n\t\tint prevZ = m_dimZ - 1;\r\n\r\n\t\tfor ( int i = 0; i < worm.size(); ++i )\r\n\t\t{\r\n\t\t\tauto pos = worm[i];\r\n\t\t\tw->getFloorLevelBelow( pos, false );\r\n\r\n\t\t\tif ( pos.z > prevZ )\r\n\t\t\t{\r\n\t\t\t\tpos.z = prevZ;\r\n\t\t\t}\r\n\t\t\tprevZ   = pos.z;\r\n\t\t\tworm[i] = pos;\r\n\t\t}\r\n\t\tworms2.append( worm );\r\n\t}\r\n\tfor ( auto worm : worms2 )\r\n\t{\r\n\t\tfor ( int i = 0; i < worm.size(); ++i )\r\n\t\t{\r\n\t\t\tauto pos = worm[i];\r\n\t\t\tcarveRiver( world, pos );\r\n\t\t}\r\n\r\n\t\tif ( worm.size() > 1 )\r\n\t\t{\r\n\t\t\tauto apos = worm[0];\r\n\t\t\tw->addAquifier( apos.belowOf() );\r\n\t\t\tauto dpos = worm[worm.size() - 1];\r\n\t\t\tw->addDeaquifier( dpos.belowOf() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nstd::vector<Position> WorldGenerator::riverWorm( Position pos, int dir, int num, int maxLength )\r\n{\r\n\tstd::vector<Position> out;\r\n\r\n\tif ( pos.x > 1 && pos.x < m_dimX - 2 && pos.y > 1 && pos.y < m_dimY - 2 )\r\n\t{\r\n\t\tout.push_back( pos );\r\n\t}\r\n\r\n\tint origDir = dir;\r\n\r\n\tint x = pos.x;\r\n\tint y = pos.y;\r\n\tint z = pos.z;\r\n\r\n\tfor ( int i = 0; i < maxLength; ++i )\r\n\t{\r\n\r\n\t\t// do we change dir?\r\n\t\tif ( perlinRandWhiteNoise( x * i * num, y * i * num ) > 0.8 && out.size() > m_dimX / 10 )\r\n\t\t{\r\n\t\t\t//if yes\r\n\t\t\tfloat rand    = perlinRandWhiteNoise( x * i * 2 * num, y * i * 2 * num );\r\n\t\t\tint dirChange = rand > 0.5 ? -1 : 1;\r\n\t\t\tdir += dirChange;\r\n\r\n\t\t\tswitch ( origDir )\r\n\t\t\t{\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\tif ( dir == 4 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdir -= dirChange;\r\n\t\t\t\t\t\tdir -= dirChange;\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 ( dir == 6 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdir -= dirChange;\r\n\t\t\t\t\t\tdir -= dirChange;\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 ( dir == 0 || dir == 8 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdir -= dirChange;\r\n\t\t\t\t\t\tdir -= dirChange;\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 ( dir == 2 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tdir -= dirChange;\r\n\t\t\t\t\t\tdir -= dirChange;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( dir < 0 )\r\n\t\t\tdir = 7;\r\n\t\tif ( dir > 7 )\r\n\t\t\tdir = 0;\r\n\t\tswitch ( dir )\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tx -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tx -= 1;\r\n\t\t\t\ty -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\ty -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tx += 1;\r\n\t\t\t\ty -= 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 4:\r\n\t\t\t\tx += 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 5:\r\n\t\t\t\tx += 1;\r\n\t\t\t\ty += 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 6:\r\n\t\t\t\ty += 1;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 7:\r\n\t\t\t\tx -= 1;\r\n\t\t\t\ty += 1;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif ( x > 1 && x < m_dimX - 2 && y > 1 && y < m_dimY - 2 )\r\n\t\t{\r\n\t\t\tout.push_back( Position( x, y, z ) );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\r\n\treturn out;\r\n}\r\n\r\nvoid WorldGenerator::carveRiver( std::vector<Tile>& world, Position& pos )\r\n{\r\n\tint size = ngs->riverSize();\r\n\tint sandRowID = DBH::materialUID( \"Sand\" );\r\n\tfor ( int x = pos.x - size; x < pos.x + size + 1; ++x )\r\n\t{\r\n\t\tfor ( int y = pos.y - size; y < pos.y + size + 1; ++y )\r\n\t\t{\r\n\t\t\tif ( x > 0 && x < m_dimX - 1 && y > 0 && y < m_dimY - 1 )\r\n\t\t\t{\r\n\t\t\t\tTile& tile         = world[x + y * m_dimX + pos.z * m_dimX * m_dimY];\r\n\t\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\t\ttile.flags         = TileFlag::TF_NONE;\r\n\t\t\t\ttile.wallType      = WallType::WT_NOWALL;\r\n\t\t\t\ttile.wallMaterial  = 0;\r\n\r\n\t\t\t\ttile.floorType      = FT_NOFLOOR;\r\n\t\t\t\ttile.floorMaterial  = 0;\r\n\t\t\t\ttile.floorSpriteUID = 0;\r\n\r\n\t\t\t\tTile& tile2         = world[x + y * m_dimX + ( pos.z - 1 ) * m_dimX * m_dimY];\r\n\t\t\t\ttile2.wallSpriteUID = 0;\r\n\t\t\t\ttile2.flags         = TileFlag::TF_NONE;\r\n\t\t\t\ttile2.wallType      = WallType::WT_NOWALL;\r\n\t\t\t\ttile2.wallMaterial  = 0;\r\n\r\n\t\t\t\ttile2.floorType      = FT_NOFLOOR;\r\n\t\t\t\ttile2.floorMaterial  = 0;\r\n\t\t\t\ttile2.floorSpriteUID = 0;\r\n\r\n\t\t\t\tTile& tile3         = world[x + y * m_dimX + ( pos.z - 2 ) * m_dimX * m_dimY];\r\n\t\t\t\ttile3.wallSpriteUID = 0;\r\n\t\t\t\ttile3.flags         = TileFlag::TF_NONE;\r\n\t\t\t\ttile3.wallType      = WallType::WT_NOWALL;\r\n\t\t\t\ttile3.wallMaterial  = 0;\r\n\r\n\t\t\t\tw->addWater( Position( x, y, pos.z - 1 ), 10 );\r\n\t\t\t\tw->addWater( Position( x, y, pos.z - 2 ), 10 );\r\n\r\n\t\t\t\tfor ( int z = pos.z; z < m_dimZ - 1; ++z )\r\n\t\t\t\t{\r\n\t\t\t\t\tTile& tile         = world[x + y * m_dimX + z * m_dimX * m_dimY];\r\n\t\t\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\t\t\ttile.flags         = TileFlag::TF_NONE;\r\n\t\t\t\t\ttile.wallType      = WallType::WT_NOWALL;\r\n\t\t\t\t\ttile.wallMaterial  = 0;\r\n\r\n\t\t\t\t\ttile.floorType      = FT_NOFLOOR;\r\n\t\t\t\t\ttile.floorMaterial  = 0;\r\n\t\t\t\t\ttile.floorSpriteUID = 0;\r\n\t\t\t\t}\r\n\t\t\t\tsetSandFloor( x, y, sandRowID );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid WorldGenerator::placeLairs()\r\n{\r\n\t// find suitable location\r\n\tQString lairType   = \"Mant\";\r\n\tauto row           = DB::selectRow( \"Lairs\", \"MantLair1\" );\r\n\tQString sizeString = row.value( \"Size\" ).toString();\r\n\tauto sl            = sizeString.split( \" \" );\r\n\tint xs             = 0;\r\n\tint ys             = 0;\r\n\tint zs             = 0;\r\n\tif ( sl.size() == 3 )\r\n\t{\r\n\t\txs = sl[0].toInt();\r\n\t\tys = sl[1].toInt();\r\n\t\tzs = sl[2].toInt();\r\n\t}\r\n\tqDebug() << \"lair size \" << xs << ys << zs;\r\n\tint x = 5;\r\n\tint y = 5;\r\n\tint z = 100 - zs;\r\n\tPosition posZero( x, y, z );\r\n\tbool found = true;\r\n\twhile ( ( x + xs ) < m_dimX - 5 && ( y + ys ) < m_dimY - 5 )\r\n\t{\r\n\t\tfound = checkPlacement( x, y, z, xs, ys, zs );\r\n\t\tif ( found )\r\n\t\t{\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tx += 5;\r\n\t\ty += 5;\r\n\t}\r\n\tqDebug() << \"lair location \" << x << y << z;\r\n\tif ( found )\r\n\t{\r\n\t\tauto& world = w->world();\r\n\r\n\t\tQString def  = row.value( \"Layout\" ).toString();\r\n\t\tauto defList = def.split( \" \" );\r\n\r\n\t\tfor ( int zz = 0; zz < zs; ++zz )\r\n\t\t{\r\n\t\t\tfor ( int yy = 0; yy < ys; ++yy )\r\n\t\t\t{\r\n\t\t\t\tfor ( int xx = 0; xx < xs; ++xx )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString tileDef = defList[xx + yy * xs + zz * xs * ys];\r\n\t\t\t\t\tTile& tile      = world[x + xx + ( y + yy ) * m_dimX + ( z + zz ) * m_dimX * m_dimY];\r\n\t\t\t\t\tswitch ( tileDef.toInt() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase 0:\r\n\t\t\t\t\t\t\ttile.floorType      = FT_NOFLOOR;\r\n\t\t\t\t\t\t\ttile.floorMaterial  = 0;\r\n\t\t\t\t\t\t\ttile.floorSpriteUID = 0;\r\n\r\n\t\t\t\t\t\t\ttile.wallType         = WT_NOWALL;\r\n\t\t\t\t\t\t\ttile.wallSpriteUID    = 0;\r\n\t\t\t\t\t\t\ttile.wallMaterial     = 0;\r\n\t\t\t\t\t\t\ttile.embeddedMaterial = 0;\r\n\t\t\t\t\t\t\ttile.itemSpriteUID    = 0;\r\n\r\n\t\t\t\t\t\t\ttile.flags = TileFlag::TF_NONE;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\t\ttile.wallType         = WT_NOWALL;\r\n\t\t\t\t\t\t\ttile.wallSpriteUID    = 0;\r\n\t\t\t\t\t\t\ttile.wallMaterial     = 0;\r\n\t\t\t\t\t\t\ttile.embeddedMaterial = 0;\r\n\t\t\t\t\t\t\ttile.itemSpriteUID    = 0;\r\n\t\t\t\t\t\t\ttile.flags += TileFlag::TF_WALKABLE;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\t\ttile.wallType      = WT_NOWALL;\r\n\t\t\t\t\t\t\ttile.wallSpriteUID = 0;\r\n\t\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}\r\n\t\tfor ( int zz = 0; zz < zs; ++zz )\r\n\t\t{\r\n\t\t\tfor ( int yy = 0; yy < ys; ++yy )\r\n\t\t\t{\r\n\t\t\t\tfor ( int xx = 0; xx < xs; ++xx )\r\n\t\t\t\t{\r\n\t\t\t\t\tQString tileDef = defList[xx + yy * xs + zz * xs * ys];\r\n\t\t\t\t\tTile& tile      = world[x + xx + ( y + yy ) * m_dimX + ( z + zz ) * m_dimX * m_dimY];\r\n\t\t\t\t\tswitch ( tileDef.toInt() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase 0:\r\n\t\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tTile& tileAbove     = world[x + xx + ( y + yy ) * m_dimX + ( z + zz + 1 ) * m_dimX * m_dimY];\r\n\t\t\t\t\t\t\ttileAbove.floorType = FT_NOFLOOR;\r\n\t\t\t\t\t\t\ttileAbove.flags     = TileFlag::TF_NONE;\r\n\t\t\t\t\t\t\t//tileAbove.floorMaterial = 0;\r\n\t\t\t\t\t\t\ttileAbove.floorSpriteUID = 0;\r\n\r\n\t\t\t\t\t\t\ttile.wallType      = WT_NOWALL;\r\n\t\t\t\t\t\t\ttile.flags         = TileFlag::TF_NONE;\r\n\t\t\t\t\t\t\ttile.wallSpriteUID = 0;\r\n\t\t\t\t\t\t\t//tile.wallMaterial = 0;\r\n\t\t\t\t\t\t\tw->createRamp( x + xx, y + yy, z + zz, DBH::materialSID( tile.wallMaterial ) );\r\n\t\t\t\t\t\t}\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}\r\n\r\n\t\tfor ( auto row : DB::selectRows( \"Lairs_Spawns\" ) )\r\n\t\t{\r\n\t\t\tint rot       = row.value( \"Rotation\" ).toInt();\r\n\t\t\tGender gender = (Gender)row.value( \"Gender\" ).toInt();\r\n\t\t\tint level     = row.value( \"Level\" ).toInt();\r\n\r\n\t\t\tg->cm()->addCreature( CreatureType::MONSTER, lairType + row.value( \"Type\" ).toString(), posZero + Position( row.value( \"Offset\" ) ), gender, true, false );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool WorldGenerator::checkPlacement( int xLoc, int yLoc, int zLoc, int xSize, int ySize, int zSize )\r\n{\r\n\tauto& world = w->world();\r\n\tfor ( int z = zLoc; z < zSize; ++z )\r\n\t{\r\n\t\tfor ( int x = xLoc; x < xSize; ++x )\r\n\t\t{\r\n\t\t\tfor ( int y = yLoc; y < ySize; ++y )\r\n\t\t\t{\r\n\t\t\t\tTile& tile = world[x + y * m_dimX + z * m_dimX * m_dimY];\r\n\t\t\t\tif ( !(bool)( tile.wallType & WT_SOLIDWALL ) )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\temit signalStatus( \"Found lairs location.\" );\r\n\treturn true;\r\n}"
  },
  {
    "path": "src/game/worldgenerator.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../../3rdparty/fastnoise/FastNoise.h\"\r\n\r\n#include <QMap>\r\n#include <QObject>\r\n#include <QVector>\r\n\r\n#include <vector>\r\n\r\nclass Grass;\r\nstruct Tile;\r\nstruct EmbeddedMaterial;\r\nstruct TerrainMaterial;\r\nstruct Position;\r\nclass NewGameSettings;\r\nclass World;\r\nclass Game;\r\n\r\nclass WorldGenerator : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tWorldGenerator( NewGameSettings* ngs, Game* parent );\r\n\t~WorldGenerator();\r\n\r\n\tWorld* generateTopology();\r\n\tvoid addLife();\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\t// resize world and fill stone layers\r\n\tvoid setStoneLayers();\r\n\t// set metal ores and gems\r\n\tvoid setMetalsAndGems();\r\n\t// set water and sand floor at water\r\n\tvoid setWater();\r\n\t// set sunlight and grass\r\n\tvoid initSunLight();\r\n\t// add plants and trees\r\n\tvoid addPlantsAndTrees();\r\n\t// add animals\r\n\tvoid addAnimals();\r\n\t// add gnomes and starting items\r\n\tvoid addGnomesAndStartingItems();\r\n\tQString getRandomMaterial( QString itemSID );\r\n\r\n\tvoid initMateralVectors();\r\n\r\n\tvoid fillFloor( int z, QVector<TerrainMaterial>& mats, QVector<int>& matsinLevel );\r\n\r\n\tvoid fillFloorMushroomBiome( int z, QVector<TerrainMaterial>& mats, QVector<int>& matsinLevel );\r\n\r\n\tvoid discoverAll();\r\n\r\n\tvoid createRamps();\r\n\tvoid createRamp( int z );\r\n\r\n\tvoid createOceanFront();\r\n\tvoid decreaseHeight( int x, int y, int diff );\r\n\tvoid setSandFloor( int x, int y, int sandRowID );\r\n\tint getLowestZonXLine( int x );\r\n\tint getLowestZonYLine( int y );\r\n\tvoid fillWater( int x, int y, int z );\r\n\r\n\tvoid createRivers();\r\n\tstd::vector<Position> riverWorm( Position pos, int dir, int num, int maxLength );\r\n\tvoid carveRiver( std::vector<Tile>& world, Position& pos );\r\n\r\n\tvoid placeLairs();\r\n\tbool checkPlacement( int xLoc, int yLoc, int zLoc, int xSize, int ySize, int zSize );\r\n\r\n\tbool fBm( int x, int y, int z );\r\n\r\n\tstd::vector<Position> perlinWorm( int z, int num, int maxLength );\r\n\tvoid clear3x3( std::vector<Tile>& world, Position& pos );\r\n\tvoid setEmbedded3x3( std::vector<Tile>& world, Position& pos, unsigned short embeddedMaterial, unsigned short spriteID );\r\n\r\n\tfloat perlinRandWhiteNoise( int x, int y, int z = -1 );\r\n\tQString getRandomEmbedded( int x, int y, int z, QMap<QString, EmbeddedMaterial>& em );\r\n\r\n\tvoid createHeightMap( int dimX, int dimY );\r\n\r\n\tQVector<int> m_heightMap;\r\n\tQVector<float> m_heightMap2;\r\n\r\n\tint m_seed = 1337;\r\n\r\n\tfloat m_min;\r\n\tfloat m_max;\r\n\r\n\tint m_dimX;\r\n\tint m_dimY;\r\n\tint m_dimZ;\r\n\r\n\tint m_groundLevel;\r\n\r\n\tint m_mushroomLevel = 0;\r\n\r\n\tFastNoise m_random;\r\n\r\n\tQVector<TerrainMaterial> m_mats;\r\n\tQVector<int> m_matsInLevel;\r\n\r\n\tbool m_fow = true;\r\n\r\n\tWorld* w = nullptr;\r\n\tNewGameSettings* ngs = nullptr;\r\nsignals:\r\n\tvoid signalStatus( QString msg );\r\n};\r\n"
  },
  {
    "path": "src/game/worldgetters.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/animal.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n\r\nTile& World::getTile( const unsigned short x, const unsigned short y, const unsigned short z )\r\n{\r\n\treturn getTile( Position( x, y, z ) );\r\n}\r\n\r\nTile& World::getTile( const Position pos )\r\n{\r\n\treturn m_world[pos.toInt()];\r\n}\r\n\r\nconst Tile& World::getTile( const Position pos ) const\r\n{\r\n\treturn m_world[pos.toInt()];\r\n}\r\n\r\nTile& World::getTile( const unsigned int id )\r\n{\r\n\treturn m_world[id];\r\n}\r\n\r\nbool World::hasJob( Position pos )\r\n{\r\n\treturn hasJob( pos.toInt() );\r\n}\r\n\r\nbool World::hasJob( int x, int y, int z )\r\n{\r\n\treturn hasJob( Position( x, y, z ).toInt() );\r\n}\r\n\r\nbool World::hasJob( unsigned int tileID )\r\n{\r\n\treturn m_jobSprites.contains( tileID );\r\n}\r\n\r\nQVariantMap World::jobSprite( Position pos )\r\n{\r\n\treturn m_jobSprites.value( pos.toInt() );\r\n}\r\n\r\nQVariantMap World::jobSprite( int x, int y, int z )\r\n{\r\n\treturn jobSprite( Position( x, y, z ) );\r\n}\r\n\r\nQVariantMap World::jobSprite( unsigned int tileID )\r\n{\r\n\treturn m_jobSprites.value( tileID );\r\n}\r\n\r\nTileFlag World::getTileFlag( Position pos )\r\n{\r\n\treturn getTile( pos ).flags;\r\n}\r\n\r\nunsigned short World::wallMaterial( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.wallMaterial;\r\n}\r\n\r\nunsigned short World::embeddedMaterial( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.embeddedMaterial;\r\n}\r\n\r\nunsigned short World::floorMaterial( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.floorMaterial;\r\n}\r\n\r\nWallType World::wallType( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.wallType;\r\n}\r\n\r\nFloorType World::floorType( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.floorType;\r\n}\r\n\r\nbool World::creatureAtPos( Position pos )\r\n{\r\n\treturn m_creaturePositions.contains( pos.toInt() );\r\n}\r\n\r\nbool World::creatureAtPos( unsigned int posID )\r\n{\r\n\tbool ret = m_creaturePositions.contains( posID );\r\n\treturn ret;\r\n}\r\n\r\nCreature* World::firstCreatureAtPos( unsigned int posID, quint8& rotation )\r\n{\r\n\tif ( m_creaturePositions.contains( posID ) )\r\n\t{\r\n\t\tunsigned int ID = m_creaturePositions[posID].first();\r\n\t\tAnimal* a       = g->cm()->animal( ID );\r\n\t\tif ( a )\r\n\t\t{\r\n\t\t\treturn a;\r\n\t\t}\r\n\t\tGnome* gn = g->gm()->gnome( ID );\r\n\t\tif ( gn )\r\n\t\t{\r\n\t\t\treturn gn;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nvoid World::setWalkable( Position pos, bool value )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\tif ( value )\r\n\t{\r\n\t\tsetTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tclearTileFlag( pos, TileFlag::TF_WALKABLE );\r\n\t}\r\n\tupdateWalkable( pos );\r\n}\r\n\r\nvoid World::updateWalkable( Position pos )\r\n{\r\n\tm_regionMap.updatePosition( pos );\r\n}\r\n\r\nbool World::isWalkable( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.flags & TileFlag::TF_WALKABLE;\r\n}\r\n\r\nbool World::isWalkableGnome( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.flags & TileFlag::TF_WALKABLE && !( tile.flags & TileFlag::TF_NOPASS ) && ( tile.fluidLevel < 4 ) && !( tile.flags & TileFlag::TF_LAVA );\r\n}\r\n\r\nbool World::isRamp( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn ( tile.wallType & WallType::WT_RAMP ) || ( tile.floorType & FloorType::FT_RAMPTOP );\r\n}\r\n\r\nbool World::isSolidFloor( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn ( tile.floorType & FloorType::FT_SOLIDFLOOR );\r\n}\r\n\r\nbool World::noTree( const Position pos, const int xRange, const int yRange )\r\n{\r\n\tif ( pos.x < 3 || pos.x > m_dimX - 4 || pos.y < 3 || pos.y > m_dimY - 4 )\r\n\t{\r\n\t\treturn false;\r\n\t}\r\n\r\n\tint xStart = qMax( 0, pos.x - xRange );\r\n\tint xEnd   = qMin( m_dimX - 1, pos.x + xRange );\r\n\tint yStart = qMax( 0, pos.y - yRange );\r\n\tint yEnd   = qMin( m_dimY - 1, pos.y + yRange );\r\n\r\n\tfor ( int x = xStart; x <= xEnd; ++x )\r\n\t{\r\n\t\tfor ( int y = yStart; y <= yEnd; ++y )\r\n\t\t{\r\n\t\t\tunsigned int testPosID = Position( x, y, pos.z ).toInt();\r\n\t\t\tif ( m_plants.contains( testPosID ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_plants[testPosID].isTree() )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( auto job = g->jm()->getJobAtPos( Position( x, y, pos.z ) ) )\r\n\t\t\t{\r\n\t\t\t\tif ( job && job->type() == \"PlantTree\" )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nbool World::noShroom( const Position pos, const int xRange, const int yRange )\r\n{\r\n\tint xStart = qMax( 0, pos.x - xRange );\r\n\tint xEnd   = qMin( m_dimX - 1, pos.x + xRange );\r\n\tint yStart = qMax( 0, pos.y - yRange );\r\n\tint yEnd   = qMin( m_dimY - 1, pos.y + yRange );\r\n\r\n\tfor ( int x = xStart; x <= xEnd; ++x )\r\n\t{\r\n\t\tfor ( int y = yStart; y <= yEnd; ++y )\r\n\t\t{\r\n\t\t\tunsigned int testPosID = Position( x, y, pos.z ).toInt();\r\n\t\t\tif ( m_plants.contains( testPosID ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_plants[testPosID].isMushroom() )\r\n\t\t\t\t{\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn true;\r\n}\r\n\r\nQSet<unsigned int> World::updatedTiles()\r\n{\r\n\tQMutexLocker lock( &m_updateMutex );\r\n\tQSet<unsigned int> ret;\r\n\tret.swap( m_updatedTiles );\r\n\t// Assume next update batch is going to be similar in size\r\n\tm_updatedTiles.reserve( ret.size() );\r\n\treturn ret;\r\n}\r\n\r\nvoid World::getFloorLevelBelow( Position& pos, bool setSunlight )\r\n{\r\n\tint z = pos.z;\r\n\twhile ( z > 0 )\r\n\t{\r\n\t\tTile& tile = getTile( pos.x, pos.y, z );\r\n\t\tif ( setSunlight )\r\n\t\t{\r\n\t\t\ttile.flags += TileFlag::TF_SUNLIGHT;\r\n\t\t\taddToUpdateList( Position( pos.x, pos.y, z ) );\r\n\t\t\tspreadIndirectSunlight( Position( pos.x, pos.y, z ) );\r\n\t\t}\r\n\t\tif ( !( tile.floorType == FloorType::FT_NOFLOOR || ( tile.floorType & FloorType::FT_RAMPTOP ) ) )\r\n\t\t{\r\n\t\t\tpos.z = z;\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t--z;\r\n\t}\r\n}\r\n\r\nvoid World::spreadIndirectSunlight( Position pos )\r\n{\r\n\tTile& te = getTile( pos.eastOf() );\r\n\tte.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\tTile& ts = getTile( pos.southOf() );\r\n\tts.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\tTile& tw = getTile( pos.westOf() );\r\n\ttw.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\tTile& tn = getTile( pos.northOf() );\r\n\ttn.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n}\r\n\r\nvoid World::checkIndirectSunlightForNeighbors( Position pos )\r\n{\r\n\tcheckIndirectSunlight( pos.eastOf() );\r\n\tcheckIndirectSunlight( pos.southOf() );\r\n\tcheckIndirectSunlight( pos.westOf() );\r\n\tcheckIndirectSunlight( pos.northOf() );\r\n}\r\n\r\nvoid World::checkIndirectSunlight( Position pos )\r\n{\r\n\tTile& here = getTile( pos );\r\n\tTile& te   = getTile( pos.eastOf() );\r\n\tif ( te.flags & TileFlag::TF_SUNLIGHT )\r\n\t{\r\n\t\there.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\t\treturn;\r\n\t}\r\n\tTile& ts = getTile( pos.southOf() );\r\n\tif ( ts.flags & TileFlag::TF_SUNLIGHT )\r\n\t{\r\n\t\there.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\t\treturn;\r\n\t}\r\n\tTile& tw = getTile( pos.westOf() );\r\n\tif ( tw.flags & TileFlag::TF_SUNLIGHT )\r\n\t{\r\n\t\there.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\t\treturn;\r\n\t}\r\n\tTile& tn = getTile( pos.northOf() );\r\n\tif ( tn.flags & TileFlag::TF_SUNLIGHT )\r\n\t{\r\n\t\there.flags += TileFlag::TF_INDIRECT_SUNLIGHT;\r\n\t\treturn;\r\n\t}\r\n\r\n\tclearTileFlag( pos, TileFlag::TF_INDIRECT_SUNLIGHT );\r\n}\r\n\r\nint World::fluidLevel( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.fluidLevel;\r\n}\r\n\r\nint World::vegetationLevel( Position pos )\r\n{\r\n\tTile& tile = getTile( pos );\r\n\treturn tile.vegetationLevel;\r\n}\r\n\r\nvoid World::setVegetationLevel( Position pos, int level )\r\n{\r\n\tTile& tile           = getTile( pos );\r\n\ttile.vegetationLevel = level;\r\n}\r\n\r\nvoid World::loadFloorConstructions( QVariantList list )\r\n{\r\n\tfor ( auto item : list )\r\n\t{\r\n\t\tPosition pos( item.toMap().value( \"Pos\" ) );\r\n\t\tauto constr = item.toMap();\r\n\t\tm_floorConstructions.insert( pos.toInt(), constr );\r\n\t}\r\n}\r\n\r\nvoid World::loadWallConstructions( QVariantList list )\r\n{\r\n\tfor ( auto item : list )\r\n\t{\r\n\t\tauto map = item.toMap();\r\n\r\n\t\tPosition pos( map.value( \"Pos\" ) );\r\n\t\tauto constr = item.toMap();\r\n\t\tm_wallConstructions.insert( pos.toInt(), constr );\r\n\r\n\t\tif ( map.value( \"Light\" ).toInt() > 0 )\r\n\t\t{\r\n\t\t\taddLight( pos.toInt(), pos, map.value( \"Light\" ).toInt() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nQMap<unsigned int, QVariantMap> World::jobSprites()\r\n{\r\n\treturn m_jobSprites;\r\n}\r\n\r\nvoid World::insertLoadedJobSprite( unsigned int key, QVariantMap entry )\r\n{\r\n\tm_jobSprites.insert( key, entry );\r\n}\r\n\r\nint World::walkableNeighbors( Position pos )\r\n{\r\n\tint out = 0;\r\n\tif ( isWalkable( pos.eastOf() ) )\r\n\t\t++out;\r\n\tif ( isWalkable( pos.westOf() ) )\r\n\t\t++out;\r\n\tif ( isWalkable( pos.southOf() ) )\r\n\t\t++out;\r\n\tif ( isWalkable( pos.northOf() ) )\r\n\t\t++out;\r\n\treturn out;\r\n}\r\n\r\nQString World::getDebugWallConstruction( Position pos )\r\n{\r\n\tif ( m_wallConstructions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto wc = m_wallConstructions.value( pos.toInt() );\r\n\t\treturn QString( QJsonDocument::fromVariant( wc ).toJson() );\r\n\t}\r\n\treturn \"no construction\";\r\n}\r\n\r\nunsigned int World::getFurnitureOnTile( Position pos )\r\n{\r\n\tif ( m_wallConstructions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tauto wc = m_wallConstructions.value( pos.toInt() );\r\n\t\tif( wc.value( \"Type\").toString() == \"Furniture\" )\r\n\t\t{\r\n\t\t\treturn wc.value( \"Item\" ).toUInt();\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\n\r\nbool World::isLineOfSight( Position a, Position b ) const\r\n{\r\n\treturn testLine( a, b, [world = this]( const Position &current, const Position& previous ) -> bool {\r\n\t\tconst auto& tile = world->getTile( current );\r\n\t\tif ( tile.wallType & WallType::WT_VIEWBLOCKING )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif ( current.z > previous.z && tile.floorType & FloorType::FT_SOLIDFLOOR )\r\n\t\t{\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (current.z < previous.z)\r\n\t\t{\r\n\t\t\tconst auto& tilePrev = world->getTile( current );\r\n\t\t\tif ( tilePrev.floorType & FloorType::FT_SOLIDFLOOR )\r\n\t\t\t{\r\n\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\r\nQString World::getDebugFloorConstruction( Position pos )\r\n{\r\n\tif ( m_floorConstructions.contains( pos.toInt() ) )\r\n\t{\r\n\t\tif ( m_floorConstructions.contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tauto fc = m_floorConstructions.value( pos.toInt() );\r\n\t\t\treturn QString( QJsonDocument::fromVariant( fc ).toJson() );\r\n\t\t}\r\n\t}\r\n\treturn \"no construction\";\r\n}\r\n\r\nQList<Position> World::connectedNeighbors( Position pos )\r\n{\r\n\tQList<Position> out;\r\n\r\n\tbool north = false;\r\n\tbool east  = false;\r\n\tbool south = false;\r\n\tbool west  = false;\r\n\r\n\tauto next = pos.northOf();\r\n\tif ( isWalkable( next ) )\r\n\t{\r\n\t\tnorth = true;\r\n\t\tout.append( next );\r\n\t}\r\n\t{\r\n\t\tTile& tile = getTile( next );\r\n\t\tif ( tile.floorType & FT_RAMPTOP )\r\n\t\t{\r\n\t\t\tout.append( next.belowOf() );\r\n\t\t}\r\n\t}\r\n\r\n\tnext = pos.eastOf();\r\n\tif ( isWalkable( next ) )\r\n\t{\r\n\t\teast = true;\r\n\t\tout.append( next );\r\n\t}\r\n\t{\r\n\t\tTile& tile = getTile( next );\r\n\t\tif ( tile.floorType & FT_RAMPTOP )\r\n\t\t{\r\n\t\t\tout.append( next.belowOf() );\r\n\t\t}\r\n\t}\r\n\r\n\tnext = pos.southOf();\r\n\tif ( isWalkable( next ) )\r\n\t{\r\n\t\tsouth = true;\r\n\t\tout.append( next );\r\n\t}\r\n\t{\r\n\t\tTile& tile = getTile( next );\r\n\t\tif ( tile.floorType & FT_RAMPTOP )\r\n\t\t{\r\n\t\t\tout.append( next.belowOf() );\r\n\t\t}\r\n\t}\r\n\r\n\tnext = pos.westOf();\r\n\tif ( isWalkable( next ) )\r\n\t{\r\n\t\twest = true;\r\n\t\tout.append( next );\r\n\t}\r\n\t{\r\n\t\tTile& tile = getTile( next );\r\n\t\tif ( tile.floorType & FT_RAMPTOP )\r\n\t\t{\r\n\t\t\tout.append( next.belowOf() );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( north && east )\r\n\t{\r\n\t\tnext = pos.neOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t}\r\n\tif ( east && south )\r\n\t{\r\n\t\tnext = pos.seOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t}\r\n\tif ( south && west )\r\n\t{\r\n\t\tnext = pos.swOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t}\r\n\tif ( west && north )\r\n\t{\r\n\t\tnext = pos.nwOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t}\r\n\r\n\tTile& curTile = g->w()->getTile( pos );\r\n\r\n\tif ( (bool)( curTile.wallType & ( WT_STAIR | WT_SCAFFOLD ) ) )\r\n\t{\r\n\t\tnext = pos.aboveOf();\r\n\t\tout.append( next );\r\n\t}\r\n\tif ( (bool)( curTile.floorType & ( FT_STAIRTOP | FT_SCAFFOLD ) ) )\r\n\t{\r\n\t\tnext = pos.belowOf();\r\n\t\tout.append( next );\r\n\t}\r\n\tif ( (bool)( curTile.wallType & ( WT_RAMP ) ) )\r\n\t{\r\n\t\tauto above = pos.aboveOf();\r\n\t\tnext       = above.northOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t\tnext = above.eastOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t\tnext = above.southOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t\tnext = above.westOf();\r\n\t\tif ( isWalkable( next ) )\r\n\t\t{\r\n\t\t\tout.append( next );\r\n\t\t}\r\n\t}\r\n\treturn out;\r\n}\r\n"
  },
  {
    "path": "src/game/worldobject.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"worldobject.h\"\r\n\r\n#include \"../base/gamestate.h\"\r\n#include \"../game/game.h\"\r\n\r\nWorldObject::WorldObject( Game* game ) :\r\n\tg( game )\r\n{\r\n\tm_id = GameState::createID();\r\n}\r\n\r\nWorldObject::~WorldObject()\r\n{\r\n}\r\n\r\nWorldObject::WorldObject( QVariantMap vals, Game* game ) :\r\n\tg( game )\r\n{\r\n\tm_id             = vals.value( \"ID\" ).toUInt();\r\n\tm_lastUpdateTick = vals.value( \"LastUpdate\" ).value<quint64>();\r\n\tm_name           = vals.value( \"Name\" ).toString();\r\n\tm_active         = vals.value( \"Active\" ).toBool();\r\n\r\n\tif ( vals.contains( \"Suspended\" ) )\r\n\t{\r\n\t\tm_active = !vals.value( \"Suspended\" ).toBool();\r\n\t}\r\n}\r\n\r\nvoid WorldObject::serialize( QVariantMap& out ) const\r\n{\r\n\tout.insert( \"ID\", m_id );\r\n\tout.insert( \"Name\", m_name );\r\n\tout.insert( \"LastUpdate\", m_lastUpdateTick );\r\n\tout.insert( \"Active\", m_active );\r\n}\r\n"
  },
  {
    "path": "src/game/worldobject.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QPoint>\r\n#include <QPointer>\r\n#include <QSize>\r\n#include <QString>\r\n#include <QVariantMap>\r\n\r\nclass Game;\r\n\r\nclass WorldObject\r\n{\r\n\tQ_DISABLE_COPY_MOVE( WorldObject )\r\npublic:\r\n\tWorldObject( Game* game );\r\n\tWorldObject( QVariantMap vals, Game* game );\r\n\tvirtual ~WorldObject();\r\n\r\n\tvoid serialize( QVariantMap& out ) const;\r\n\r\n\tQString name()\r\n\t{\r\n\t\treturn m_name;\r\n\t}\r\n\tvoid setName( QString name )\r\n\t{\r\n\t\tm_name = name;\r\n\t}\r\n\r\n\tunsigned int id()\r\n\t{\r\n\t\treturn m_id;\r\n\t}\r\n\tvoid setId( unsigned int id )\r\n\t{\r\n\t\tm_id = id;\r\n\t}\r\n\r\n\tvoid setActive( bool state )\r\n\t{\r\n\t\tm_active = state;\r\n\t}\r\n\tbool active()\r\n\t{\r\n\t\treturn m_active;\r\n\t}\r\n\r\n\tvoid setSuspended( bool state )\r\n\t{\r\n\t\tm_active = !state;\r\n\t}\r\n\tbool suspended()\r\n\t{\r\n\t\treturn !m_active;\r\n\t}\r\n\r\nprotected:\r\n\tQPointer<Game> g;\r\n\tunsigned int m_id = 0;\r\n\tQString m_name    = \"\";\r\n\tbool m_active     = true;\r\n\r\n\tquint64 m_lastUpdateTick = 0;\r\n};"
  },
  {
    "path": "src/gfx/sprite.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"../gfx/sprite.h\"\r\n\r\n#include \"../base/db.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nSprite::Sprite()\r\n{\r\n}\r\n\r\nSprite::Sprite( const Sprite& other )\r\n{\r\n\tuID           = other.uID;\r\n\tsID           = other.sID;\r\n\txOffset       = other.xOffset;\r\n\tyOffset       = other.yOffset;\r\n\topacity       = other.opacity;\r\n\trandomNumbers = other.randomNumbers;\r\n}\r\n\r\nSprite::~Sprite()\r\n{\r\n}\r\n\r\nSpritePixmap::SpritePixmap( QPixmap pixmap ) :\r\n\tSprite()\r\n{\r\n\tm_pixmap = pixmap;\r\n\tm_type   = \"pixmap\";\r\n}\r\n\r\nSpritePixmap::SpritePixmap( QPixmap pixmap, QString offset ) :\r\n\tSprite()\r\n{\r\n\tm_type          = \"pixmap\";\r\n\tint xOffset     = 0;\r\n\tint yOffset     = 0;\r\n\tQStringList osl = offset.split( \" \" );\r\n\tif ( osl.size() == 2 )\r\n\t{\r\n\t\txOffset = osl[0].toInt();\r\n\t\tyOffset = osl[1].toInt();\r\n\t}\r\n\tQImage img = pixmap.toImage();\r\n\tQImage target( 32, 64, QImage::Format::Format_RGBA8888 );\r\n\r\n\ttarget.fill( QColor( 0, 0, 0, 0 ) );\r\n\r\n\tfor ( int y = 0; y < img.height(); ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < img.width(); ++x )\r\n\t\t{\r\n\t\t\tif ( y > 63 )\r\n\t\t\t\tqDebug() << \"SpritePixmap::SpritePixmap\" << sID;\r\n\t\t\ttarget.setPixelColor( qMin( 31, x + xOffset ), qMax( 0, qMin( 63, y + yOffset + 16 ) ), img.pixelColor( x, y ) );\r\n\t\t}\r\n\t}\r\n\r\n\tm_pixmap = QPixmap::fromImage( target );\r\n}\r\n\r\nSpritePixmap::SpritePixmap( const SpritePixmap& other ) :\r\n\tSprite( other )\r\n{\r\n\tm_type   = \"pixmap\";\r\n\tm_pixmap = other.m_pixmap;\r\n}\r\n\r\nSpritePixmap::~SpritePixmap()\r\n{\r\n}\r\n\r\nQPixmap& SpritePixmap::pixmap( QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\treturn m_pixmap;\r\n}\r\n\r\nvoid SpritePixmap::setPixmap( QPixmap pm, QString season, unsigned char rotation )\r\n{\r\n\tm_pixmap = pm;\r\n}\r\n\r\nvoid SpritePixmap::applyEffect( QString effect )\r\n{\r\n\tif ( effect == \"FlipHorizontal\" )\r\n\t{\r\n\t\tQImage img = m_pixmap.toImage();\r\n\t\tm_pixmap   = QPixmap::fromImage( img.mirrored( true, false ) );\r\n\t}\r\n\telse if ( effect == \"Rot90\" )\r\n\t{\r\n\t\tQImage img = m_pixmap.toImage();\r\n\t\tQImage tmp( 32, 32, QImage::Format::Format_RGBA8888 );\r\n\t\tfor ( int y = 0; y < 32; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t\t{\r\n\t\t\t\tif ( y + 16 > 63 )\r\n\t\t\t\t\tqDebug() << \"SpritePixmap::applyEffect 1\" << sID;\r\n\t\t\t\ttmp.setPixelColor( x, y, img.pixelColor( x, y + 16 ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tQPixmap pm = QPixmap::fromImage( tmp );\r\n\t\tpm         = pm.transformed( QTransform().rotate( 90 ) );\r\n\t\ttmp        = pm.toImage();\r\n\t\tfor ( int y = 0; y < 32; ++y )\r\n\t\t{\r\n\t\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t\t{\r\n\t\t\t\tif ( y > 63 )\r\n\t\t\t\t\tqDebug() << \"SpritePixmap::applyEffect 2\" << sID;\r\n\t\t\t\timg.setPixelColor( x, y + 16, tmp.pixelColor( x, y ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_pixmap = QPixmap::fromImage( img );\r\n\t}\r\n}\r\n\r\nvoid SpritePixmap::applyTint( QString tint, QString materialSID )\r\n{\r\n\tif ( tint.isEmpty() )\r\n\t\treturn;\r\n\r\n\tQColor color;\r\n\r\n\tif ( tint == \"Material\" )\r\n\t{\r\n\t\ttint = DB::select( \"Color\", \"Materials\", materialSID ).toString();\r\n\t}\r\n\tQList<QString> csl = tint.split( ' ' );\r\n\tif ( csl.size() == 4 )\r\n\t{\r\n\t\tcolor = QColor( csl[0].toInt(), csl[1].toInt(), csl[2].toInt(), csl[3].toInt() );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t//qDebug() << \"no tint\" << materialSID << tint;\r\n\t\tcolor = QColor( 255, 255, 255, 255 );\r\n\t}\r\n\topacity = color.alphaF();\r\n\r\n\tQImage img = m_pixmap.toImage();\r\n\r\n\tfor ( int x = 0; x < img.size().width(); ++x )\r\n\t{\r\n\t\tfor ( int y = 0; y < img.size().height(); ++y )\r\n\t\t{\r\n\t\t\tif ( y > 63 )\r\n\t\t\t\tqDebug() << \"SpritePixmap::applyTint\" << sID;\r\n\t\t\tQColor col = img.pixelColor( x, y );\r\n\t\t\tcol.setRedF( qMin( 1., col.redF() * color.redF() ) );\r\n\t\t\tcol.setGreenF( qMin( 1., col.greenF() * color.greenF() ) );\r\n\t\t\tcol.setBlueF( qMin( 1., col.blueF() * color.blueF() ) );\r\n\t\t\tcol.setAlphaF( qMin( 1., col.alphaF() * color.alphaF() ) );\r\n\t\t\timg.setPixelColor( x, y, col );\r\n\t\t}\r\n\t}\r\n\tm_pixmap = QPixmap::fromImage( img );\r\n}\r\n\r\nvoid SpritePixmap::combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\tif ( m_pixmap.size().width() > 0 && m_pixmap.size().height() > 0 )\r\n\t{\r\n\t\tQPainter painter( &m_pixmap );\r\n\t\tpainter.drawPixmap( 0, 0, other->pixmap( season, rotation, animationStep ) );\r\n\t}\r\n}\r\n\r\nSpriteSeasons::SpriteSeasons() :\r\n\tSprite()\r\n{\r\n\tm_type = \"seasons\";\r\n}\r\n\r\nSpriteSeasons::SpriteSeasons( const SpriteSeasons& other ) :\r\n\tSprite( other )\r\n{\r\n\tm_type    = \"seasons\";\r\n\tm_sprites = other.m_sprites;\r\n}\r\n\r\nSpriteSeasons::~SpriteSeasons()\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\tdelete s;\r\n\t}\r\n}\r\n\r\nQPixmap& SpriteSeasons::pixmap( QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\treturn m_sprites[season]->pixmap( season, rotation, animationStep );\r\n}\r\n\r\nvoid SpriteSeasons::setPixmap( QPixmap pm, QString season, unsigned char rotation )\r\n{\r\n\tm_sprites[season]->setPixmap( pm, season, rotation );\r\n}\r\n\r\nvoid SpriteSeasons::applyEffect( QString effect )\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\ts->applyEffect( effect );\r\n\t}\r\n}\r\n\r\nvoid SpriteSeasons::applyTint( QString tint, QString materialSID )\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\ts->applyTint( tint, materialSID );\r\n\t}\r\n}\r\n\r\nvoid SpriteSeasons::combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\tm_sprites[season]->combine( other, season, rotation, animationStep );\r\n}\r\n\r\nSpriteRotations::SpriteRotations() :\r\n\tSprite()\r\n{\r\n\tm_type = \"rotations\";\r\n}\r\n\r\nSpriteRotations::~SpriteRotations()\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\tdelete s;\r\n\t}\r\n}\r\n\r\nSpriteRotations::SpriteRotations( const SpriteRotations& other ) :\r\n\tSprite( other )\r\n{\r\n\tm_type    = \"rotations\";\r\n\tm_sprites = other.m_sprites;\r\n}\r\n\r\nQPixmap& SpriteRotations::pixmap( QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\treturn m_sprites[rotation]->pixmap( season, rotation, animationStep );\r\n}\r\n\r\nvoid SpriteRotations::setPixmap( QPixmap pm, QString season, unsigned char rotation )\r\n{\r\n\tm_sprites[rotation]->setPixmap( pm, season, rotation );\r\n}\r\n\r\nvoid SpriteRotations::applyEffect( QString effect )\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\ts->applyEffect( effect );\r\n\t}\r\n}\r\n\r\nvoid SpriteRotations::applyTint( QString tint, QString materialSID )\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\ts->applyTint( tint, materialSID );\r\n\t}\r\n}\r\n\r\nvoid SpriteRotations::combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\tm_sprites[rotation]->combine( other, season, rotation, animationStep );\r\n}\r\n\r\nSpriteFrames::SpriteFrames() :\r\n\tSprite()\r\n{\r\n\tm_type = \"frames\";\r\n}\r\n\r\nSpriteFrames::SpriteFrames( const SpriteFrames& other ) :\r\n\tSprite( other )\r\n{\r\n\tm_type    = \"frames\";\r\n\tm_sprites = other.m_sprites;\r\n}\r\n\r\nSpriteFrames::~SpriteFrames()\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\tdelete s;\r\n\t}\r\n}\r\n\r\nQPixmap& SpriteFrames::pixmap( QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\treturn m_sprites[animationStep % m_sprites.size()]->pixmap( season, rotation, animationStep );\r\n}\r\n\r\nvoid SpriteFrames::setPixmap( QPixmap pm, QString season, unsigned char rotation )\r\n{\r\n\tm_sprites[0]->setPixmap( pm, season, rotation );\r\n}\r\n\r\nvoid SpriteFrames::applyEffect( QString effect )\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\ts->applyEffect( effect );\r\n\t}\r\n}\r\n\r\nvoid SpriteFrames::applyTint( QString tint, QString materialSID )\r\n{\r\n\tfor ( auto s : m_sprites )\r\n\t{\r\n\t\ts->applyTint( tint, materialSID );\r\n\t}\r\n}\r\n\r\nvoid SpriteFrames::combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep )\r\n{\r\n\tif ( m_sprites.size() > animationStep )\r\n\t{\r\n\t\tm_sprites[animationStep]->combine( other, season, rotation, animationStep );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/gfx/sprite.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMap>\r\n#include <QPixmap>\r\n#include <QString>\r\n\r\nenum SpriteRotation : unsigned char\r\n{\r\n\tNoRot,\r\n\tFR,\r\n\tFL = 1,\r\n\tBL = 2,\r\n\tBR = 3\r\n};\r\n\r\nclass Sprite\r\n{\r\npublic:\r\n\tSprite();\r\n\tSprite( const Sprite& other );\r\n\tvirtual ~Sprite();\r\n\r\n\tvirtual QPixmap& pixmap( QString season, unsigned char rotation, unsigned char animationStep ) = 0;\r\n\tvirtual void setPixmap( QPixmap pm, QString season, unsigned char rotation )                   = 0;\r\n\r\n\tvirtual void applyEffect( QString effect )                  = 0;\r\n\tvirtual void applyTint( QString tint, QString materialSID ) = 0;\r\n\r\n\tvirtual void combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep ) = 0;\r\n\r\n\tunsigned int uID = 0;\r\n\tQString sID      = \"\";\r\n\tchar xOffset     = 0;\r\n\tchar yOffset     = 0;\r\n\tfloat opacity    = 1.0;\r\n\tbool anim        = false;\r\n\tbool hasTransp   = false;\r\n\tQMap<int, int> randomNumbers;\r\n\tQString m_type = \"\";\r\n};\r\n\r\nclass SpritePixmap : public Sprite\r\n{\r\npublic:\r\n\tSpritePixmap( QPixmap pixmap );\r\n\tSpritePixmap( QPixmap pixmap, QString offset );\r\n\tSpritePixmap( const SpritePixmap& other );\r\n\t~SpritePixmap();\r\n\r\n\tQPixmap& pixmap( QString season, unsigned char rotation, unsigned char animationStep );\r\n\tvoid setPixmap( QPixmap pm, QString season, unsigned char rotation );\r\n\r\n\tvoid applyEffect( QString effect );\r\n\tvoid applyTint( QString tint, QString materialSID );\r\n\r\n\tvoid combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep );\r\n\r\n\tQPixmap m_pixmap;\r\n};\r\n\r\nclass SpriteSeasons : public Sprite\r\n{\r\npublic:\r\n\tSpriteSeasons();\r\n\tSpriteSeasons( const SpriteSeasons& other );\r\n\t~SpriteSeasons();\r\n\r\n\tQPixmap& pixmap( QString season, unsigned char rotation, unsigned char animationStep );\r\n\tvoid setPixmap( QPixmap pm, QString season, unsigned char rotation );\r\n\r\n\tvoid applyEffect( QString effect );\r\n\tvoid applyTint( QString tint, QString materialSID );\r\n\r\n\tvoid combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep );\r\n\r\n\tQHash<QString, Sprite*> m_sprites;\r\n};\r\n\r\nclass SpriteRotations : public Sprite\r\n{\r\npublic:\r\n\tSpriteRotations();\r\n\tSpriteRotations( const SpriteRotations& other );\r\n\t~SpriteRotations();\r\n\r\n\tQPixmap& pixmap( QString season, unsigned char rotation, unsigned char animationStep );\r\n\tvoid setPixmap( QPixmap pm, QString season, unsigned char rotation );\r\n\r\n\tvoid applyEffect( QString effect );\r\n\tvoid applyTint( QString tint, QString materialSID );\r\n\r\n\tvoid combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep );\r\n\r\n\tQList<Sprite*> m_sprites;\r\n};\r\n\r\nclass SpriteFrames : public Sprite\r\n{\r\npublic:\r\n\tSpriteFrames();\r\n\tSpriteFrames( const SpriteFrames& other );\r\n\t~SpriteFrames();\r\n\r\n\tQPixmap& pixmap( QString season, unsigned char rotation, unsigned char animationStep );\r\n\tvoid setPixmap( QPixmap pm, QString season, unsigned char rotation );\r\n\r\n\tvoid applyEffect( QString effect );\r\n\tvoid applyTint( QString tint, QString materialSID );\r\n\r\n\tvoid combine( Sprite* other, QString season, unsigned char rotation, unsigned char animationStep );\r\n\r\n\tQList<Sprite*> m_sprites;\r\n};\r\n"
  },
  {
    "path": "src/gfx/spritefactory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"spritefactory.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/io.h\"\r\n#include \"../base/util.h\"\r\n\r\n#include <QDebug>\r\n#include <QElapsedTimer>\r\n#include <QHash>\r\n#include <QJsonArray>\r\n#include <QJsonDocument>\r\n#include <QPainter>\r\n#include <QPixmap>\r\n\r\nSpriteFactory::SpriteFactory()\r\n{\r\n\tinit();\r\n}\r\n\r\nSpriteFactory::~SpriteFactory()\r\n{\r\n\tfor( auto& sprite : m_sprites )\r\n\t{\r\n\t\tdelete sprite;\r\n\t}\r\n\tm_sprites.clear();\r\n\tfor( auto& def : m_spriteDefinitions )\r\n\t{\r\n\t\tdelete def;\r\n\t}\r\n\tm_spriteDefinitions.clear();\r\n}\r\n\r\nbool SpriteFactory::init()\r\n{\r\n\t//m_pixmapSources.clear();\r\n\tm_baseSprites.clear();\r\n\r\n\tm_sprites.clear();\r\n\tm_sprites.append( nullptr );\r\n\r\n\tm_spriteIDs.clear();\r\n\tm_creatureSpriteIDs.clear();\r\n\r\n\tm_pixelData.clear();\r\n\r\n\tm_randomNumbers.clear();\r\n\r\n\tm_spriteDefinitions.clear();\r\n\tm_spriteDefVMs.clear();\r\n\r\n\tm_spriteCreations.clear();\r\n\r\n\tm_colors.clear();\r\n\tm_hairColors.clear();\r\n\r\n\tm_seasons = DB::ids( \"Seasons\" );\r\n\r\n\tauto matIds = DB::ids( \"Materials\" );\r\n\tfor ( auto id : matIds )\r\n\t{\r\n\t\tm_materialTypes.insert( id, DB::select( \"Type\", \"Materials\", id ).toString() );\r\n\t}\r\n\r\n\tfor ( auto color : DB::select2( \"Color\", \"Materials\", \"Type\", \"Dye\" ) )\r\n\t{\r\n\t\tm_colors.push_back( Global::util->string2QColor( color.toString() ) );\r\n\t}\r\n\r\n\tfor ( auto color : DB::selectRows( \"HairColors\" ) )\r\n\t{\r\n\t\tm_hairColors.push_back( Global::util->string2QColor( color.value( \"Color\" ).toString() ) );\r\n\t}\r\n\r\n\tbool loaded = true;\r\n\tauto rows   = DB::selectRows( \"BaseSprites\" );\r\n\tfor ( auto row : rows )\r\n\t{\r\n\t\tQString tilesheet = row.value( \"Tilesheet\" ).toString();\r\n\t\tif ( !m_pixmapSources.contains( tilesheet ) )\r\n\t\t{\r\n\t\t\tQPixmap pm;\r\n\t\t\tloaded = pm.load( Global::cfg->get( \"dataPath\" ).toString() + \"/tilesheet/\" + tilesheet );\r\n\t\t\tif ( !loaded )\r\n\t\t\t{\r\n\t\t\t\tloaded = pm.load( tilesheet );\r\n\t\t\t\tif ( !loaded )\r\n\t\t\t\t{\r\n\t\t\t\t\tqDebug() << \"SpriteFactory: failed to load \" << tilesheet;\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tm_pixmapSources.insert( tilesheet, pm );\r\n\t\t\t/*\r\n\t\t\tif( tilesheet == \"default.png\" )\r\n\t\t\t{\r\n\t\t\t\tQSet<QString>unused;\r\n\t\t\t\tint count = 0;\r\n\t\t\t\tfor( auto r : DB::selectRows( \"BaseSprites\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( r.value( \"Tilesheet\"  ).toString() == \"default.png\" )\r\n\t\t\t\t\tif( DB::numRows( \"Sprites\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\tif( DB::numRows2( \"Sprites\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_ByMaterialTypes\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_ByMaterials\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_Combine\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_Frames\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_Random\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_Rotations\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_Seasons\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif( DB::numRows2( \"Sprites_Seasons_Rotations\", r.value( \"ID\" ).toString() ) == 0 )\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tqDebug() << count++ << r.value( \"ID\" ).toString() << r.value( \"Tilesheet\" ).toString();\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tunused.insert( r.value( \"ID\" ).toString() );\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tint width = pm.width();\r\n\t\t\t\tint height = pm.height();\r\n\t\t\t\tQPixmap newPM( width, height );\r\n\t\t\t\t\r\n\t\t\t\tnewPM.fill( Qt::transparent);\r\n\t\t\t\tQPainter painter( &newPM );\r\n\t\t\t\t\r\n\t\t\t\tfor( auto r : DB::selectRows( \"BaseSprites\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( r.value( \"Tilesheet\" ).toString() == \"default.png\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif( !unused.contains( r.value( \"ID\" ).toString() ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tauto p = r.value( \"SourceRectangle\" ).toString().split( \" \" );\r\n\t\t\t\t\t\t\tauto sp = pm.copy( p[0].toInt(), p[1].toInt(), 32, 36 );\r\n\t\t\t\t\t\t\tpainter.drawPixmap( p[0].toInt(), p[1].toInt(), sp );\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\tnewPM.save( Global::cfg->get( \"dataPath\" ).toString() + \"/tilesheet2/\" + tilesheet );\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t}\r\n\t\tm_baseSprites.insert( row.value( \"ID\" ).toString(), extractPixmap( tilesheet, row ) );\r\n\t}\r\n\t\r\n\tQList<QVariantMap> spriteList = DB::selectRows( \"Sprites\" );\r\n\tfor ( auto& sprite : spriteList )\r\n\t{\r\n\t\tQString spriteID = sprite.value( \"ID\" ).toString();\r\n\r\n\t\tif ( sprite.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t{\r\n\t\t\tsprite.insert( \"BaseSprite\", spriteID );\r\n\t\t}\r\n\t\tif ( sprite.value( \"Tint\" ).toString().isEmpty() )\r\n\t\t{\r\n\t\t\tsprite.remove( \"Tint\" );\r\n\t\t}\r\n\t\tif ( sprite.value( \"DefaultMaterial\" ).toString().isEmpty() )\r\n\t\t{\r\n\t\t\tsprite.remove( \"DefaultMaterial\" );\r\n\t\t}\r\n\r\n\t\tif ( DB::numRows( \"Sprites_ByMaterials\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_ByMaterials\", spriteID );\r\n\t\t\tQVariantList byMaterials;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tif ( entry.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tentry.remove( \"BaseSprite\" );\r\n\t\t\t\t}\r\n\t\t\t\tif ( entry.value( \"Sprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tentry.remove( \"Sprite\" );\r\n\t\t\t\t}\r\n\t\t\t\tbyMaterials.append( entry );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"ByMaterials\", byMaterials );\r\n\t\t}\r\n\t\tif ( DB::numRows( \"Sprites_ByMaterialTypes\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_ByMaterialTypes\", spriteID );\r\n\t\t\tQVariantList byMaterialTypes;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tif ( entry.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tentry.remove( \"BaseSprite\" );\r\n\t\t\t\t}\r\n\t\t\t\tif ( entry.value( \"Sprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tentry.remove( \"Sprite\" );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbyMaterialTypes.append( entry );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"ByMaterialTypes\", byMaterialTypes );\r\n\t\t}\r\n\t\tif ( DB::numRows( \"Sprites_Combine\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_Combine\", spriteID );\r\n\t\t\tQVariantList combine;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap cm;\r\n\t\t\t\tif ( entry.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"Sprite\", entry.value( \"Sprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"BaseSprite\", entry.value( \"BaseSprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\tif ( !entry.value( \"Tint\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"Tint\", entry.value( \"Tint\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\tif ( !entry.value( \"Offset\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"Offset\", entry.value( \"Offset\" ).toString() );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcombine.append( cm );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"Combine\", combine );\r\n\t\t}\r\n\t\tif ( DB::numRows( \"Sprites_Frames\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_Frames\", spriteID );\r\n\t\t\tQVariantList frames;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap cm;\r\n\t\t\t\tcm.insert( \"BaseSprite\", entry.value( \"BaseSprite\" ).toString() );\r\n\t\t\t\tframes.append( cm );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"Frames\", frames );\r\n\t\t}\r\n\t\tif ( DB::numRows( \"Sprites_Random\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_Random\", spriteID );\r\n\t\t\tQVariantList random;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap cm;\r\n\t\t\t\tif ( entry.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"Sprite\", entry.value( \"Sprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"BaseSprite\", entry.value( \"BaseSprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\tcm.insert( \"Weight\", entry.value( \"Weight\" ).toInt() );\r\n\r\n\t\t\t\trandom.append( cm );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"Random\", random );\r\n\t\t}\r\n\t\tif ( DB::numRows( \"Sprites_Rotations\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_Rotations\", spriteID );\r\n\t\t\tQVariantList rotations;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap cm;\r\n\t\t\t\tif ( entry.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"Sprite\", entry.value( \"Sprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"BaseSprite\", entry.value( \"BaseSprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\tif ( !entry.value( \"Effect\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"Effect\", entry.value( \"Effect\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\tcm.insert( \"Rotation\", entry.value( \"Rotation\" ).toString() );\r\n\r\n\t\t\t\trotations.append( cm );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"Rotations\", rotations );\r\n\t\t}\r\n\t\tif ( DB::numRows( \"Sprites_Seasons\", spriteID ) )\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Sprites_Seasons\", spriteID );\r\n\t\t\tQVariantList seasons;\r\n\t\t\tfor ( auto entry : rows )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap cm;\r\n\t\t\t\tif ( !entry.value( \"BaseSprite\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tcm.insert( \"BaseSprite\", entry.value( \"BaseSprite\" ).toString() );\r\n\t\t\t\t}\r\n\t\t\t\tcm.insert( \"Season\", entry.value( \"Season\" ) );\r\n\r\n\t\t\t\tif ( DB::numRows( \"Sprites_Seasons_Rotations\", spriteID + entry.value( \"Season\" ).toString() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto crows = DB::selectRows( \"Sprites_Seasons_Rotations\", spriteID + entry.value( \"Season\" ).toString() );\r\n\t\t\t\t\tQVariantList rots;\r\n\t\t\t\t\tfor ( auto centry : crows )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\trots.append( centry );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcm.insert( \"Rotations\", rots );\r\n\t\t\t\t}\r\n\r\n\t\t\t\tseasons.append( cm );\r\n\t\t\t}\r\n\t\t\tsprite.remove( \"BaseSprite\" );\r\n\t\t\tsprite.insert( \"Seasons\", seasons );\r\n\t\t}\r\n\t}\r\n\r\n\t/* only for debug purpose\r\n\tQJsonArray ja;\r\n\tfor ( auto sprite : spriteList )\r\n\t{\r\n\t\tQJsonValue jv = QJsonValue::fromVariant( sprite );\r\n\t\tja.append( jv );\r\n\t}\r\n\tIO::saveFile( \"spriteconv.json\", ja );\r\n\t*/\r\n\r\n\tfor ( auto row : spriteList )\r\n\t{\r\n\t\tm_spriteDefVMs.insert( row.value( \"ID\" ).toString(), row );\r\n\t}\r\n\r\n\tfor ( auto row : spriteList )\r\n\t{\r\n\t\tDefNode* root = new DefNode;\r\n\t\troot->type    = \"root\";\r\n\t\troot->value   = row.value( \"ID\" ).toString();\r\n\t\tm_numFrames   = 1;\r\n\t\tparseDef( root, row );\r\n\t\troot->numFrames = m_numFrames;\r\n\t\tif ( root->childs.isEmpty() && root->baseSprite.isEmpty() )\r\n\t\t{\r\n\t\t\troot->baseSprite = root->value;\r\n\t\t}\r\n\t\tm_spriteDefinitions.insert( root->value, root );\r\n\t}\r\n\r\n\tcreateStandardSprites();\r\n\r\n\treturn loaded;\r\n}\r\n\r\nvoid SpriteFactory::addPixmapSource( QString name, QString path )\r\n{\r\n\tif ( !m_pixmapSources.contains( name ) )\r\n\t{\r\n\t\tQPixmap pm;\r\n\t\tbool loaded = pm.load( path );\r\n\t\tif ( loaded )\r\n\t\t{\r\n\t\t\tm_pixmapSources.insert( name, pm );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SpriteFactory::createStandardSprites()\r\n{\r\n\tm_thoughtBubbleIDs.insert( \"Tired\", createSprite( \"StatusTired\", { \"None\" } )->uID );\r\n\tm_thoughtBubbleIDs.insert( \"Sleeping\", createSprite( \"StatusSleeping\", { \"None\" } )->uID );\r\n\tm_thoughtBubbleIDs.insert( \"Thirsty\", createSprite( \"ThoughtBubbleThirsty\", { \"None\" } )->uID );\r\n\tm_thoughtBubbleIDs.insert( \"Hungry\", createSprite( \"ThoughtBubbleHungry\", { \"None\" } )->uID );\r\n\tm_thoughtBubbleIDs.insert( \"Combat\", createSprite( \"ThoughtBubbleCombat\", { \"None\" } )->uID );\r\n\r\n\tcreateSprite( \"SolidSelectionWall\", { \"Purple\" } );\r\n\r\n\tSprite* sprite         = createSprite( \"WaterFloor\", { \"Water\" } );\r\n\tGlobal::waterSpriteUID = sprite->uID;\r\n\r\n\tcreateSprite( \"WaterRightWall_\", { \"Water\" } );\r\n\tcreateSprite( \"WaterLeftWall_\", { \"Water\" } );\r\n\r\n\tSprite* sprite2         = createSprite( \"SolidSelectionWall\", { \"Grey\" } );\r\n\tGlobal::undiscoveredUID = sprite2->uID;\r\n\tcreateSprite( \"SolidSelectionFloor\", { \"Grey\" } );\r\n\tcreateSprite( \"RoughFloor\", { \"Dirt\" } );\r\n\r\n\t// keep a number of sprite ID's for future sprites that are created at start\r\n\t// when adding a new sprite here decrease the buffer\r\n\twhile ( m_sprites.size() < 31 )\r\n\t{\r\n\t\tm_sprites.append( nullptr );\r\n\t}\r\n}\r\n\r\nQPixmap SpriteFactory::extractPixmap( QString sourcePNG, QVariantMap def )\r\n{\r\n\tQString rect = def.value( \"SourceRectangle\" ).toString();\r\n\r\n\tQStringList rl = rect.split( \" \" );\r\n\tif ( rl.size() == 4 )\r\n\t{\r\n\t\tint x    = rl[0].toInt();\r\n\t\tint y    = rl[1].toInt();\r\n\t\tint dimX = rl[2].toInt();\r\n\t\tint dimY = rl[3].toInt();\r\n\r\n\t\tQPixmap p = m_pixmapSources[sourcePNG].copy( x, y, dimX, dimY );\r\n\t\tp.setMask( p.createMaskFromColor( QColor( 255, 0, 255 ), Qt::MaskInColor ) );\r\n\r\n\t\treturn p;\r\n\t}\r\n\tqDebug() << \"***ERROR*** extractPixmap() for \" << def.value( \"ID\" ).toString();\r\n\treturn QPixmap();\r\n}\r\n\r\nunsigned char SpriteFactory::rotationToChar( const QString suffix )\r\n{\r\n\tSpriteRotation rot = SpriteRotation::FR;\r\n\tif ( suffix == \"FL\" )\r\n\t\trot = SpriteRotation::FL;\r\n\telse if ( suffix == \"BL\" )\r\n\t\trot = SpriteRotation::BL;\r\n\telse if ( suffix == \"BR\" )\r\n\t\trot = SpriteRotation::BR;\r\n\treturn rot;\r\n}\r\n\r\nSprite* SpriteFactory::createSprite( const QString itemSID, QStringList materialSIDs, const QMap<int, int>& random )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tQString key = itemSID;\r\n\tm_randomNumbers.clear();\r\n\tif ( random.isEmpty() )\r\n\t{\r\n\t\tif ( containsRandom( itemSID, materialSIDs ) )\r\n\t\t{\r\n\t\t\tkey = createSpriteMaterialDryRun( itemSID, materialSIDs );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto mat : materialSIDs )\r\n\t\t\t{\r\n\t\t\t\tkey += \"_\";\r\n\t\t\t\tkey += mat;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_randomNumbers = random;\r\n\r\n\t\tfor ( auto mat : materialSIDs )\r\n\t\t{\r\n\t\t\tkey += \"_\";\r\n\t\t\tkey += mat;\r\n\t\t}\r\n\r\n\t\tif ( containsRandom( itemSID, materialSIDs ) )\r\n\t\t{\r\n\r\n\t\t\tfor ( auto r : m_randomNumbers )\r\n\t\t\t{\r\n\t\t\t\tkey += \"_\";\r\n\t\t\t\tkey += QString::number( r );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tSprite* sprite = nullptr;\r\n\tif ( m_spriteIDs.contains( key ) )\r\n\t{\r\n\t\tsprite = m_sprites.value( m_spriteIDs.value( key ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprite = createSpriteMaterial( itemSID, materialSIDs, key );\r\n\r\n\t\tif ( !sprite )\r\n\t\t{\r\n\t\t\treturn m_sprites.value( m_spriteIDs.value( \"SolidSelectionWall_Purple\" ) );\r\n\t\t}\r\n\r\n\t\tsprite->uID = m_sprites.size();\r\n\t\tm_spriteIDs.insert( key, m_sprites.size() );\r\n\t\tm_sprites.append( sprite );\r\n\r\n\t\taddPixmapToPixelData( sprite );\r\n\r\n\t\tm_textureAdded = true;\r\n\t\tSpriteCreation sc { itemSID, materialSIDs, m_randomNumbers, sprite->uID };\r\n\t\tm_spriteCreations.push_back( sc );\r\n\r\n\t\tif ( sprite->anim )\r\n\t\t{\r\n\t\t\tm_sprites.append( nullptr );\r\n\t\t\tm_sprites.append( nullptr );\r\n\t\t\tm_sprites.append( nullptr );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( itemSID.endsWith( \"Wall\" ) )\r\n\t{\r\n\t\tml.unlock();\r\n\t\tcreateSprite( itemSID + \"Short\", materialSIDs, random );\r\n\t}\r\n\r\n\treturn sprite;\r\n}\r\n\r\n// used for loading definitions, doesn't check if sprite exists as it will not exist and \r\n// doesn't create short walls because they are in the definition anyway\r\nSprite* SpriteFactory::createSprite2( const QString itemSID, QStringList materialSIDs, const QMap<int, int>& random )\r\n{\r\n\tQString key = itemSID;\r\n\tm_randomNumbers.clear();\r\n\tif ( random.isEmpty() )\r\n\t{\r\n\t\tif ( containsRandom( itemSID, materialSIDs ) )\r\n\t\t{\r\n\t\t\tkey = createSpriteMaterialDryRun( itemSID, materialSIDs );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfor ( auto mat : materialSIDs )\r\n\t\t\t{\r\n\t\t\t\tkey += \"_\";\r\n\t\t\t\tkey += mat;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_randomNumbers = random;\r\n\r\n\t\tfor ( auto mat : materialSIDs )\r\n\t\t{\r\n\t\t\tkey += \"_\";\r\n\t\t\tkey += mat;\r\n\t\t}\r\n\r\n\t\tif ( containsRandom( itemSID, materialSIDs ) )\r\n\t\t{\r\n\r\n\t\t\tfor ( auto r : m_randomNumbers )\r\n\t\t\t{\r\n\t\t\t\tkey += \"_\";\r\n\t\t\t\tkey += QString::number( r );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tSprite* sprite = nullptr;\r\n\r\n\tsprite = createSpriteMaterial( itemSID, materialSIDs, key );\r\n\r\n\tif ( !sprite )\r\n\t{\r\n\t\treturn m_sprites.value( m_spriteIDs.value( \"SolidSelectionWall_Purple\" ) );\r\n\t}\r\n\r\n\tsprite->uID = m_sprites.size();\r\n\tm_spriteIDs.insert( key, m_sprites.size() );\r\n\tm_sprites.append( sprite );\r\n\r\n\taddPixmapToPixelData( sprite );\r\n\r\n\tm_textureAdded = true;\r\n\tSpriteCreation sc { itemSID, materialSIDs, m_randomNumbers, sprite->uID };\r\n\tm_spriteCreations.push_back( sc );\r\n\r\n\tif ( sprite->anim )\r\n\t{\r\n\t\tm_sprites.append( nullptr );\r\n\t\tm_sprites.append( nullptr );\r\n\t\tm_sprites.append( nullptr );\r\n\t}\r\n\treturn sprite;\r\n}\r\n\r\nSprite* SpriteFactory::createAnimalSprite( const QString spriteSID, const QMap<int, int>& random )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tQString key = spriteSID;\r\n\tm_randomNumbers.clear();\r\n\tif ( random.isEmpty() )\r\n\t{\r\n\t\tif ( containsRandom( spriteSID, { \"None\" } ) )\r\n\t\t{\r\n\t\t\tkey = createSpriteMaterialDryRun( spriteSID, { \"None\" } );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_randomNumbers = random;\r\n\r\n\t\tkey += \"_None\";\r\n\r\n\t\tfor ( auto r : m_randomNumbers )\r\n\t\t{\r\n\t\t\tkey += \"_\";\r\n\t\t\tkey += QString::number( r );\r\n\t\t}\r\n\t}\r\n\r\n\tSprite* sprite = nullptr;\r\n\tif ( m_spriteIDs.contains( key ) )\r\n\t{\r\n\t\tsprite = m_sprites.value( m_spriteIDs.value( key ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsprite = createSpriteMaterial( spriteSID, { \"None\" }, key );\r\n\r\n\t\tsprite->uID = m_sprites.size();\r\n\t\tm_spriteIDs.insert( key, m_sprites.size() );\r\n\t\tm_sprites.append( sprite );\r\n\r\n\t\taddPixmapToPixelData( sprite );\r\n\r\n\t\tm_creatureTextureAdded = true;\r\n\r\n\t\tSpriteCreation sc { spriteSID, { \"None\" }, m_randomNumbers, sprite->uID, 1 };\r\n\t\tm_spriteCreations.push_back( sc );\r\n\t}\r\n\r\n\treturn sprite;\r\n}\r\n\r\nbool SpriteFactory::containsRandom( const QString itemSID, const QStringList materialSIDs )\r\n{\r\n\tQString spriteSID = DBH::spriteID( itemSID );\r\n\tif ( spriteSID.isEmpty() )\r\n\t{\r\n\t\tspriteSID = itemSID;\r\n\t}\r\n\treturn DBH::spriteIsRandom( spriteSID );\r\n}\r\n\r\nQString SpriteFactory::createSpriteMaterialDryRun( const QString itemSID, const QStringList materialSIDs )\r\n{\r\n\tQString spriteSID = DBH::spriteID( itemSID );\r\n\tif ( spriteSID.isEmpty() )\r\n\t{\r\n\t\t// every item needs a SpriteID\r\n\t\t//qDebug() << \"***ERROR*** item \" << itemSID << \" has no SpriteID entry.\";\r\n\t\tspriteSID = itemSID;\r\n\t}\r\n\r\n\tif ( !m_spriteDefinitions.contains( spriteSID ) )\r\n\t{\r\n\t\tqDebug() << \"***ERROR*** sprite definition \" << spriteSID << \" for item \" << itemSID << \" doesn't exist.\";\r\n\t\t//abort();\r\n\t}\r\n\tDefNode* dn = m_spriteDefinitions.value( spriteSID );\r\n\tif ( dn )\r\n\t{\r\n\t\tfor ( auto season : m_seasons )\r\n\t\t{\r\n\t\t\tfor ( int i = 0; i < dn->numFrames; ++i )\r\n\t\t\t{\r\n\t\t\t\tgetBaseSpriteDryRun( dn, itemSID, materialSIDs, season, \"FR\", i );\r\n\t\t\t\tgetBaseSpriteDryRun( dn, itemSID, materialSIDs, season, \"FL\", i );\r\n\t\t\t\tgetBaseSpriteDryRun( dn, itemSID, materialSIDs, season, \"BL\", i );\r\n\t\t\t\tgetBaseSpriteDryRun( dn, itemSID, materialSIDs, season, \"BR\", i );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tQString key = itemSID;\r\n\tfor ( auto mat : materialSIDs )\r\n\t{\r\n\t\tkey += \"_\";\r\n\t\tkey += mat;\r\n\t}\r\n\tfor ( auto r : m_randomNumbers )\r\n\t{\r\n\t\tkey += \"_\";\r\n\t\tkey += QString::number( r );\r\n\t}\r\n\treturn key;\r\n}\r\n\r\nSprite* SpriteFactory::createSpriteMaterial( const QString itemSID, const QStringList materialSIDs, const QString key )\r\n{\r\n\tQString spriteSID = DBH::spriteID( itemSID );\r\n\tif ( spriteSID.isEmpty() )\r\n\t{\r\n\t\t// every item needs a SpriteID\r\n\t\t//qDebug() << \"***ERROR*** item \" << itemSID << \" has no SpriteID entry.\";\r\n\t\tspriteSID = itemSID;\r\n\t}\r\n\r\n\tif ( !m_spriteDefinitions.contains( spriteSID ) )\r\n\t{\r\n\t\tqDebug() << \"***ERROR*** sprite definition \" << spriteSID << \" for item \" << itemSID << \" doesn't exist.\";\r\n\t\t//abort();\r\n\t}\r\n\tDefNode* dn    = m_spriteDefinitions.value( spriteSID );\r\n\tSprite* sprite = nullptr;\r\n\tif ( dn )\r\n\t{\r\n\t\tm_offset = \"\";\r\n\r\n\t\tsprite = getBaseSprite( dn, itemSID, materialSIDs );\r\n\r\n\t\tif ( !m_offset.isEmpty() )\r\n\t\t{\r\n\t\t\tQStringList osl = m_offset.split( \" \" );\r\n\t\t\tif ( osl.size() == 2 )\r\n\t\t\t{\r\n\t\t\t\tsprite->xOffset = osl[0].toInt();\r\n\t\t\t\tsprite->yOffset = osl[1].toInt();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsprite->xOffset = 0;\r\n\t\t\tsprite->yOffset = 0;\r\n\t\t}\r\n\r\n\t\tsprite->opacity       = m_opacity;\r\n\t\tsprite->randomNumbers = m_randomNumbers;\r\n\t\tsprite->anim          = DBH::spriteHasAnim( spriteSID );\r\n\t}\r\n\treturn sprite;\r\n}\r\n\r\nvoid SpriteFactory::parseDef( DefNode* parent, QVariantMap def )\r\n{\r\n\tif ( def.contains( \"Sprite\" ) )\r\n\t{\r\n\t\tQString spriteID = def.value( \"Sprite\" ).toString();\r\n\t\tQVariant tint    = def.value( \"Tint\" );\r\n\t\tQVariant effect  = def.value( \"Effect\" );\r\n\t\tQVariant offset  = def.value( \"Offset\" );\r\n\t\tdef              = m_spriteDefVMs.value( spriteID );\r\n\t\tif ( tint.isValid() )\r\n\t\t{\r\n\t\t\tdef.insert( \"Tint\", tint );\r\n\t\t}\r\n\t\tif ( effect.isValid() )\r\n\t\t{\r\n\t\t\tdef.insert( \"Effect\", effect );\r\n\t\t}\r\n\t}\r\n\r\n\tparent->effect          = def.value( \"Effect\" ).toString();\r\n\tparent->offset          = def.value( \"Offset\" ).toString();\r\n\tparent->tint            = def.value( \"Tint\" ).toString();\r\n\tparent->baseSprite      = def.value( \"BaseSprite\" ).toString();\r\n\tparent->defaultMaterial = def.value( \"DefaultMaterial\" ).toString();\r\n\tparent->hasTransp       = def.value( \"HasTransp\" ).toBool();\r\n\r\n\t/*\r\n\tif( def.contains( \"ByItems\" ) )\r\n\t{\r\n\t\tfor( auto item : def.value( \"ByItems\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child = new DefNode;\r\n\t\t\tchild->depth = parent->depth + 1;\r\n\t\t\tchild->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\t\tchild->type = \"ByItem\";\r\n\t\t\tchild->value = item.toMap().value( \"ItemID\" ).toString();\r\n\t\t\tparent->childs.insert( child->value, child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\t*/\r\n\tif ( def.contains( \"ByMaterials\" ) )\r\n\t{\r\n\t\tfor ( auto item : def.value( \"ByMaterials\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = parent->depth + 1;\r\n\t\t\tchild->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\t\tchild->type     = \"ByMaterial\";\r\n\t\t\tchild->value    = item.toMap().value( \"MaterialID\" ).toString();\r\n\t\t\tparent->childs.insert( child->value, child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\tif ( def.contains( \"ByMaterialTypes\" ) )\r\n\t{\r\n\t\tfor ( auto item : def.value( \"ByMaterialTypes\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = parent->depth + 1;\r\n\t\t\tchild->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\t\tchild->type     = \"ByMaterialType\";\r\n\t\t\tchild->value    = item.toMap().value( \"MaterialType\" ).toString();\r\n\t\t\tparent->childs.insert( child->value, child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\tif ( def.contains( \"Seasons\" ) )\r\n\t{\r\n\t\tfor ( auto item : def.value( \"Seasons\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = parent->depth + 1;\r\n\t\t\tchild->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\t\tchild->type     = \"Season\";\r\n\t\t\tchild->value    = item.toMap().value( \"Season\" ).toString();\r\n\t\t\tparent->childs.insert( child->value, child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\tif ( def.contains( \"Rotations\" ) )\r\n\t{\r\n\t\tfor ( auto item : def.value( \"Rotations\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = parent->depth + 1;\r\n\t\t\tchild->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\t\tchild->type     = \"Rotation\";\r\n\t\t\tchild->value    = item.toMap().value( \"Rotation\" ).toString();\r\n\t\t\tparent->childs.insert( child->value, child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\tif ( def.contains( \"Frames\" ) )\r\n\t{\r\n\t\tint index   = 0;\r\n\t\tm_numFrames = def.value( \"Frames\" ).toList().size();\r\n\t\tfor ( auto item : def.value( \"Frames\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = parent->depth + 1;\r\n\t\t\tchild->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\t\tchild->type     = \"Frame\";\r\n\t\t\tparent->childs.insert( \"Frame\" + QString::number( index++ ), child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\tif ( def.contains( \"Random\" ) )\r\n\t{\r\n\t\tint index            = 0;\r\n\t\tDefNode* randomNode  = new DefNode;\r\n\t\trandomNode->type     = \"RandomNode\";\r\n\t\trandomNode->depth    = parent->depth + 1;\r\n\t\trandomNode->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\tparent->childs.insert( \"RandomNode\", randomNode );\r\n\r\n\t\tfor ( auto item : def.value( \"Random\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = randomNode->depth + 1;\r\n\t\t\tchild->childPos = randomNode->childPos + QString::number( randomNode->childs.size() + 1 );\r\n\t\t\tchild->type     = \"Random\";\r\n\t\t\trandomNode->childs.insert( \"Random\" + QString::number( index++ ), child );\r\n\t\t\trandomNode->randomWeights.push_back( item.toMap().value( \"Weight\" ).toInt() );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n\r\n\tif ( def.contains( \"Combine\" ) )\r\n\t{\r\n\t\tint index             = 0;\r\n\t\tDefNode* combineNode  = new DefNode;\r\n\t\tcombineNode->type     = \"CombineNode\";\r\n\t\tcombineNode->depth    = parent->depth + 1;\r\n\t\tcombineNode->childPos = parent->childPos + QString::number( parent->childs.size() + 1 );\r\n\t\tparent->childs.insert( \"CombineNode\", combineNode );\r\n\r\n\t\tfor ( auto item : def.value( \"Combine\" ).toList() )\r\n\t\t{\r\n\t\t\tDefNode* child  = new DefNode;\r\n\t\t\tchild->depth    = parent->depth + 1;\r\n\t\t\tchild->childPos = combineNode->childPos + QString::number( combineNode->childs.size() + 1 );\r\n\t\t\tchild->type     = \"Combine\";\r\n\t\t\tcombineNode->childs.insert( \"Combine\" + QString::number( index++ ), child );\r\n\t\t\tparseDef( child, item.toMap() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nSprite* SpriteFactory::getBaseSprite( const DefNode* node, const QString itemSID, const QStringList materialSIDs, int materialID )\r\n{\r\n\tif ( !node->offset.isEmpty() )\r\n\t{\r\n\t\tm_offset = node->offset;\r\n\t}\r\n\tmaterialID          = qMin( materialID, materialSIDs.size() - 1 );\r\n\tQString materialSID = materialSIDs[materialID];\r\n\tif ( !node->baseSprite.isEmpty() )\r\n\t{\r\n\t\tQPixmap pm           = m_baseSprites.value( node->baseSprite );\r\n\t\tSpritePixmap* sprite = new SpritePixmap( pm, m_offset );\r\n\t\tsprite->applyEffect( node->effect );\r\n\t\tsprite->applyTint( node->tint, materialSID );\r\n\t\tsprite->hasTransp = node->hasTransp;\r\n\t\treturn sprite;\r\n\t}\r\n\r\n\tif ( node->childs.size() && node->childs.first()->type == \"Rotation\" )\r\n\t{\r\n\t\tSpriteRotations* sr = new SpriteRotations;\r\n\r\n\t\tsr->m_sprites.push_back( getBaseSprite( node->childs.value( \"FR\" ), itemSID, materialSIDs ) );\r\n\t\tsr->m_sprites.push_back( getBaseSprite( node->childs.value( \"FL\" ), itemSID, materialSIDs ) );\r\n\t\tsr->m_sprites.push_back( getBaseSprite( node->childs.value( \"BL\" ), itemSID, materialSIDs ) );\r\n\t\tsr->m_sprites.push_back( getBaseSprite( node->childs.value( \"BR\" ), itemSID, materialSIDs ) );\r\n\r\n\t\tsr->applyEffect( node->effect );\r\n\t\tsr->applyTint( node->tint, materialSID );\r\n\t\tsr->hasTransp = node->hasTransp;\r\n\t\treturn sr;\r\n\t}\r\n\tif ( node->childs.size() && node->childs.first()->type == \"Season\" )\r\n\t{\r\n\t\tSpriteSeasons* ss = new SpriteSeasons;\r\n\t\tfor ( auto child : node->childs )\r\n\t\t{\r\n\t\t\tss->m_sprites.insert( child->value, getBaseSprite( child, itemSID, materialSIDs ) );\r\n\t\t}\r\n\t\tss->applyEffect( node->effect );\r\n\t\tss->applyTint( node->tint, materialSID );\r\n\t\tss->hasTransp = node->hasTransp;\r\n\t\treturn ss;\r\n\t}\r\n\tif ( node->childs.contains( itemSID ) )\r\n\t{\r\n\t\treturn getBaseSprite( node->childs[itemSID], itemSID, materialSIDs );\r\n\t}\r\n\tif ( node->childs.size() && node->childs.first()->type == \"Frame\" )\r\n\t{\r\n\t\tSpriteFrames* sf = new SpriteFrames;\r\n\t\tfor ( auto child : node->childs )\r\n\t\t{\r\n\t\t\tsf->m_sprites.push_back( getBaseSprite( child, itemSID, materialSIDs ) );\r\n\t\t}\r\n\t\tsf->applyEffect( node->effect );\r\n\t\tsf->applyTint( node->tint, materialSID );\r\n\t\tsf->hasTransp = node->hasTransp;\r\n\t\treturn sf;\r\n\t}\r\n\r\n\tif ( node->type == \"CombineNode\" && node->childs.size() > 1 )\r\n\t{\r\n\t\tSprite* s = getBaseSprite( node->childs[\"Combine0\"], itemSID, materialSIDs, materialID );\r\n\r\n\t\tfor ( int i = 1; i < node->childs.size(); ++i )\r\n\t\t{\r\n\t\t\tSprite* s2 = getBaseSprite( node->childs[\"Combine\" + QString::number( i )], itemSID, materialSIDs, materialID + i );\r\n\t\t\tfor ( auto season : m_seasons )\r\n\t\t\t{\r\n\t\t\t\ts->combine( s2, season, 0, 0 );\r\n\t\t\t\ts->combine( s2, season, 1, 0 );\r\n\t\t\t\ts->combine( s2, season, 2, 0 );\r\n\t\t\t\ts->combine( s2, season, 3, 0 );\r\n\r\n\t\t\t\ts->combine( s2, season, 0, 1 );\r\n\t\t\t\ts->combine( s2, season, 1, 1 );\r\n\t\t\t\ts->combine( s2, season, 2, 1 );\r\n\t\t\t\ts->combine( s2, season, 3, 1 );\r\n\r\n\t\t\t\ts->combine( s2, season, 0, 2 );\r\n\t\t\t\ts->combine( s2, season, 1, 2 );\r\n\t\t\t\ts->combine( s2, season, 2, 2 );\r\n\t\t\t\ts->combine( s2, season, 3, 2 );\r\n\r\n\t\t\t\ts->combine( s2, season, 0, 3 );\r\n\t\t\t\ts->combine( s2, season, 1, 3 );\r\n\t\t\t\ts->combine( s2, season, 2, 3 );\r\n\t\t\t\ts->combine( s2, season, 3, 3 );\r\n\t\t\t}\r\n\t\t}\r\n\t\ts->hasTransp = node->hasTransp;\r\n\t\treturn s;\r\n\t}\r\n\tif ( node->type == \"RandomNode\" )\r\n\t{\r\n\t\tint randomNumber = m_randomNumbers.value( node->childPos.toInt() );\r\n\t\tSprite* rs       = getBaseSprite( node->childs[\"Random\" + QString::number( randomNumber )], itemSID, materialSIDs );\r\n\t\trs->applyEffect( node->childs[\"Random\" + QString::number( randomNumber )]->effect );\r\n\t\trs->applyTint( node->childs[\"Random\" + QString::number( randomNumber )]->tint, materialSID );\r\n\t\trs->hasTransp = node->hasTransp;\r\n\t\treturn rs;\r\n\t}\r\n\r\n\tif ( materialSIDs.size() )\r\n\t{\r\n\t\tQString materialType = getMaterialType( materialSID );\r\n\t\tif ( node->childs.contains( materialType ) )\r\n\t\t{\r\n\t\t\tSprite* pm = getBaseSprite( node->childs[materialType], itemSID, materialSIDs );\r\n\t\t\tpm->applyEffect( node->effect );\r\n\t\t\tpm->applyTint( node->tint, materialSID );\r\n\t\t\tpm->hasTransp = node->hasTransp;\r\n\t\t\treturn pm;\r\n\t\t}\r\n\r\n\t\tQString materialSID = *materialSIDs.begin();\r\n\t\tif ( node->childs.contains( materialSID ) )\r\n\t\t{\r\n\t\t\tSprite* pm = getBaseSprite( node->childs[materialSID], itemSID, materialSIDs );\r\n\t\t\tpm->applyEffect( node->effect );\r\n\t\t\tpm->applyTint( node->tint, materialSID );\r\n\t\t\tpm->hasTransp = node->hasTransp;\r\n\t\t\treturn pm;\r\n\t\t}\r\n\t\t// if no other hit\r\n\t\tif ( node->childs.size() )\r\n\t\t{\r\n\t\t\tif ( !node->defaultMaterial.isEmpty() && node->childs.contains( node->defaultMaterial ) )\r\n\t\t\t{\r\n\t\t\t\tSprite* pm = getBaseSprite( node->childs[node->defaultMaterial], itemSID, materialSIDs );\r\n\t\t\t\tpm->applyEffect( node->effect );\r\n\t\t\t\tpm->applyTint( node->tint, materialSID );\r\n\t\t\t\tpm->hasTransp = node->hasTransp;\r\n\t\t\t\treturn pm;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSprite* pm = getBaseSprite( node->childs.first(), itemSID, materialSIDs, materialID );\r\n\t\t\t\tpm->applyEffect( node->effect );\r\n\t\t\t\tpm->applyTint( node->tint, materialSID );\r\n\t\t\t\tpm->hasTransp = node->hasTransp;\r\n\t\t\t\treturn pm;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tQPixmap pm           = m_baseSprites.value( \"SolidSelectionWall\" );\r\n\tSpritePixmap* sprite = new SpritePixmap( pm );\r\n\tsprite->applyTint( \"Material\", \"JobPurple\" );\r\n\treturn sprite;\r\n}\r\n\r\nvoid SpriteFactory::getBaseSpriteDryRun( const DefNode* node, const QString itemSID, const QStringList materialSIDs, const QString season, const QString rotation, const int animFrame )\r\n{\r\n\tQString materialSID = *materialSIDs.begin();\r\n\tif ( !node->baseSprite.isEmpty() )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( node->childs.contains( rotation ) )\r\n\t{\r\n\t\tgetBaseSpriteDryRun( node->childs[rotation], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\treturn;\r\n\t}\r\n\tif ( node->childs.contains( season ) )\r\n\t{\r\n\t\tgetBaseSpriteDryRun( node->childs[season], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\treturn;\r\n\t}\r\n\tif ( node->childs.contains( itemSID ) )\r\n\t{\r\n\t\tgetBaseSpriteDryRun( node->childs[itemSID], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\treturn;\r\n\t}\r\n\tif ( node->childs.contains( \"Frame\" + QString::number( animFrame ) ) )\r\n\t{\r\n\t\tgetBaseSpriteDryRun( node->childs[\"Frame\" + QString::number( animFrame )], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( node->type == \"CombineNode\" && node->childs.size() > 1 )\r\n\t{\r\n\t\tgetBaseSpriteDryRun( node->childs[\"Combine0\"], itemSID, materialSIDs, season, rotation, animFrame );\r\n\r\n\t\tfor ( int i = 1; i < node->childs.size(); ++i )\r\n\t\t{\r\n\t\t\tgetBaseSpriteDryRun( node->childs[\"Combine\" + QString::number( i )], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\tif ( node->type == \"RandomNode\" )\r\n\t{\r\n\t\tQList<int> weights = node->randomWeights;\r\n\t\t//qDebug() << weights;\r\n\t\tint randomNumber = 0;\r\n\t\tif ( !m_randomNumbers.contains( node->childPos.toInt() ) )\r\n\t\t{\r\n\t\t\tif ( weights.contains( 0 ) )\r\n\t\t\t{\r\n\t\t\t\trandomNumber = rand() % node->childs.size();\r\n\t\t\t\tm_randomNumbers.insert( node->childPos.toInt(), randomNumber );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tint sum = 0;\r\n\t\t\t\tfor ( auto w : weights )\r\n\t\t\t\t\tsum += w;\r\n\t\t\t\tint ran   = rand() % sum;\r\n\t\t\t\tint total = 0;\r\n\t\t\t\tfor ( int i = 0; i < weights.size(); ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\ttotal += weights[i];\r\n\t\t\t\t\tif ( ran < total )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_randomNumbers.insert( node->childPos.toInt(), 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}\r\n\t\trandomNumber = m_randomNumbers.value( node->childPos.toInt() );\r\n\r\n\t\tgetBaseSpriteDryRun( node->childs[\"Random\" + QString::number( randomNumber )], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( materialSIDs.size() )\r\n\t{\r\n\t\tQString materialType = getMaterialType( materialSID );\r\n\t\tif ( node->childs.contains( materialType ) )\r\n\t\t{\r\n\t\t\tgetBaseSpriteDryRun( node->childs[materialType], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tQString materialSID = *materialSIDs.begin();\r\n\t\tif ( node->childs.contains( materialSID ) )\r\n\t\t{\r\n\t\t\tgetBaseSpriteDryRun( node->childs[materialSID], itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t// if no other hit\r\n\t\tif ( node->childs.size() )\r\n\t\t{\r\n\t\t\tgetBaseSpriteDryRun( node->childs.first(), itemSID, materialSIDs, season, rotation, animFrame );\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\treturn;\r\n}\r\n\r\nint SpriteFactory::numFrames( const DefNode* node, const QString itemSID, const QStringList materialSIDs, const QString season, const QString rotation )\r\n{\r\n\treturn 1;\r\n}\r\n\r\nQString SpriteFactory::getMaterialType( const QString materialSID )\r\n{\r\n\treturn m_materialTypes.value( materialSID );\r\n}\r\n\r\nSprite* SpriteFactory::getSprite( const int id )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tif ( m_sprites.size() > id )\r\n\t{\r\n\t\treturn m_sprites[id];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid SpriteFactory::printDebug()\r\n{\r\n\tfor ( auto si : m_spriteIDs.toStdMap() )\r\n\t{\r\n\t\tqDebug() << si.first << \" - \" << si.second;\r\n\t}\r\n}\r\n\r\nvoid SpriteFactory::createSprites( QList<SpriteCreation> scl )\r\n{\r\n\t//m_sprites.clear();\r\n\t//m_spriteIDs.clear();\r\n\r\n\t//createStandardSprites();\r\n\r\n\tfor ( auto sc : scl )\r\n\t{\r\n\t\tif ( sc.uID > 30 )\r\n\t\t{\r\n\t\t\tif ( sc.uID != static_cast<unsigned int>( m_sprites.size() ) )\r\n\t\t\t{\r\n\t\t\t\tif ( sc.uID < static_cast<unsigned int>( m_sprites.size() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tqWarning() << \"## Loosing sprite \" << sc.uID << m_sprites.size() << sc.itemSID << sc.materialSIDs;\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tqDebug() << \"## Missing sprite before \" << sc.uID << m_sprites.size() << sc.itemSID << sc.materialSIDs;\r\n\t\t\t\t\twhile ( sc.uID > static_cast<unsigned int>( m_sprites.size() ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\t// Sprite was probably lost due to a deleted definition, ID won't be reused\r\n\t\t\t\t\t\tm_sprites.append( nullptr );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif ( sc.creatureID )\r\n\t\t\t{\r\n\t\t\t\tif ( sc.creatureID == 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tcreateAnimalSprite( sc.itemSID, sc.random );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_creatureSpriteIDs.insert( sc.creatureID, sc.uID );\r\n\t\t\t\t\tm_sprites.append( nullptr );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tcreateSprite2( sc.itemSID, sc.materialSIDs, sc.random );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tqDebug() << \"Used\" << m_texesUsed << \"array textures\";\r\n\tm_spriteCreations = scl;\r\n}\r\n\r\nvoid SpriteFactory::addPixmapToPixelData( Sprite* sprite )\r\n{\r\n\tQString season = GameState::seasonString;\r\n\tif( season.isEmpty() )\r\n\t{\r\n\t\tseason = \"Spring\";\r\n\t}\r\n\tif ( sprite->anim )\r\n\t{\r\n\t\tfor ( int frame = 0; frame < 4; ++frame )\r\n\t\t{\r\n\t\t\tint tex     = ( sprite->uID + frame ) / 512;\r\n\t\t\tm_texesUsed = qMax( m_texesUsed, tex + 1 );\r\n\t\t\tint id      = ( sprite->uID + frame ) % 512;\r\n\r\n\t\t\tif ( m_pixelData.size() < tex + 1 )\r\n\t\t\t{\r\n\t\t\t\tint maxArrayTextures = Global::cfg->get( \"MaxArrayTextures\" ).toInt();\r\n\t\t\t\tint bytes            = 32 * 64 * 4 * maxArrayTextures;\r\n\r\n\t\t\t\tfor ( int i = 0; i < 32; ++i )\r\n\t\t\t\t{\r\n\t\t\t\t\tQVector<uint8_t> data( bytes );\r\n\t\t\t\t\tm_pixelData.push_back( data );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfor ( int i = 0; i < 4; ++i )\r\n\t\t\t{\r\n\t\t\t\tauto pm    = sprite->pixmap( season, i, frame );\r\n\t\t\t\tQImage img = pm.toImage();\r\n\r\n\t\t\t\tint startIndex = 8192 * ( 4 * id + i );\r\n\r\n\t\t\t\tif ( img.height() == 64 && img.width() == 32 )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto data = m_pixelData[tex].data();\r\n\t\t\t\t\tfor ( int y = 0; y < 64; ++y )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tQColor col = img.pixelColor( x, y );\r\n\t\t\t\t\t\t\tconst size_t baseIndex = startIndex + ( x * 4 + 128 * y );\r\n\t\t\t\t\t\t\tdata[baseIndex + 0]    = col.red();\r\n\t\t\t\t\t\t\tdata[baseIndex + 1]    = col.green();\r\n\t\t\t\t\t\t\tdata[baseIndex + 2]    = col.blue();\r\n\t\t\t\t\t\t\tdata[baseIndex + 3]    = col.alpha();\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\telse\r\n\t{\r\n\t\tint tex     = sprite->uID / 512;\r\n\t\tm_texesUsed = qMax( m_texesUsed, tex + 1 );\r\n\t\tint id      = sprite->uID % 512;\r\n\r\n\t\tif ( m_pixelData.size() < tex + 1 )\r\n\t\t{\r\n\t\t\tint maxArrayTextures = Global::cfg->get( \"MaxArrayTextures\" ).toInt();\r\n\t\t\tint bytes            = 32 * 64 * 4 * maxArrayTextures;\r\n\r\n\t\t\tfor ( int i = 0; i < 32; ++i )\r\n\t\t\t{\r\n\t\t\t\tQVector<uint8_t> data( bytes );\r\n\t\t\t\tm_pixelData.push_back( data );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor ( int i = 0; i < 4; ++i )\r\n\t\t{\r\n\t\t\tauto pm    = sprite->pixmap( season, i, 0 );\r\n\t\t\tQImage img = pm.toImage();\r\n\r\n\t\t\tint startIndex = 8192 * ( 4 * id + i );\r\n\r\n\t\t\tif ( img.height() == 64 && img.width() == 32 )\r\n\t\t\t{\r\n\t\t\t\tfor ( int y = 0; y < 64; ++y )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQColor col = img.pixelColor( x, y );\r\n\t\t\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y ), col.red() );\r\n\t\t\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 1 ), col.green() );\r\n\t\t\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 2 ), col.blue() );\r\n\t\t\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 3 ), col.alpha() );\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 SpriteFactory::addPixmapToPixelData32( Sprite* sprite )\r\n{\r\n\tint tex        = sprite->uID / 512;\r\n\tint id         = sprite->uID % 512;\r\n\tQString season = GameState::seasonString;\r\n\r\n\tfor ( int i = 0; i < 4; ++i )\r\n\t{\r\n\t\tauto pm    = sprite->pixmap( season, i, 0 );\r\n\t\tQImage img = pm.toImage();\r\n\r\n\t\tint startIndex = 8192 * ( 4 * id + i );\r\n\r\n\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t{\r\n\t\t\tfor ( int y = 0; y < 16; ++y )\r\n\t\t\t{\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y ), 0 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 1 ), 0 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 2 ), 0 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 3 ), 0 );\r\n\t\t\t}\r\n\r\n\t\t\tfor ( int y = 16; y < 48; ++y )\r\n\t\t\t{\r\n\t\t\t\tQColor col = img.pixelColor( x, y - 16 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y ), col.red() );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 1 ), col.green() );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 2 ), col.blue() );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 3 ), col.alpha() );\r\n\t\t\t}\r\n\t\t\tfor ( int y = 48; y < 64; ++y )\r\n\t\t\t{\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y ), 0 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 1 ), 0 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 2 ), 0 );\r\n\t\t\t\tm_pixelData[tex].replace( startIndex + ( x * 4 + 128 * y + 3 ), 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid SpriteFactory::addEmptyRows( int startIndex, int rows, QVector<uint8_t>& pixelData )\r\n{\r\n\tfor ( int y = 0; y < rows; ++y )\r\n\t{\r\n\t\tfor ( int x = 0; x < 32; ++x )\r\n\t\t{\r\n\t\t\tpixelData.replace( startIndex + ( x * 4 + 128 * y ), 0 );\r\n\t\t\tpixelData.replace( startIndex + ( x * 4 + 128 * y + 1 ), 0 );\r\n\t\t\tpixelData.replace( startIndex + ( x * 4 + 128 * y + 2 ), 0 );\r\n\t\t\tpixelData.replace( startIndex + ( x * 4 + 128 * y + 3 ), 0 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool SpriteFactory::textureAdded()\r\n{\r\n#if 1\r\n\tbool out       = m_textureAdded;\r\n\tm_textureAdded = false;\r\n\treturn out;\r\n#else\r\n\tif ( GameState::tick % 10 == 0 )\r\n\t{\r\n\t\tbool out       = m_textureAdded;\r\n\t\tm_textureAdded = false;\r\n\t\treturn out;\r\n\t}\r\n\treturn false;\r\n#endif\r\n}\r\n\r\nbool SpriteFactory::creatureTextureAdded()\r\n{\r\n#if 1\r\n\tbool out               = m_creatureTextureAdded;\r\n\tm_creatureTextureAdded = false;\r\n\treturn out;\r\n#else\r\n\tif ( GameState::tick % 10 == 0 )\r\n\t{\r\n\t\tbool out               = m_creatureTextureAdded;\r\n\t\tm_creatureTextureAdded = false;\r\n\t\treturn out;\r\n\t}\r\n\treturn false;\r\n#endif\r\n}\r\n\r\nvoid SpriteFactory::forceUpdate()\r\n{\r\n\tfor ( auto sprite : m_sprites )\r\n\t{\r\n\t\tif ( sprite )\r\n\t\t{\r\n\t\t\taddPixmapToPixelData( sprite );\r\n\t\t}\r\n\t}\r\n\tm_textureAdded = true;\r\n}\r\n\r\nQPixmap SpriteFactory::getTintedBaseSprite( QString baseSprite, QString material )\r\n{\r\n\tif ( baseSprite.isEmpty() )\r\n\t{\r\n\t\treturn m_baseSprites[\"EmptyWall\"];\r\n\t}\r\n\r\n\tQPixmap pm = m_baseSprites[baseSprite];\r\n\ttintPixmap( pm, Global::util->string2QColor( DBH::materialColor( material ) ) );\r\n\treturn pm;\r\n}\r\n\r\nSprite* SpriteFactory::setCreatureSprite( const unsigned int creatureUID, QVariantList components, QVariantList componentsBack, bool isDead )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tQPixmap pmfr( 32, 32 );\r\n\tpmfr.fill( QColor( 0, 0, 0, 0 ) );\r\n\tQPainter painter( &pmfr );\r\n\t//qDebug() << \" =================================================\";\r\n\tfor ( auto vcm : components )\r\n\t{\r\n\t\tauto cm = vcm.toMap();\r\n\t\tif ( cm.value( \"Hidden\" ).toBool() )\r\n\t\t\tcontinue;\r\n\r\n\t\tQString baseSprite = cm.value( \"BaseSprite\" ).toString();\r\n\r\n\t\t//if( !baseSprite.isEmpty() ) qDebug() << baseSprite << cm.value( \"Tint\" ).toString() << cm.value( \"Material\" ).toString();\r\n\r\n\t\tif ( cm.value( \"HasBase\" ).toBool() )\r\n\t\t{\r\n\t\t\tpainter.drawPixmap( 0, 0, m_baseSprites[baseSprite + \"Base\"] );\r\n\t\t}\r\n\r\n\t\tQString tint = cm.value( \"Tint\" ).toString();\r\n\t\tbool isHair  = cm.value( \"IsHair\" ).toBool();\r\n\t\tif ( tint.isEmpty() )\r\n\t\t{\r\n\t\t\tpainter.drawPixmap( 0, 0, m_baseSprites[baseSprite] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( tint == \"Material\" )\r\n\t\t\t{\r\n\t\t\t\tauto pm = getTintedBaseSprite( baseSprite, cm.value( \"Material\" ).toString() );\r\n\t\t\t\tpainter.drawPixmap( 0, 0, pm );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbool ok;\r\n\t\t\t\tint colorInt = tint.toInt( &ok );\r\n\t\t\t\tif ( ok )\r\n\t\t\t\t{\r\n\t\t\t\t\tQPixmap pm = m_baseSprites[baseSprite];\r\n\t\t\t\t\tif ( isHair )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttintPixmap( pm, m_hairColors[colorInt] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttintPixmap( pm, m_colors[colorInt] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpainter.drawPixmap( 0, 0, pm );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tQImage img   = pmfr.toImage();\r\n\tQPixmap pmfl = QPixmap::fromImage( img.mirrored( true, false ) );\r\n\r\n\tQPixmap pmbr( 32, 32 );\r\n\tpmbr.fill( QColor( 0, 0, 0, 0 ) );\r\n\tQPainter painter2( &pmbr );\r\n\t//qDebug() << \"---------------------------------\";\r\n\tfor ( auto vcm : componentsBack )\r\n\t{\r\n\t\tauto cm = vcm.toMap();\r\n\t\tif ( cm.value( \"Hidden\" ).toBool() )\r\n\t\t\tcontinue;\r\n\r\n\t\tQString baseSprite = cm.value( \"BaseSprite\" ).toString();\r\n\r\n\t\t//if( !baseSprite.isEmpty() ) qDebug() << baseSprite << cm.value( \"Tint\" ).toString() << cm.value( \"Material\" ).toString();\r\n\r\n\t\tif ( cm.value( \"HasBase\" ).toBool() )\r\n\t\t{\r\n\t\t\tpainter2.drawPixmap( 0, 0, m_baseSprites[baseSprite + \"Base\"] );\r\n\t\t}\r\n\t\tQString tint = cm.value( \"Tint\" ).toString();\r\n\t\tbool isHair  = cm.value( \"IsHair\" ).toBool();\r\n\t\tif ( tint.isEmpty() )\r\n\t\t{\r\n\t\t\tpainter2.drawPixmap( 0, 0, m_baseSprites[baseSprite] );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( tint == \"Material\" )\r\n\t\t\t{\r\n\t\t\t\tauto pm = getTintedBaseSprite( baseSprite, cm.value( \"Material\" ).toString() );\r\n\t\t\t\tpainter2.drawPixmap( 0, 0, pm );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tbool ok;\r\n\t\t\t\tint colorInt = tint.toInt( &ok );\r\n\t\t\t\tif ( ok )\r\n\t\t\t\t{\r\n\t\t\t\t\tQPixmap pm = m_baseSprites[baseSprite];\r\n\t\t\t\t\tif ( isHair )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttintPixmap( pm, m_hairColors[colorInt] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttintPixmap( pm, m_colors[colorInt] );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tpainter2.drawPixmap( 0, 0, pm );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\timg          = pmbr.toImage();\r\n\tQPixmap pmbl = QPixmap::fromImage( img.mirrored( true, false ) );\r\n\r\n\tSpritePixmap* sfr = nullptr;\r\n\tSpritePixmap* sfl = nullptr;\r\n\tSpritePixmap* sbl = nullptr;\r\n\tSpritePixmap* sbr = nullptr;\r\n\r\n\tif ( isDead )\r\n\t{\r\n\t\tsfr = new SpritePixmap( pmfr.transformed( QTransform().rotate( 90 ) ) );\r\n\t\tsfl = new SpritePixmap( pmfl.transformed( QTransform().rotate( 90 ) ) );\r\n\t\tsbl = new SpritePixmap( pmbl.transformed( QTransform().rotate( 90 ) ) );\r\n\t\tsbr = new SpritePixmap( pmbr.transformed( QTransform().rotate( 90 ) ) );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsfr = new SpritePixmap( pmfr );\r\n\t\tsfl = new SpritePixmap( pmfl );\r\n\t\tsbl = new SpritePixmap( pmbl );\r\n\t\tsbr = new SpritePixmap( pmbr );\r\n\t}\r\n\r\n\tSpriteRotations* sr = new SpriteRotations;\r\n\r\n\tsr->m_sprites.push_back( sfr );\r\n\tsr->m_sprites.push_back( sfl );\r\n\tsr->m_sprites.push_back( sbl );\r\n\tsr->m_sprites.push_back( sbr );\r\n\r\n\tif ( m_creatureSpriteIDs.contains( creatureUID ) )\r\n\t{\r\n\t\tSprite* oldSprite = m_sprites[m_creatureSpriteIDs.value( creatureUID )];\r\n\t\tif ( oldSprite )\r\n\t\t{\r\n\t\t\tdelete oldSprite;\r\n\t\t}\r\n\r\n\t\tsr->uID = m_creatureSpriteIDs.value( creatureUID );\r\n\t\tm_sprites.replace( sr->uID, sr );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsr->uID = m_sprites.size();\r\n\t\tm_creatureSpriteIDs.insert( creatureUID, sr->uID );\r\n\t\tm_sprites.append( sr );\r\n\r\n\t\tSpriteCreation sc { \"Creature\", { \"None\" }, m_randomNumbers, sr->uID, creatureUID };\r\n\t\tm_spriteCreations.push_back( sc );\r\n\t}\r\n\r\n\taddPixmapToPixelData32( sr );\r\n\r\n\tm_creatureTextureAdded = true;\r\n\r\n\t/*\r\n\tQString season = GameState::season\" ).toString();\r\n\tQImage img_ = sr->pixmap( season, 0, 0 ).toImage();\r\n\timg_.save( \"d:/tmp/gnome/gnome\" + QString::number( creatureUID ) + \"_\" + QString::number( 0 ) + \".png\", \"PNG\" );\r\n\timg_ = sr->pixmap( season, 1, 0 ).toImage();\r\n\timg_.save( \"d:/tmp/gnome/gnome\" + QString::number( creatureUID ) + \"_\" + QString::number( 1 ) + \".png\", \"PNG\" );\r\n\timg_ = sr->pixmap( season, 2, 0 ).toImage();\r\n\timg_.save( \"d:/tmp/gnome/gnome\" + QString::number( creatureUID ) + \"_\" + QString::number( 2 ) + \".png\", \"PNG\" );\r\n\timg_ = sr->pixmap( season, 3, 0 ).toImage();\r\n\timg_.save( \"d:/tmp/gnome/gnome\" + QString::number( creatureUID ) + \"_\" + QString::number( 3 ) + \".png\", \"PNG\" );\r\n\t*/\r\n\treturn sr;\r\n}\r\n\r\nSprite* SpriteFactory::getCreatureSprite( const unsigned int id, unsigned int& spriteID )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\tif ( m_creatureSpriteIDs.contains( id ) )\r\n\t{\r\n\t\tspriteID = m_creatureSpriteIDs[id];\r\n\t\treturn m_sprites[m_creatureSpriteIDs[id]];\r\n\t}\r\n\treturn nullptr;\r\n}\r\n\r\nvoid SpriteFactory::tintPixmap( QPixmap& pm, QColor color )\r\n{\r\n\tQImage img = pm.toImage();\r\n\r\n\tfor ( int x = 0; x < img.size().width(); ++x )\r\n\t{\r\n\t\tfor ( int y = 0; y < img.size().height(); ++y )\r\n\t\t{\r\n\t\t\tQColor col = img.pixelColor( x, y );\r\n\t\t\tcol.setRedF( qMin( 1., col.redF() * color.redF() ) );\r\n\t\t\tcol.setGreenF( qMin( 1., col.greenF() * color.greenF() ) );\r\n\t\t\tcol.setBlueF( qMin( 1., col.blueF() * color.blueF() ) );\r\n\t\t\tcol.setAlphaF( qMin( 1., col.alphaF() * color.alphaF() ) );\r\n\t\t\timg.setPixelColor( x, y, col );\r\n\t\t}\r\n\t}\r\n\tpm = QPixmap::fromImage( img );\r\n}\r\n\r\nQStringList SpriteFactory::pixmaps()\r\n{\r\n\treturn m_pixmapSources.keys();\r\n}\r\n\r\nQPixmap SpriteFactory::pixmap( QString name )\r\n{\r\n\tif ( m_pixmapSources.contains( name ) )\r\n\t{\r\n\t\treturn m_pixmapSources[name];\r\n\t}\r\n\tqDebug() << \"Pixmap \" << name << \" doesn't exist\";\r\n\treturn QPixmap( 32, 32 );\r\n}\r\n\r\nQPixmap SpriteFactory::baseSprite( QString id )\r\n{\r\n\tif ( m_baseSprites.contains( id ) )\r\n\t{\r\n\t\treturn m_baseSprites[id];\r\n\t}\r\n\tqDebug() << \"Base sprite \" << id << \" doesn't exist\";\r\n\treturn QPixmap( 32, 32 );\r\n}\r\n\r\nunsigned int SpriteFactory::thoughtBubbleID( QString sid )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\treturn m_thoughtBubbleIDs.value( sid );\r\n}\r\n\r\nint SpriteFactory::texesUsed()\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\treturn m_texesUsed;\r\n}\r\n\r\nunsigned int SpriteFactory::size()\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\treturn m_spriteIDs.size();\r\n}\r\n\r\nQVector<uint8_t> SpriteFactory::pixelData( int index )\r\n{\r\n\tQMutexLocker ml( &m_mutex );\r\n\treturn m_pixelData[index];\r\n}"
  },
  {
    "path": "src/gfx/spritefactory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../gfx/sprite.h\"\r\n\r\n#include <QBitmap>\r\n#include <QGraphicsPixmapItem>\r\n#include <QPixmap>\r\n#include <QVector>\r\n\r\nstruct DefNode\r\n{\r\n\tDefNode()\r\n\t{\r\n\t\t//parent = 0;\r\n\r\n\t\ttype       = \"\";\r\n\t\toffset     = \"\";\r\n\t\teffect     = \"\";\r\n\t\ttint       = \"\";\r\n\t\tvalue      = \"\";\r\n\t\tbaseSprite = \"\";\r\n\t\tdepth      = 0;\r\n\t\tchildPos   = \"1\";\r\n\t\tnumFrames  = 1;\r\n\t};\r\n\t~DefNode()\r\n\t{\r\n\t\tfor( auto& child : childs )\r\n\t\t{\r\n\t\t\tdelete child;\r\n\t\t}\r\n\t}\r\n\r\n\tQString type;\r\n\tQString offset;\r\n\tQString effect;\r\n\tQString tint;\r\n\tQString value;\r\n\tQString baseSprite;\r\n\tQString defaultMaterial;\r\n\tint depth;\r\n\tint numFrames;\r\n\tQString childPos;\r\n\tQList<int> randomWeights;\r\n\tbool rot90 = false;\r\n\tbool hasTransp = false;\r\n\r\n\t//DefNode* parent;\r\n\tQMap<QString, DefNode*> childs;\r\n};\r\n\r\nstruct SpriteCreation\r\n{\r\n\tQString itemSID;\r\n\tQStringList materialSIDs;\r\n\tQMap<int, int> random;\r\n\tunsigned int uID        = 0;\r\n\tunsigned int creatureID = 0;\r\n};\r\n\r\nclass SpriteFactory\r\n{\r\nprivate:\r\n\tvoid parseDef( DefNode* parent, QVariantMap def );\r\n\r\n\tSprite* createSpriteMaterial( const QString itemSID, const QStringList materialSIDs, const QString key );\r\n\tSprite* getBaseSprite( const DefNode* node, const QString itemSID, const QStringList materialSIDs, int materialID = 0 );\r\n\r\n\tQString createSpriteMaterialDryRun( const QString itemSID, const QStringList materialSIDs );\r\n\tvoid getBaseSpriteDryRun( const DefNode* node, const QString itemSID, const QStringList materialSIDs, const QString season, const QString rotation, const int animFrame );\r\n\r\n\tint numFrames( const DefNode* node, const QString itemSID, const QStringList materialSIDs, const QString season, const QString rotation );\r\n\tbool containsRandom( const QString itemSID, const QStringList materialSIDs );\r\n\r\n\tQString getMaterialType( const QString materialSID );\r\n\r\n\tQPixmap extractPixmap( QString sourcePNG, QVariantMap def );\r\n\tunsigned char rotationToChar( QString suffix );\r\n\r\n\t// base sprites and sources for creation\r\n\tQHash<QString, QPixmap> m_pixmapSources;\r\n\tQMap<QString, QPixmap> m_baseSprites;\r\n\tQMap<QString, DefNode*> m_spriteDefinitions;\r\n\tQMap<QString, QVariantMap> m_spriteDefVMs;\r\n\r\n\tQMap<QString, unsigned int> m_thoughtBubbleIDs;\r\n\r\n\t// cached DB values for faster lookup\r\n\tQStringList m_seasons;\r\n\tQMap<QString, QString> m_materialTypes;\r\n\r\n\t//pixel data for array textures\r\n\tQVector<QVector<uint8_t>> m_pixelData;\r\n\tint m_texesUsed = 0;\r\n\r\n\tbool m_textureAdded         = false;\r\n\tbool m_creatureTextureAdded = false;\r\n\r\n\t// intermediate variables during sprite creation\r\n\tQString m_offset  = \"\";\r\n\tfloat m_opacity   = 1.0;\r\n\tfloat m_numFrames = 1;\r\n\tQMap<int, int> m_randomNumbers;\r\n\r\n\tQList<QColor> m_colors;\r\n\tQList<QColor> m_hairColors;\r\n\r\n\t// created sprites for current game\r\n\tQList<Sprite*> m_sprites;\r\n\r\n\tQMap<QString, int> m_spriteIDs;\r\n\tQMap<unsigned int, int> m_creatureSpriteIDs;\r\n\r\n\tQList<SpriteCreation> m_spriteCreations;\r\n\r\n\tvoid addPixmapToPixelData( Sprite* sprite );\r\n\tvoid addPixmapToPixelData32( Sprite* sprite );\r\n\r\n\tvoid addEmptyRows( int startIndex, int rows, QVector<uint8_t>& pixelData );\r\n\r\n\tvoid tintPixmap( QPixmap& pm, QColor color );\r\n\r\n\tvoid createStandardSprites();\r\n\r\n\tQPixmap getTintedBaseSprite( QString baseSprite, QString material );\r\n\r\n\tSprite* createSprite2( const QString itemSID, QStringList materialSID, const QMap<int, int>& random = QMap<int, int>() );\r\n\t\r\n\tvoid printDebug();\r\n\r\n\tQStringList pixmaps();\r\n\tQPixmap pixmap( QString name );\r\n\r\n\tQPixmap baseSprite( QString id );\r\n\r\n\tQMutex m_mutex;\r\n\r\n\tbool init();\r\n\r\npublic:\r\n\tSpriteFactory();\r\n\t~SpriteFactory();\r\n\r\n\t\r\n\r\n\tSprite* createSprite( const QString itemSID, QStringList materialSID, const QMap<int, int>& random = QMap<int, int>() );\r\n\tSprite* createAnimalSprite( const QString spriteSID, const QMap<int, int>& random = QMap<int, int>() );\r\n\tSprite* getSprite( const int id );\r\n\r\n\tSprite* setCreatureSprite( const unsigned int gnomeUID, QVariantList components, QVariantList componentsBack, bool isDead = false );\r\n\t//unsigned int setAutomatonSprite( const unsigned int automatonID, const unsigned int id );\r\n\tSprite* getCreatureSprite( const unsigned int id, unsigned int& spriteID );\r\n\r\n\tQList<SpriteCreation> spriteCreations()\r\n\t{\r\n\t\treturn m_spriteCreations;\r\n\t}\r\n\r\n\tvoid createSprites( QList<SpriteCreation> scl );\r\n\r\n\t\r\n\r\n\tbool textureAdded();\r\n\tbool creatureTextureAdded();\r\n\r\n\tvoid forceUpdate();\r\n\r\n\tvoid addPixmapSource( QString name, QString path );\r\n\r\n\tunsigned int thoughtBubbleID( QString sid );\r\n\t\r\n\tint texesUsed();\r\n\t\r\n\tunsigned int size();\r\n\t\r\n\tQVector<uint8_t> pixelData( int index );\r\n\t\r\n};"
  },
  {
    "path": "src/gui/aggregatoragri.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatoragri.h\"\r\n#include \"../game/game.h\"\r\n\r\n#include \"../base/counter.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/util.h\"\r\n\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include \"../gui/strings.h\"\r\n\r\n\r\n\r\n#include <QDebug>\r\n\r\nAggregatorAgri::AggregatorAgri( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\tqRegisterMetaType<GuiFarmInfo>();\r\n\tqRegisterMetaType<GuiPastureInfo>();\r\n\tqRegisterMetaType<GuiGroveInfo>();\r\n\tqRegisterMetaType<QList<GuiPlant>>();\r\n\tqRegisterMetaType<QList<GuiAnimal>>();\r\n}\r\n\r\nvoid AggregatorAgri::init( Game* game )\r\n{\r\n\tg = game;\r\n\tm_globalPlantInfo.clear();\r\n\tQStringList keys = DB::ids( \"Plants\" );\r\n\tkeys.sort();\r\n\tfor ( auto key : keys )\r\n\t{\r\n\t\tauto plantRow = DB::selectRow( \"Plants\", key );\r\n\t\tif ( plantRow.value( \"Type\" ).toString() == \"Plant\" )\r\n\t\t{\r\n\t\t\tGuiPlant gp;\r\n\t\t\tgp.plantID       = key;\r\n\t\t\tgp.seedID        = plantRow.value( \"SeedItemID\" ).toString();\r\n\t\t\tgp.materialID    = plantRow.value( \"Material\" ).toString();\r\n\t\t\tgp.seedCount     = 0;\r\n\t\t\tgp.harvestedItem = DB::select( \"ItemID\", \"Plants_OnHarvest_HarvestedItem\", key ).toString();\r\n\t\t\tgp.name          = S::s( \"$MaterialName_\" + gp.materialID );\r\n\t\t\tgp.sprite\t\t = Global::util->smallPixmap( g->sf()->createSprite( gp.harvestedItem, { gp.materialID } ), GameState::seasonString, 0 );\r\n\t\t\tm_globalPlantInfo.append( gp );\r\n\r\n\t\t\t//QIcon icon = Global::util->smallPixmap( g->sf()->createSprite( harvestedItemID, { material } ), season, 0 );\r\n\t\t}\r\n\t}\r\n\r\n\tm_globalTreeInfo.clear();\r\n\tkeys = DB::ids( \"Plants\" );\r\n\tkeys.sort();\r\n\tfor ( auto key : keys )\r\n\t{\r\n\t\tauto plantRow = DB::selectRow( \"Plants\", key );\r\n\t\tif ( plantRow.value( \"Type\" ).toString() == \"Tree\" )\r\n\t\t{\r\n\t\t\tGuiPlant gp;\r\n\t\t\tgp.plantID       = key;\r\n\t\t\tgp.seedID        = plantRow.value( \"SeedItemID\" ).toString();\r\n\t\t\tgp.materialID    = plantRow.value( \"Material\" ).toString();\r\n\t\t\tgp.sprite        = Global::util->smallPixmap( g->sf()->createSprite( plantRow.value( \"ToolButtonSprite\" ).toString(), { gp.materialID } ), GameState::seasonString, 0 );\r\n\t\t\tgp.seedCount     = 0;\r\n\t\t\tgp.harvestedItem = DB::select( \"ItemID\", \"Plants_OnHarvest_HarvestedItem\", key ).toString();\r\n\t\t\tgp.name          = S::s( \"$MaterialName_\" + gp.materialID );\r\n\t\t\t\r\n\r\n\t\t\tm_globalTreeInfo.append( gp );\r\n\r\n\t\t\t//QIcon icon = Global::util->smallPixmap( g->sf()->createSprite( harvestedItemID, { material } ), GameState::seasonString, 0 );\r\n\t\t}\r\n\t}\r\n\r\n\tm_globalAnimalInfo.clear();\r\n\tkeys = DB::ids( \"Animals\" );\r\n\tkeys.sort();\r\n\tfor ( auto key : keys )\r\n\t{\r\n\t\tauto animalRow = DB::selectRow( \"Animals\", key );\r\n\t\tif ( animalRow.value( \"Pasture\" ).toBool() )\r\n\t\t{\r\n\t\t\tGuiAnimal ga;\r\n\t\t\tga.animalID   = key;\r\n\t\t\tga.materialID = key;\r\n\t\t\tga.name       = S::s( \"$CreatureName_\" + key );\r\n\r\n\t\t\tfor ( auto sm : DB::selectRows( \"Animals_States\", key ) )\r\n\t\t\t{\r\n\t\t\t\tif ( sm.value( \"ID2\" ).toString() == \"Adult\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tga.sprite = Global::util->smallPixmap( g->sf()->createAnimalSprite( sm.value( \"SpriteID\" ).toString() ), GameState::seasonString, 0 );\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tm_globalAnimalInfo.append( ga );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nAggregatorAgri::~AggregatorAgri()\r\n{\r\n}\r\n\r\nvoid AggregatorAgri::onCloseWindow()\r\n{\r\n\tm_farmInfo.ID    = 0;\r\n\tm_pastureInfo.ID = 0;\r\n\tm_groveInfo.ID   = 0;\r\n\tm_currentTileID  = 0;\r\n}\r\n\r\nvoid AggregatorAgri::onOpen( TileFlag designation, unsigned int tileID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_currentTileID != tileID )\r\n\t{\r\n\t\tm_currentTileID = tileID;\r\n\r\n\t\tswitch ( designation )\r\n\t\t{\r\n\t\t\tcase TileFlag::TF_FARM:\r\n\t\t\t{\r\n\t\t\t\tauto farm = g->fm()->getFarmAtPos( Position( tileID ) );\r\n\t\t\t\tif ( farm )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_farmInfo.ID    = farm->id();\r\n\t\t\t\t\tm_pastureInfo.ID = 0;\r\n\t\t\t\t\tm_groveInfo.ID   = 0;\r\n\t\t\t\t\tonUpdateFarm( m_farmInfo.ID );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase TileFlag::TF_PASTURE:\r\n\t\t\t{\r\n\t\t\t\tauto pasture = g->fm()->getPastureAtPos( Position( tileID ) );\r\n\t\t\t\tif ( pasture )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_pastureInfo.ID = pasture->id();\r\n\t\t\t\t\tm_farmInfo.ID    = 0;\r\n\t\t\t\t\tm_groveInfo.ID   = 0;\r\n\t\t\t\t\tonUpdatePasture( m_pastureInfo.ID );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tcase TileFlag::TF_GROVE:\r\n\t\t\t{\r\n\t\t\t\tauto grove = g->fm()->getGroveAtPos( Position( tileID ) );\r\n\t\t\t\tif ( grove )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_groveInfo.ID   = grove->id();\r\n\t\t\t\t\tm_farmInfo.ID    = 0;\r\n\t\t\t\t\tm_pastureInfo.ID = 0;\r\n\t\t\t\t\tonUpdateGrove( m_groveInfo.ID );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\temit signalShowAgri( tileID );\r\n}\r\n\r\nvoid AggregatorAgri::onRequestGlobalPlantInfo()\r\n{\r\n\temit signalGlobalPlantInfo( m_globalPlantInfo );\r\n}\r\n\r\nvoid AggregatorAgri::onRequestGlobalTreeInfo()\r\n{\r\n\temit signalGlobalTreeInfo( m_globalTreeInfo );\r\n}\r\n\r\nvoid AggregatorAgri::onRequestGlobalAnimalInfo()\r\n{\r\n\temit signalGlobalAnimalInfo( m_globalAnimalInfo );\r\n}\r\n\r\nvoid AggregatorAgri::onUpdate( unsigned int designationID )\r\n{\r\n\t//qDebug() << \"AggregatorAgri::onUpdate\";\r\n\tif ( m_farmInfo.ID == designationID )\r\n\t{\r\n\t\tonUpdateFarm( designationID );\r\n\t}\r\n\telse if ( m_pastureInfo.ID == designationID )\r\n\t{\r\n\t\tonUpdatePasture( designationID );\r\n\t}\r\n\telse if ( m_groveInfo.ID == designationID )\r\n\t{\r\n\t\tonUpdateGrove( designationID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onUpdateFarm( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onUpdateFarm\";\r\n\tif ( m_farmInfo.ID == id )\r\n\t{\r\n\t\tauto farm = g->fm()->getFarm( id );\r\n\t\tif ( farm )\r\n\t\t{\r\n\t\t\tfarm->getInfo( m_farmInfo.numPlots, m_farmInfo.tilled, m_farmInfo.planted, m_farmInfo.cropReady );\r\n\t\t\t/*\r\n\t\t\tfor( auto& gp : m_globalPlantInfo )\r\n\t\t\t{\r\n\t\t\t\tgp.seedCount = m_inv->itemCount( gp.seedID, gp.materialID );\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t\tm_farmInfo.suspended   = farm->suspended();\r\n\t\t\tm_farmInfo.name        = farm->name();\r\n\t\t\tm_farmInfo.priority    = g->fm()->farmPriority( id );\r\n\t\t\tm_farmInfo.maxPriority = g->fm()->countFarms();\r\n\t\t\tm_farmInfo.harvest     = farm->harvest();\r\n\t\t\tm_farmInfo.plantType   = farm->plantType();\r\n\r\n\t\t\tif ( m_farmInfo.product.plantID != m_farmInfo.plantType )\r\n\t\t\t{\r\n\t\t\t\tonRequestProductInfo( AgriType::Farm, m_farmInfo.ID );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\temit signalUpdateFarm( m_farmInfo );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onUpdatePasture( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onUpdatePasture\";\r\n\tif ( m_pastureInfo.ID == id )\r\n\t{\r\n\t\tauto past = g->fm()->getPasture( id );\r\n\t\tif ( past )\r\n\t\t{\r\n\t\t\tm_pastureInfo.suspended   = past->suspended();\r\n\t\t\tm_pastureInfo.name        = past->name();\r\n\t\t\tm_pastureInfo.priority    = g->fm()->pasturePriority( id );\r\n\t\t\tm_pastureInfo.maxPriority = g->fm()->countPastures();\r\n\t\t\tm_pastureInfo.animalType  = past->animalType();\r\n\t\t\tm_pastureInfo.harvest     = past->harvest();\r\n\t\t\tm_pastureInfo.harvestHay  = past->harvestHay();\r\n\t\t\tm_pastureInfo.hayMax      = past->maxHay();\r\n\t\t\tm_pastureInfo.hayCurrent  = g->inv()->itemCount( \"Hay\", \"Grass\" );\r\n\t\t\tm_pastureInfo.foodMax     = past->maxFoodLevel();\r\n\t\t\tm_pastureInfo.foodCurrent = past->foodLevel();\r\n\r\n\t\t\tm_pastureInfo.food.clear();\r\n\t\t\tif ( !past->animalType().isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tpast->getInfo( m_pastureInfo.numPlots, m_pastureInfo.numMale, m_pastureInfo.numFemale );\r\n\t\t\t\tm_pastureInfo.animalSize = past->animalSize();\r\n\t\t\t\tm_pastureInfo.maxNumber  = past->maxNumber();\r\n\t\t\t\tm_pastureInfo.maxMale    = past->m_properties.maxMale;\r\n\t\t\t\tm_pastureInfo.maxFemale  = past->m_properties.maxFemale;\r\n\t\t\t\tm_pastureInfo.total      = m_pastureInfo.numMale + m_pastureInfo.numFemale;\r\n\r\n\t\t\t\tauto foodSettings = past->foodSettings();\r\n\r\n\t\t\t\tauto foods = DB::select( \"Food\", \"Animals\", past->animalType() ).toString();\r\n\r\n\t\t\t\tfor( auto food : foods.split( \"|\" ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto mats = g->inv()->materialsForItem( food, 0 );\r\n\r\n\t\t\t\t\tfor( auto mat : mats )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQString name = S::s( \"$MaterialName_\" + mat ) + \" \" + S::s( \"$ItemName_\" + food );\r\n\t\t\t\t\t\tGuiPastureFoodItem pfi;\r\n\t\t\t\t\t\tpfi.itemSID = food;\r\n\t\t\t\t\t\tpfi.materialSID = mat;\r\n\t\t\t\t\t\tpfi.name = name;\r\n\t\t\t\t\t\tpfi.checked = foodSettings.contains( food + \"_\" + mat );\r\n\t\t\t\t\t\tpfi.sprite = Global::util->smallPixmap( g->sf()->createSprite( food, { mat } ), GameState::seasonString, 0 );\r\n\t\t\t\t\t\tm_pastureInfo.food.append( pfi );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_pastureInfo.numPlots   = 0;\r\n\t\t\t\tm_pastureInfo.numMale    = 0;\r\n\t\t\t\tm_pastureInfo.numFemale  = 0;\r\n\t\t\t\tm_pastureInfo.maxMale    = 0;\r\n\t\t\t\tm_pastureInfo.maxFemale  = 0;\r\n\t\t\t\tm_pastureInfo.total      = 0;\r\n\t\t\t\tm_pastureInfo.maxNumber  = 0;\r\n\t\t\t\tm_pastureInfo.animalSize = 0;\r\n\t\t\t\tm_pastureInfo.hayMax     = 0;\r\n\t\t\t\tm_pastureInfo.hayCurrent = 0;\r\n\t\t\t\tm_pastureInfo.foodMax    = 0;\r\n\t\t\t\tm_pastureInfo.foodCurrent= 0;\r\n\t\t\t}\r\n\r\n\t\t\tonRequestProductInfo( AgriType::Pasture, m_pastureInfo.ID );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tqDebug() << \"but no update\";\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onUpdateGrove( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onUpdateGrove\";\r\n\tif ( m_groveInfo.ID == id )\r\n\t{\r\n\t\tauto grove = g->fm()->getGrove( id );\r\n\t\tif ( grove )\r\n\t\t{\r\n\t\t\t//grove->getInfo( m_farmInfo.numPlots, m_farmInfo.tilled, m_farmInfo.planted, m_farmInfo.cropReady );\r\n\t\t\t/*\r\n\t\t\tfor( auto& gp : m_globalPlantInfo )\r\n\t\t\t{\r\n\t\t\t\tgp.seedCount = m_inv->itemCount( gp.seedID, gp.materialID );\r\n\t\t\t}\r\n\t\t\t*/\r\n\t\t\tm_groveInfo.suspended   = grove->suspended();\r\n\t\t\tm_groveInfo.name        = grove->name();\r\n\t\t\tm_groveInfo.priority    = g->fm()->farmPriority( id );\r\n\t\t\tm_groveInfo.maxPriority = g->fm()->countFarms();\r\n\r\n\t\t\tauto props             = grove->properties();\r\n\t\t\tm_groveInfo.pickFruits = props.pickFruit;\r\n\t\t\tm_groveInfo.plantTrees = props.plant;\r\n\t\t\tm_groveInfo.fellTrees  = props.fell;\r\n\t\t\tm_groveInfo.treeType   = props.treeType;\r\n\t\t\tm_groveInfo.planted\t   = grove->numTrees();\r\n\t\t\tm_groveInfo.numPlots   = grove->numPlots();\r\n\r\n\t\t\tif ( m_groveInfo.product.plantID != m_groveInfo.treeType )\r\n\t\t\t{\r\n\t\t\t\tonRequestProductInfo( AgriType::Grove, m_groveInfo.ID );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\temit signalUpdateGrove( m_groveInfo );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onSetBasicOptions( AgriType type, unsigned int designationID, QString name, int priority, bool suspended )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onSetBasicOptions\";\r\n\tif ( m_farmInfo.ID == designationID || m_pastureInfo.ID == designationID || m_groveInfo.ID == designationID )\r\n\t{\r\n\t\tswitch ( type )\r\n\t\t{\r\n\t\t\tcase AgriType::Farm:\r\n\t\t\t{\r\n\t\t\t\tauto farm = g->fm()->getFarm( designationID );\r\n\t\t\t\tif ( farm )\r\n\t\t\t\t{\r\n\t\t\t\t\tfarm->setName( name );\r\n\t\t\t\t\tfarm->setSuspended( suspended );\r\n\t\t\t\t\tg->fm()->setFarmPriority( designationID, priority );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Pasture:\r\n\t\t\t{\r\n\t\t\t\tauto pasture = g->fm()->getPasture( designationID );\r\n\t\t\t\tif ( pasture )\r\n\t\t\t\t{\r\n\t\t\t\t\tpasture->setName( name );\r\n\t\t\t\t\tpasture->setSuspended( suspended );\r\n\t\t\t\t\tg->fm()->setPasturePriority( designationID, priority );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Grove:\r\n\t\t\t{\r\n\t\t\t\tauto grove = g->fm()->getGrove( designationID );\r\n\t\t\t\tif ( grove )\r\n\t\t\t\t{\r\n\t\t\t\t\tgrove->setName( name );\r\n\t\t\t\t\tgrove->setSuspended( suspended );\r\n\t\t\t\t\tg->fm()->setGrovePriority( designationID, priority );\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onSelectProduct( AgriType type, unsigned designationID, QString productSID )\r\n{\r\n\tif( !g ) return;\r\n\t//collect info\r\n\t//qDebug() << \"AggregatorAgri::onSelectProduct\";\r\n\tif ( m_farmInfo.ID == designationID || m_pastureInfo.ID == designationID || m_groveInfo.ID == designationID )\r\n\t{\r\n\t\tswitch ( type )\r\n\t\t{\r\n\t\t\tcase AgriType::Farm:\r\n\t\t\t{\r\n\t\t\t\tauto farm = g->fm()->getFarm( designationID );\r\n\t\t\t\tif ( farm )\r\n\t\t\t\t{\r\n\t\t\t\t\tfarm->setPlantType( productSID );\r\n\t\t\t\t\tm_farmInfo.plantType = productSID;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Pasture:\r\n\t\t\t{\r\n\t\t\t\tauto pasture = g->fm()->getPasture( designationID );\r\n\t\t\t\tif ( pasture )\r\n\t\t\t\t{\r\n\t\t\t\t\tpasture->setAnimalType( productSID );\r\n\t\t\t\t\tm_pastureInfo.animalType = productSID;\r\n\t\t\t\t\tonUpdatePasture( designationID );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Grove:\r\n\t\t\t{\r\n\t\t\t\tauto grove = g->fm()->getGrove( designationID );\r\n\t\t\t\tif ( grove )\r\n\t\t\t\t{\r\n\t\t\t\t\tgrove->properties().treeType = productSID;\r\n\t\t\t\t\tm_groveInfo.treeType         = productSID;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t\tonRequestProductInfo( type, designationID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onSetHarvestOptions( AgriType type, unsigned int designationID, bool harvest, bool harvestHay, bool tame )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onSetHarvestOptions\";\r\n\tif ( m_farmInfo.ID == designationID || m_pastureInfo.ID == designationID || m_groveInfo.ID == designationID )\r\n\t{\r\n\t\tswitch ( type )\r\n\t\t{\r\n\t\t\tcase AgriType::Farm:\r\n\t\t\t{\r\n\t\t\t\tauto farm = g->fm()->getFarm( designationID );\r\n\t\t\t\tif ( farm )\r\n\t\t\t\t{\r\n\t\t\t\t\tfarm->setHarvest( harvest );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Pasture:\r\n\t\t\t{\r\n\t\t\t\tauto past = g->fm()->getPasture( designationID );\r\n\t\t\t\tif ( past )\r\n\t\t\t\t{\r\n\t\t\t\t\tpast->setHarvest( harvest );\r\n\t\t\t\t\tpast->setHarvestHay( harvestHay );\r\n\t\t\t\t\tpast->setTameWild( tame );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onSetGroveOptions( unsigned int groveID, bool pick, bool plant, bool fell )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onSetGroveOptions\";\r\n\tif ( m_groveInfo.ID == groveID )\r\n\t{\r\n\t\tauto grove = g->fm()->getGrove( groveID );\r\n\t\tif ( grove )\r\n\t\t{\r\n\t\t\tauto& props     = grove->properties();\r\n\t\t\tprops.pickFruit = pick;\r\n\t\t\tprops.plant     = plant;\r\n\t\t\tprops.fell      = fell;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onRequestProductInfo( AgriType type, unsigned int designationID )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onRequestProductInfo\";\r\n\tif ( m_farmInfo.ID == designationID || m_pastureInfo.ID == designationID || m_groveInfo.ID == designationID )\r\n\t{\r\n\t\tswitch ( type )\r\n\t\t{\r\n\t\t\tcase AgriType::Farm:\r\n\t\t\t{\r\n\t\t\t\tauto farm = g->fm()->getFarm( designationID );\r\n\t\t\t\tif ( farm )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto plantRow = DB::selectRow( \"Plants\", m_farmInfo.plantType );\r\n\t\t\t\t\tGuiPlant gp;\r\n\t\t\t\t\tif ( plantRow.value( \"Type\" ).toString() == \"Plant\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgp.plantID    = m_farmInfo.plantType;\r\n\t\t\t\t\t\tgp.seedID     = plantRow.value( \"SeedItemID\" ).toString();\r\n\t\t\t\t\t\tgp.materialID = plantRow.value( \"Material\" ).toString();\r\n\t\t\t\t\t\tgp.seedCount  = g->inv()->itemCount( gp.seedID, gp.materialID );\r\n\r\n\t\t\t\t\t\tgp.harvestedItem = DB::select( \"ItemID\", \"Plants_OnHarvest_HarvestedItem\", m_farmInfo.plantType ).toString();\r\n\t\t\t\t\t\tgp.itemCount     = g->inv()->itemCount( gp.plantID, gp.materialID );\r\n\r\n\t\t\t\t\t\tgp.name = S::s( \"$MaterialName_\" + gp.materialID );\r\n\r\n\t\t\t\t\t\tgp.sprite = Global::util->smallPixmap( g->sf()->createSprite( gp.harvestedItem, { gp.materialID } ), GameState::seasonString, 0 );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_farmInfo.product = gp;\r\n\t\t\t\t\temit signalUpdateFarm( m_farmInfo );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Pasture:\r\n\t\t\t{\r\n\t\t\t\tauto pasture = g->fm()->getPasture( designationID );\r\n\t\t\t\tif ( pasture )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto animalRow = DB::selectRow( \"Animals\", m_pastureInfo.animalType );\r\n\t\t\t\t\tGuiAnimal ga;\r\n\t\t\t\t\tif ( animalRow.value( \"Pasture\" ).toBool() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tga.animalID   = m_pastureInfo.animalType;\r\n\t\t\t\t\t\tga.materialID = m_pastureInfo.animalType;\r\n\t\t\t\t\t\tga.name       = S::s( \"$CreatureName_\" + m_pastureInfo.animalType );\r\n\r\n\t\t\t\t\t\tif ( !pasture->animalType().isEmpty() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tpasture->getInfo( m_pastureInfo.numPlots, m_pastureInfo.numMale, m_pastureInfo.numFemale );\r\n\t\t\t\t\t\t\tm_pastureInfo.animalSize = pasture->animalSize();\r\n\t\t\t\t\t\t\tm_pastureInfo.maxNumber  = pasture->maxNumber();\r\n\t\t\t\t\t\t\tm_pastureInfo.maxMale    = pasture->m_properties.maxMale;\r\n\t\t\t\t\t\t\tm_pastureInfo.maxFemale  = pasture->m_properties.maxFemale;\r\n\t\t\t\t\t\t\tm_pastureInfo.total      = m_pastureInfo.numMale + m_pastureInfo.numFemale;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfor ( auto sm : DB::selectRows( \"Animals_States\", m_pastureInfo.animalType ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( sm.value( \"ID2\" ).toString() == \"Adult\" )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tga.sprite = Global::util->smallPixmap( g->sf()->createAnimalSprite( sm.value( \"SpriteID\" ).toString() ), GameState::seasonString, 0 );\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}\r\n\r\n\t\t\t\t\t\tm_pastureInfo.animals.clear();\r\n\t\t\t\t\t\tfor( const auto& id : pasture->animals() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tauto animal = g->cm()->animal( id );\r\n\t\t\t\t\t\t\tif( animal )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tGuiPastureAnimal pa;\r\n\t\t\t\t\t\t\t\tpa.id = id;\r\n\t\t\t\t\t\t\t\tpa.name = animal->name();\r\n\t\t\t\t\t\t\t\tpa.isYoung = animal->isYoung();\r\n\t\t\t\t\t\t\t\tpa.gender = animal->gender();\r\n\t\t\t\t\t\t\t\tpa.toButcher = animal->toButcher();\r\n\r\n\t\t\t\t\t\t\t\tm_pastureInfo.animals.append( pa );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_pastureInfo.product = ga;\r\n\t\t\t\t\temit signalUpdatePasture( m_pastureInfo );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase AgriType::Grove:\r\n\t\t\t{\r\n\t\t\t\tauto grove = g->fm()->getGrove( designationID );\r\n\t\t\t\tif ( grove )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto plantRow = DB::selectRow( \"Plants\", m_groveInfo.treeType );\r\n\t\t\t\t\tGuiPlant gp;\r\n\t\t\t\t\tif ( plantRow.value( \"Type\" ).toString() == \"Tree\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgp.plantID    = m_groveInfo.treeType;\r\n\t\t\t\t\t\tgp.seedID     = plantRow.value( \"SeedItemID\" ).toString();\r\n\t\t\t\t\t\tgp.materialID = plantRow.value( \"Material\" ).toString();\r\n\t\t\t\t\t\tgp.seedCount  = g->inv()->itemCount( gp.seedID, gp.materialID );\r\n\r\n\t\t\t\t\t\tgp.harvestedItem = DB::select( \"ItemID\", \"Plants_OnHarvest_HarvestedItem\", m_groveInfo.treeType ).toString();\r\n\t\t\t\t\t\tgp.itemCount     = g->inv()->itemCount( gp.harvestedItem, gp.materialID );\r\n\r\n\t\t\t\t\t\tgp.name     = S::s( \"$MaterialName_\" + gp.materialID );\r\n\r\n\t\t\t\t\t\tauto pm = Global::util->smallPixmap( g->sf()->createSprite( plantRow.value( \"ToolButtonSprite\" ).toString(), { gp.materialID } ), GameState::seasonString, 0 );\r\n\t\t\t\t\t\tgp.sprite = pm;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_groveInfo.product = gp;\r\n\t\t\t\t\temit signalUpdateGrove( m_groveInfo );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onSetMaxMale( unsigned int pastureID, int max )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_pastureInfo.ID == pastureID )\r\n\t{\r\n\t\tauto pasture = g->fm()->getPasture( pastureID );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tpasture->setMaxMale( max );\r\n\t\t}\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorAgri::onSetMaxFemale( unsigned int pastureID, int max )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_pastureInfo.ID == pastureID )\r\n\t{\r\n\t\tauto pasture = g->fm()->getPasture( pastureID );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tpasture->setMaxFemale( max );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onSetButchering( unsigned int animalID, bool value )\r\n{\r\n\tif( !g ) return;\r\n\t//qDebug() << \"AggregatorAgri::onSetButchering\" << animalID << value;\r\n\tauto animal = g->cm()->animal( animalID );\r\n\tif( animal )\r\n\t{\r\n\t\tanimal->setToButcher( value );\r\n\t}\r\n}\r\n\r\nvoid AggregatorAgri::onRequestPastureAnimalInfo( unsigned int pastureID )\r\n{\r\n\tonRequestProductInfo( AgriType::Pasture, pastureID );\r\n}\r\n\r\nvoid AggregatorAgri::onRequestPastureFoodInfo( unsigned int pastureID )\r\n{\r\n\tonRequestProductInfo( AgriType::Pasture, pastureID );\r\n}\r\n\r\nvoid AggregatorAgri::onSetFoodItemChecked( unsigned int pastureID, QString itemSID, QString materialSID, bool checked )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_pastureInfo.ID == pastureID )\r\n\t{\r\n\t\tauto pasture = g->fm()->getPasture( pastureID );\r\n\t\tif ( pasture )\r\n\t\t{\r\n\t\t\tif( checked )\r\n\t\t\t{\r\n\t\t\t\tpasture->addFoodSetting( itemSID, materialSID );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tpasture->removeFoodSetting( itemSID, materialSID );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/gui/aggregatoragri.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/tile.h\"\r\n#include \"../game/creature.h\"\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\n\r\nstruct GuiAnimal\r\n{\r\n\tQString name;\r\n\tQString animalID;\r\n\tQString materialID; // = animalID usually\r\n\tQString harvestedItem;\r\n\tint totalcount  = 0;\r\n\tint maleCount   = 0;\r\n\tint femaleCount = 0;\r\n\tQPixmap sprite;\r\n};\r\nQ_DECLARE_METATYPE( GuiAnimal )\r\n\r\nstruct GuiPastureAnimal\r\n{\r\n\tQString name;\r\n\tunsigned int id = 0;\r\n\tQString animalID;\r\n\tQString materialID; // = animalID usually\r\n\tGender gender = Gender::UNDEFINED;\r\n\tbool isYoung = false;\r\n\tbool toButcher = false;\r\n};\r\nQ_DECLARE_METATYPE( GuiPastureAnimal )\r\n\r\n\r\nstruct GuiPlant\r\n{\r\n\tQString name;\r\n\tQString plantID;\r\n\tQString seedID;\r\n\tint seedCount = 0;\r\n\tQString materialID; // = plantID usually\r\n\tQString harvestedItem;\r\n\tint itemCount  = 0;\r\n\tint plantCount = 0;\r\n\tQPixmap sprite;\r\n};\r\nQ_DECLARE_METATYPE( GuiPlant )\r\n\r\nenum class AgriType\r\n{\r\n\tFarm,\r\n\tPasture,\r\n\tGrove\r\n};\r\nQ_DECLARE_METATYPE( AgriType )\r\n\r\nstruct GuiFarmInfo\r\n{\r\n\tunsigned int ID = 0;\r\n\r\n\tQString name;\r\n\tint priority    = 1;\r\n\tint maxPriority = 1;\r\n\tbool suspended  = false;\r\n\tbool harvest    = true;\r\n\tQString plantType;\r\n\r\n\tint numPlots  = 0;\r\n\tint tilled    = 0;\r\n\tint planted   = 0;\r\n\tint cropReady = 0;\r\n\r\n\tGuiPlant product;\r\n};\r\nQ_DECLARE_METATYPE( GuiFarmInfo )\r\n\r\nstruct GuiPastureFoodItem\r\n{\r\n\tQString itemSID;\r\n\tQString materialSID;\r\n\tQString name;\r\n\tbool checked = false;\r\n\tQPixmap sprite;\r\n};\r\n\r\nstruct GuiPastureInfo\r\n{\r\n\tunsigned int ID = 0;\r\n\r\n\tQString name;\r\n\tint priority    = 1;\r\n\tint maxPriority = 1;\r\n\tbool suspended  = false;\r\n\tbool harvest    = true;\r\n\tbool harvestHay = false;\r\n\tbool tame\t\t= false;\r\n\tQString animalType;\r\n\r\n\tint numPlots   = 0;\r\n\tint numMale    = 0;\r\n\tint numFemale  = 0;\r\n\tint total      = 0;\r\n\tint maxNumber  = 0;\r\n\tint maxMale    = 0;\r\n\tint maxFemale  = 0;\r\n\tint animalSize = 0;\r\n\r\n\tint foodMax    = 0;\r\n\tint foodCurrent= 0;\r\n\tint hayMax     = 0;\r\n\tint hayCurrent = 0;\r\n\r\n\tQList<GuiPastureFoodItem> food;\r\n\r\n\tGuiAnimal product;\r\n\tQList<GuiPastureAnimal> animals;\r\n};\r\nQ_DECLARE_METATYPE( GuiPastureInfo )\r\n\r\nstruct GuiGroveInfo\r\n{\r\n\tunsigned int ID = 0;\r\n\r\n\tQString name;\r\n\tint priority    = 1;\r\n\tint maxPriority = 1;\r\n\tbool suspended  = false;\r\n\tbool plantTrees = true;\r\n\tbool fellTrees  = false;\r\n\tbool pickFruits = true;\r\n\tQString treeType;\r\n\r\n\tint numPlots  = 0;\r\n\tint planted   = 0;\r\n\tint cropReady = 0;\r\n\r\n\tGuiPlant product;\r\n};\r\nQ_DECLARE_METATYPE( GuiGroveInfo )\r\n\r\nclass AggregatorAgri : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorAgri( QObject* parent = nullptr );\r\n\t~AggregatorAgri();\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tbool m_AgriDirty             = false;\r\n\tunsigned int m_currentTileID = 0;\r\n\tAgriType m_currentType       = AgriType::Farm;\r\n\tGuiFarmInfo m_farmInfo;\r\n\tGuiPastureInfo m_pastureInfo;\r\n\tGuiGroveInfo m_groveInfo;\r\n\tQList<GuiPlant> m_globalPlantInfo;\r\n\tQList<GuiAnimal> m_globalAnimalInfo;\r\n\tQList<GuiPlant> m_globalTreeInfo;\r\n\r\npublic slots:\r\n\tvoid onOpen( TileFlag designation, unsigned int tileID );\r\n\tvoid onUpdate( unsigned int id );\r\n\tvoid onUpdateFarm( unsigned int id );\r\n\tvoid onUpdatePasture( unsigned int id );\r\n\tvoid onUpdateGrove( unsigned int id );\r\n\r\n\tvoid onSetBasicOptions( AgriType type, unsigned int ID, QString name, int priority, bool suspended );\r\n\tvoid onSelectProduct( AgriType type, unsigned int designationID, QString productSID );\r\n\tvoid onSetHarvestOptions( AgriType type, unsigned int designationID, bool harvest, bool harvestHay, bool tame );\r\n\tvoid onSetGroveOptions( unsigned int groveID, bool pick, bool plant, bool fell );\r\n\r\n\tvoid onSetMaxMale( unsigned int pastureID, int max );\r\n\tvoid onSetMaxFemale( unsigned int pastureID, int max );\r\n\r\n\tvoid onRequestGlobalPlantInfo();\r\n\tvoid onRequestGlobalAnimalInfo();\r\n\tvoid onRequestGlobalTreeInfo();\r\n\tvoid onRequestProductInfo( AgriType type, unsigned int designationID );\r\n\r\n\tvoid onCloseWindow();\r\n\r\n\tvoid onSetButchering( unsigned int animalID, bool value );\r\n\tvoid onRequestPastureAnimalInfo( unsigned int pastureID );\r\n\tvoid onRequestPastureFoodInfo( unsigned int pastureID );\r\n\r\n\tvoid onSetFoodItemChecked( unsigned int pastureID, QString itemSID, QString materialSID, bool checked );\r\n\r\nsignals:\r\n\tvoid signalShowAgri( unsigned int id );\r\n\tvoid signalUpdateFarm( const GuiFarmInfo& info );\r\n\tvoid signalUpdatePasture( const GuiPastureInfo& info );\r\n\tvoid signalUpdateGrove( const GuiGroveInfo& info );\r\n\tvoid signalGlobalPlantInfo( const QList<GuiPlant>& info );\r\n\tvoid signalGlobalAnimalInfo( const QList<GuiAnimal>& info );\r\n\tvoid signalGlobalTreeInfo( const QList<GuiPlant>& info );\r\n};"
  },
  {
    "path": "src/gui/aggregatorcreatureinfo.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorcreatureinfo.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/militarymanager.h\"\r\n\r\n#include \"../gfx/spritefactory.h\"\r\n\r\n#include \"../gui/strings.h\"\r\n\r\nAggregatorCreatureInfo::AggregatorCreatureInfo( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n}\r\n\r\nvoid AggregatorCreatureInfo::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorCreatureInfo::update()\r\n{\r\n\tif( m_currentID != 0 )\r\n\t{\r\n\t\tonRequestCreatureUpdate( m_currentID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorCreatureInfo::onRequestCreatureUpdate( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\tm_currentID = id;\r\n\tauto gnome = g->gm()->gnome( id );\r\n\tif( gnome )\r\n\t{\r\n\t\tm_info.name = gnome->name();\r\n\t\tm_info.id = id;\r\n\t\tm_info.profession = gnome->profession();\r\n\r\n\t\tm_info.str = gnome->attribute( \"Str\" );\r\n\t\tm_info.con = gnome->attribute( \"Con\" );\r\n\t\tm_info.dex = gnome->attribute( \"Dex\" );\r\n\t\tm_info.intel = gnome->attribute( \"Int\" );\r\n\t\tm_info.wis = gnome->attribute( \"Wis\" );\r\n\t\tm_info.cha = gnome->attribute( \"Cha\" );\r\n\r\n\t\tm_info.hunger = gnome->need( \"Hunger\" );\r\n\t\tm_info.thirst = gnome->need( \"Thirst\" );\r\n\t\tm_info.sleep = gnome->need( \"Sleep\" );\r\n\t\tm_info.happiness = gnome->need( \"Happiness\" );\r\n\r\n\t\tm_info.activity = \"Doing something. tbi\";\r\n\r\n\t\tif( gnome->roleID() )\r\n\t\t{\r\n\t\t\tm_info.uniform = g->mil()->uniformCopy( gnome->roleID() );\r\n\t\t}\r\n\t\tm_info.equipment = gnome->equipment();\r\n\t\t\r\n\t\tif( m_previousID != m_currentID || gnome->equipmentChanged() )\r\n\t\t{\r\n\t\t\tm_previousID = m_currentID;\r\n\r\n\t\t\tm_info.itemPics.clear();\r\n\t\t\tif( m_info.equipment.head.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateUniformImg( \"ArmorHead\", m_info.uniform.parts.value( \"HeadArmor\" ), m_info.equipment.head );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.chest.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateUniformImg( \"ArmorChest\", m_info.uniform.parts.value( \"ChestArmor\" ), m_info.equipment.chest );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.arm.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateUniformImg( \"ArmorArms\", m_info.uniform.parts.value( \"ArmArmor\" ), m_info.equipment.arm );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.hand.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateUniformImg( \"ArmorHands\", m_info.uniform.parts.value( \"HandArmor\" ), m_info.equipment.hand );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.leg.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateUniformImg( \"ArmorLegs\", m_info.uniform.parts.value( \"LegArmor\" ), m_info.equipment.leg );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.foot.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateUniformImg( \"ArmorFeet\", m_info.uniform.parts.value( \"FootArmor\" ), m_info.equipment.foot );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.leftHandHeld.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateItemImg( \"LeftHandHeld\", m_info.equipment.leftHandHeld );\r\n\t\t\t}\r\n\t\t\tif( m_info.equipment.rightHandHeld.itemID )\r\n\t\t\t{\r\n\t\t\t\tcreateItemImg( \"RightHandHeld\", m_info.equipment.rightHandHeld );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\temit signalCreatureUpdate( m_info );\r\n\t\treturn;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tauto monster = g->cm()->monster( id );\r\n\t\tif( monster )\r\n\t\t{\r\n\t\t\tm_info.name = monster->name();\r\n\t\t\tm_info.id = id;\r\n\t\t\t//m_info.profession = monster->profession();\r\n\r\n\t\t\tm_info.str = monster->attribute( \"Str\" );\r\n\t\t\tm_info.con = monster->attribute( \"Con\" );\r\n\t\t\tm_info.dex = monster->attribute( \"Dex\" );\r\n\t\t\tm_info.intel = monster->attribute( \"Int\" );\r\n\t\t\tm_info.wis = monster->attribute( \"Wis\" );\r\n\t\t\tm_info.cha = monster->attribute( \"Cha\" );\r\n\r\n\t\t\tm_info.hunger = 100; //monster->need( \"Hunger\" );\r\n\t\t\tm_info.thirst = 100; //monster->need( \"Thirst\" );\r\n\t\t\tm_info.sleep = 100; //monster->need( \"Sleep\" );\r\n\t\t\tm_info.happiness = 100; //monster->need( \"Happiness\" );\r\n\t\t\t\r\n\t\t\tm_info.activity = \"Doing something. tbi\";\r\n\t\t\temit signalCreatureUpdate( m_info );\r\n\t\t\treturn;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tauto animal = g->cm()->animal( id );\r\n\t\t\tif( animal )\r\n\t\t\t{\r\n\t\t\t\tm_info.name = animal->name();\r\n\t\t\t\tm_info.id = id;\r\n\t\t\t\t//m_info.profession = animal->profession();\r\n\r\n\t\t\t\tm_info.str = animal->attribute( \"Str\" );\r\n\t\t\t\tm_info.con = animal->attribute( \"Con\" );\r\n\t\t\t\tm_info.dex = animal->attribute( \"Dex\" );\r\n\t\t\t\tm_info.intel = animal->attribute( \"Int\" );\r\n\t\t\t\tm_info.wis = animal->attribute( \"Wis\" );\r\n\t\t\t\tm_info.cha = animal->attribute( \"Cha\" );\r\n\r\n\t\t\t\tm_info.hunger = animal->hunger();\r\n\t\t\t\tm_info.thirst = 100; //animal->need( \"Thirst\" );\r\n\t\t\t\tm_info.sleep = 100; //animal->need( \"Sleep\" );\r\n\t\t\t\tm_info.happiness = 100; //animal->need( \"Happiness\" );\r\n\t\t\t\r\n\t\t\t\tm_info.activity = \"Doing something. tbi\";\r\n\t\t\t\temit signalCreatureUpdate( m_info );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t}\r\n\tm_currentID = 0;\r\n}\r\n\r\n\r\nvoid AggregatorCreatureInfo::onRequestProfessionList()\r\n{\r\n\tif( !g ) return;\r\n\temit signalProfessionList( g->gm()->professions() );\r\n}\r\n\r\nvoid AggregatorCreatureInfo::onSetProfession( unsigned int gnomeID, QString profession )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\tQString oldProf = gnome->profession();\r\n\t\tif( oldProf != profession )\r\n\t\t{\r\n\t\t\tgnome->selectProfession( profession );\r\n\t\t\t//onUpdateSingleGnome( gnomeID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorCreatureInfo::createItemImg( QString slot, EquipmentItem& eItem )\r\n{\r\n\tif( !g ) return;\r\n\tif( eItem.itemID == 0 )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tQStringList mats;\r\n\tif( eItem.allMats.size() )\r\n\t{\r\n\t\tmats = eItem.allMats;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tmats.append( eItem.material );\r\n\t\tmats.append( \"Pine\" );\r\n\t}\r\n\r\n\tauto sprite = g->sf()->createSprite( \"UI\" + eItem.item, mats );\r\n\tif( sprite )\r\n\t{\r\n\t\tQPixmap pm = sprite->pixmap( \"Spring\", 0, 0 );\r\n\r\n\t\tstd::vector<unsigned char> buffer;\r\n\r\n\t\tGlobal::util->createBufferForNoesisImage( pm, buffer );\r\n\t\tm_info.itemPics.insert( slot, buffer );\r\n\t}\r\n\telse\r\n\t{\r\n\t\teItem.itemID = 0;\r\n\t}\r\n}\r\n\r\nvoid AggregatorCreatureInfo::createUniformImg( QString slot, const UniformItem& uItem, EquipmentItem& eItem )\r\n{\r\n\tif( !g ) return;\r\n\tif( uItem.item.isEmpty() || eItem.itemID == 0 )\r\n\t{\r\n\t\treturn; \r\n\t}\r\n\tQStringList mats;\r\n\tmats.append( eItem.material );\r\n\r\n\tauto sprite = g->sf()->createSprite( \"UI\" + uItem.type + slot, mats );\r\n\tif( sprite )\r\n\t{\r\n\t\tQPixmap pm = sprite->pixmap( \"Spring\", 0, 0 );\r\n\r\n\t\tstd::vector<unsigned char> buffer;\r\n\r\n\t\tGlobal::util->createBufferForNoesisImage( pm, buffer );\r\n\t\tm_info.itemPics.insert( slot, buffer );\r\n\t}\r\n\telse\r\n\t{\r\n\t\teItem.itemID = 0;\r\n\t}\r\n}\r\n\r\nvoid AggregatorCreatureInfo::createEmptyUniformImg( QString spriteID )\r\n{\r\n\tif( !g ) return;\r\n\tQStringList mats; \r\n\tmats.append( \"any\" );\r\n\t\r\n\tauto sprite = g->sf()->createSprite( spriteID, mats );\r\n\tif( sprite )\r\n\t{\r\n\t\tQPixmap pm = sprite->pixmap( \"Spring\", 0, 0 );\r\n\r\n\t\tstd::vector<unsigned char> buffer;\r\n\r\n\t\tGlobal::util->createBufferForNoesisImage( pm, buffer );\r\n\r\n\t\tm_emptyPics.insert( spriteID, buffer );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstd::vector<unsigned char> buffer;\r\n\t\tbuffer.resize( 32 * 32 * 4, 0 );\r\n\t\tm_emptyPics.insert( spriteID, buffer );\r\n\t}\r\n}\r\n\r\nvoid AggregatorCreatureInfo::onRequestEmptySlotImages()\r\n{\r\n\tif( !g ) return;\r\n\tm_emptyPics.clear();\r\n\r\n\tcreateEmptyUniformImg( \"UIEmptySlotHead\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotChest\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotArms\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotHands\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotLegs\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotFeet\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotShield\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotWeapon\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotBack\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotNeck\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotRing\" );\r\n\tcreateEmptyUniformImg( \"UIEmptySlotRing\" );\r\n\r\n\temit signalEmptyPics( m_emptyPics );\r\n}"
  },
  {
    "path": "src/gui/aggregatorcreatureinfo.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/creature.h\"\r\n\r\n#include <QObject>\r\n\r\n#include \"../game/gnome.h\"\r\n#include \"../game/militarymanager.h\"\r\n\r\nclass Game;\r\n\r\nstruct GuiCreatureInfo\r\n{\r\n\tQString name;\r\n\tunsigned int id = 0;\r\n\tQString profession;\r\n\tint str = 0;\r\n\tint dex = 0;\r\n\tint con = 0;\r\n\tint intel = 0;\r\n\tint wis = 0;\r\n\tint cha = 0;\r\n\tint hunger = 0;\r\n\tint thirst = 0;\r\n\tint sleep = 0;\r\n\tint happiness = 0;\r\n\r\n\tQString activity;\r\n\r\n\tUniform uniform;\r\n\tEquipment equipment;\r\n\r\n\tQMap< QString, std::vector<unsigned char> > itemPics;\r\n};\r\nQ_DECLARE_METATYPE( GuiCreatureInfo )\r\n\r\n\r\nclass AggregatorCreatureInfo : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorCreatureInfo( QObject* parent = nullptr );\r\n\r\n\tvoid init( Game* game );\r\n\r\n\tvoid update();\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tGuiCreatureInfo m_info;\r\n\tQMap< QString, std::vector<unsigned char> > m_emptyPics;\r\n\r\n\tunsigned int m_currentID = 0;\r\n\tunsigned int m_previousID = 0;\r\n\r\n\tvoid createItemImg( QString slot, EquipmentItem& eItem );\r\n\tvoid createUniformImg( QString slot, const UniformItem& uItem, EquipmentItem& eItem );\r\n\tvoid createEmptyUniformImg( QString spriteID );\r\n\r\npublic slots:\r\n\tvoid onRequestCreatureUpdate( unsigned int creatureID );\r\n\tvoid onRequestProfessionList();\r\n\tvoid onSetProfession( unsigned int gnomeID, QString profession );\r\n\r\n\tvoid onRequestEmptySlotImages();\r\n\r\nsignals:\r\n\tvoid signalCreatureUpdate( const GuiCreatureInfo& info );\r\n\tvoid signalProfessionList( const QStringList& profs );\r\n\t\r\n\tvoid signalEmptyPics( const QMap< QString, std::vector<unsigned char> >& emptyPics );\r\n\r\n};"
  },
  {
    "path": "src/gui/aggregatordebug.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatordebug.h\"\r\n\r\n#include <QDebug>\r\n\r\nAggregatorDebug::AggregatorDebug( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\t\r\n}\r\n\r\nAggregatorDebug::~AggregatorDebug()\r\n{\r\n}\r\n\r\nvoid AggregatorDebug::onSpawnCreature( QString type )\r\n{\r\n\tqDebug() << \"spawn creature:\" << type;\r\n\tif( type == \"Gnome\" )\r\n\t{\r\n\t\temit signalTriggerEvent( EventType::MIGRATION, QVariantMap() );\r\n\t}\r\n\telse if( type == \"Trader\" )\r\n\t{\r\n\t\temit signalTriggerEvent( EventType::TRADER, QVariantMap() );\r\n\t}\r\n\telse if( type == \"Goblin\" )\r\n\t{\r\n\t\tQVariantMap args; \r\n\t\targs.insert( \"Amount\", 1 );\r\n\t\targs.insert( \"Type\", \"Goblin\" );\r\n\t\temit signalTriggerEvent( EventType::INVASION, args );\r\n\t}\r\n}\r\n\r\n\r\nvoid AggregatorDebug::onSetWindowSize( int width, int height )\r\n{\r\n\temit signalSetWindowSize( width, height );\r\n}"
  },
  {
    "path": "src/gui/aggregatordebug.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/creature.h\"\r\n#include \"../game/eventmanager.h\"\r\n\r\n\r\n#include <QObject>\r\n\r\nclass AggregatorDebug : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorDebug( QObject* parent = nullptr );\r\n\t~AggregatorDebug();\r\n\r\nprivate:\r\n\t\r\npublic slots:\r\n\tvoid onSpawnCreature( QString type );\r\n    void onSetWindowSize( int width, int height );\r\n\r\nsignals:\r\n\tvoid signalTriggerEvent( EventType type, QVariantMap args );\r\n    void signalSetWindowSize( int width, int height );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorinventory.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorinventory.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../gui/strings.h\"\r\n\r\nAggregatorInventory::AggregatorInventory( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\r\n\tm_buildSelection2String.insert( BuildSelection::Workshop, \"Workshop\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Wall, \"Wall\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Floor, \"Floor\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Stairs, \"Stairs\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Ramps, \"Ramp\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Containers, \"Containers\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Fence, \"Fence\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Furniture, \"Furniture\" );\r\n\tm_buildSelection2String.insert( BuildSelection::Utility, \"Utility\" );\r\n\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Workshop, BuildItemType::Workshop );\r\n\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Wall, BuildItemType::Terrain );\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Floor, BuildItemType::Terrain );\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Stairs, BuildItemType::Terrain );\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Ramps, BuildItemType::Terrain );\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Fence, BuildItemType::Terrain );\r\n\t\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Containers, BuildItemType::Item );\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Furniture, BuildItemType::Item );\r\n\tm_buildSelection2buildItem.insert( BuildSelection::Utility, BuildItemType::Item );\r\n}\r\n\r\nAggregatorInventory::~AggregatorInventory()\r\n{\r\n}\r\n\r\nvoid AggregatorInventory::init( Game* game )\r\n{\r\n\tg = game;\r\n\r\n\tfor ( const auto& cat : g->inv()->categories() )\r\n\t{\r\n\t\tfor ( const auto& group : g->inv()->groups( cat ) )\r\n\t\t{\r\n\t\t\tfor ( const auto& item : g->inv()->items( cat, group ) )\r\n\t\t\t{\r\n\t\t\t\tm_itemToCategoryCache.insert( item, cat );\r\n\t\t\t\tm_itemToGroupCache.insert( item, group );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tm_watchedItems.clear();\r\n\t// Can't use iterator due to 2nd reference being created in updateWatchedItem\r\n\tfor( size_t i = 0; i < GameState::watchedItemList.size(); ++i )\r\n\t{\r\n\t\t// Reference is valid until first updateWatchedItem only\r\n\t\tconst auto& gwi = GameState::watchedItemList[i];\r\n\t\tQString key = gwi.category + gwi.group + gwi.item + gwi.material;\r\n\t\tm_watchedItems.insert( key );\r\n\r\n\t\tif( m_watchedItems.contains( gwi.category ) && gwi.category == key )\r\n\t\t{\r\n\t\t\tupdateWatchedItem( gwi.category );\r\n\t\t}\r\n\t\telse if( m_watchedItems.contains( gwi.category + gwi.group ) && gwi.category + gwi.group == key  )\r\n\t\t{\r\n\t\t\tupdateWatchedItem( gwi.category, gwi.group );\r\n\t\t}\r\n\t\telse if( m_watchedItems.contains( gwi.category + gwi.group + gwi.item ) && gwi.category + gwi.group + gwi.item == key )\r\n\t\t{\r\n\t\t\tupdateWatchedItem( gwi.category, gwi.group, gwi.item );\r\n\t\t}\r\n\t\telse //if( m_watchedItems.contains( gwi.category + gwi.group + gwi.item + gwi.material ) && gwi.category + gwi.group + gwi.item + gwi.material == key )\r\n\t\t{\r\n\t\t\tupdateWatchedItem( gwi.category, gwi.group, gwi.item, gwi.material );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorInventory::onRequestCategories()\r\n{\r\n\tif( !g ) return;\r\n\tm_categories.clear();\r\n\tfor ( const auto& cat : g->inv()->categories() )\r\n\t{\r\n\t\tGuiInventoryCategory gic;\r\n\t\tgic.id = cat;\r\n\t\tgic.name = S::s( \"$CategoryName_\" + cat );\r\n\t\tgic.watched = m_watchedItems.contains( cat );\r\n\r\n\t\tfor ( const auto& group : g->inv()->groups( cat ) )\r\n\t\t{\r\n\t\t\tGuiInventoryGroup gig;\r\n\t\t\tgig.id = group;\r\n\t\t\tgig.name = S::s( \"$GroupName_\" + group );\r\n\t\t\tgig.cat = cat;\r\n\t\t\tgig.watched = m_watchedItems.contains( cat + group );\r\n\r\n\t\t\tfor ( const auto& item : g->inv()->items( cat, group ) )\r\n\t\t\t{\r\n\t\t\t\tGuiInventoryItem gii;\r\n\t\t\t\tgii.id = item;\r\n\t\t\t\tgii.name = S::s( \"$ItemName_\" + item );\r\n\t\t\t\tgii.cat = cat;\r\n\t\t\t\tgii.group = group;\r\n\t\t\t\tgii.watched = m_watchedItems.contains( cat + group + item );\r\n\r\n\t\t\t\tfor ( const auto& mat : g->inv()->materials( cat, group, item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tauto result   = g->inv()->itemCountDetailed( item, mat );\r\n\t\t\t\t\t//if( result.total > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGuiInventoryMaterial gim;\r\n\t\t\t\t\t\tgim.id = mat;\r\n\t\t\t\t\t\tgim.name = S::s( \"$MaterialName_\" + mat );\r\n\t\t\t\t\t\tgim.cat = cat;\r\n\t\t\t\t\t\tgim.group = group;\r\n\t\t\t\t\t\tgim.item = item;\r\n\t\t\t\t\t\tgim.watched = m_watchedItems.contains( cat + group + item + mat );\r\n\t\t\t\t\t\tgim.countTotal = result.total; \r\n\t\t\t\t\t\tgim.countInJob = result.inJob; \r\n\t\t\t\t\t\tgim.countInStockpiles = result.inStockpile;\r\n\t\t\t\t\t\tgim.countEquipped = result.equipped;\r\n\t\t\t\t\t\tgim.countConstructed = result.constructed;\r\n\t\t\t\t\t\tgim.countLoose = result.loose; \r\n\t\t\t\t\t\tgim.totalValue = result.totalValue;\r\n\r\n\t\t\t\t\t\tgii.countTotal += result.total;\r\n\t\t\t\t\t\tgii.countInStockpiles += result.inStockpile;\r\n\r\n\t\t\t\t\t\tgii.materials.append( gim );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tgig.countTotal += gii.countTotal;\r\n\t\t\t\tgig.countInStockpiles += gii.countInStockpiles;\r\n\r\n\t\t\t\tgig.items.append( gii );\r\n\t\t\t}\r\n\r\n\t\t\tgic.countTotal += gig.countTotal;\r\n\t\t\tgic.countInStockpiles += gig.countInStockpiles;\r\n\r\n\t\t\tgic.groups.append( gig );\r\n\t\t}\r\n\t\r\n\t\tm_categories.append( gic );\r\n\t}\r\n\r\n\temit signalInventoryCategories( m_categories );\r\n}\r\n\r\nvoid AggregatorInventory::onRequestBuildItems( BuildSelection buildSelection, QString category )\r\n{\r\n\tif( !g ) return;\r\n\tm_buildItems.clear();\r\n\tif ( m_buildSelection2String.contains( buildSelection ) )\r\n\t{\r\n\t\tQList<QVariantMap> rows;\r\n\t\tQString prefix = \"$ConstructionName_\";\r\n\t\tswitch( buildSelection )\r\n\t\t{\r\n\t\t\tcase BuildSelection::Wall:\r\n\t\t\tcase BuildSelection::Floor:\r\n\t\t\tcase BuildSelection::Stairs:\r\n\t\t\tcase BuildSelection::Ramps:\r\n\t\t\tcase BuildSelection::Fence:\r\n\t\t\t\trows = DB::selectRows( \"Constructions\", \"Type\", m_buildSelection2String.value( buildSelection ), \"Category\", category );\r\n\t\t\t\tbreak;\r\n\t\t\tcase BuildSelection::Workshop:\r\n\t\t\t\trows = DB::selectRows( \"Workshops\", \"Tab\", category );\r\n\t\t\t\tprefix = \"$WorkshopName_\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase BuildSelection::Containers:\r\n\t\t\t\trows = DB::selectRows( \"Containers\", \"Buildable\", \"1\" );\r\n\t\t\t\tprefix = \"$ItemName_\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase BuildSelection::Furniture:\r\n\t\t\t\trows = DB::selectRows( \"Items\", \"Category\", \"Furniture\", \"ItemGroup\", category );\r\n\t\t\t\tprefix = \"$ItemName_\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase BuildSelection::Utility:\r\n\t\t\t\trows = DB::selectRows( \"Items\", \"Category\", \"Utility\", \"ItemGroup\", category );\r\n\t\t\t\tprefix = \"$ItemName_\";\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\t \r\n\t\t//qDebug() << \"Type:\" << m_buildSelection2String.value( buildSelection )<< \"Category\" << category << rows.size();\r\n\t\tfor ( auto row : rows )\r\n\t\t{\r\n\t\t\tGuiBuildItem gbi;\r\n\t\t\tgbi.id   = row.value( \"ID\" ).toString();\r\n\t\t\tgbi.name = S::s( prefix + row.value( \"ID\" ).toString() );\r\n\t\t\tgbi.biType = m_buildSelection2buildItem.value( buildSelection );\r\n\r\n\t\t\tsetBuildItemValues( gbi, buildSelection );\r\n\r\n\t\t\tm_buildItems.append( gbi );\r\n\t\t}\r\n\t}\r\n\temit signalBuildItems( m_buildItems );\r\n}\r\n\r\nvoid AggregatorInventory::setBuildItemValues( GuiBuildItem& gbi, BuildSelection selection )\r\n{\r\n\tif( !g ) return;\r\n\tauto type = m_buildSelection2buildItem.value( selection );\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase BuildItemType::Workshop:\r\n\t\t{\r\n\t\t\tfor ( auto row : DB::selectRows( \"Workshops_Components\", gbi.id ) )\r\n\t\t\t{\r\n\t\t\t\tif ( !row.value( \"ItemID\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tGuiBuildRequiredItem gbri;\r\n\t\t\t\t\tgbri.itemID = row.value( \"ItemID\" ).toString();\r\n\t\t\t\t\tgbri.amount = row.value( \"Amount\" ).toInt();\r\n\t\t\t\t\tsetAvailableMats( gbri );\r\n\t\t\t\t\tgbi.requiredItems.append( gbri );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tQStringList mats;\r\n\t\t\tfor ( int i = 0; i < 25; ++i )\r\n\t\t\t\tmats.push_back( \"None\" );\r\n\r\n\t\t\tQPixmap pm = Global::util->createWorkshopImage( gbi.id, mats );\r\n\t\t\tGlobal::util->createBufferForNoesisImage( pm, gbi.buffer );\r\n\t\t\tgbi.iconWidth = pm.width();\r\n\t\t\tgbi.iconHeight = pm.height();\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase BuildItemType::Terrain:\r\n\t\t{\r\n\t\t\tfor ( auto row : DB::selectRows( \"Constructions_Components\", gbi.id ) )\r\n\t\t\t{\r\n\t\t\t\t\tGuiBuildRequiredItem gbri;\r\n\t\t\t\t\tgbri.itemID = row.value( \"ItemID\" ).toString();\r\n\t\t\t\t\tgbri.amount = row.value( \"Amount\" ).toInt();\r\n\t\t\t\t\tsetAvailableMats( gbri );\r\n\t\t\t\t\tgbi.requiredItems.append( gbri );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tQStringList mats;\r\n\t\t\tfor ( int i = 0; i < 25; ++i )\r\n\t\t\t\tmats.push_back( \"None\" );\r\n\r\n\t\t\tQPixmap pm = Global::util->createConstructionImage( gbi.id, mats );\r\n\r\n\t\t\tGlobal::util->createBufferForNoesisImage( pm, gbi.buffer );\r\n\t\t\tgbi.iconWidth = pm.width();\r\n\t\t\tgbi.iconHeight = pm.height();\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase BuildItemType::Item:\r\n\t\t{\r\n\t\t\tauto rows = DB::selectRows( \"Constructions_Components\", gbi.id );\r\n\r\n\t\t\tif( rows.size() )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto row : rows )\r\n\t\t\t\t{\r\n\t\t\t\t\tGuiBuildRequiredItem gbri;\r\n\t\t\t\t\tgbri.itemID = row.value( \"ItemID\" ).toString();\r\n\t\t\t\t\tgbri.amount = row.value( \"Amount\" ).toInt();\r\n\t\t\t\t\tsetAvailableMats( gbri );\r\n\t\t\t\t\tgbi.requiredItems.append( gbri );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tGuiBuildRequiredItem gbri;\r\n\t\t\t\tgbri.itemID = gbi.id;\r\n\t\t\t\tgbri.amount = 1;\r\n\t\t\t\tsetAvailableMats( gbri );\r\n\t\t\t\tgbi.requiredItems.append( gbri );\r\n\t\t\t}\r\n\r\n\r\n\t\t\tQStringList mats;\r\n\t\t\tfor ( int i = 0; i < 25; ++i )\r\n\t\t\t\tmats.push_back( \"None\" );\r\n\r\n\t\t\tQPixmap pm = Global::util->createItemImage( gbi.id, mats );\r\n\t\t\tGlobal::util->createBufferForNoesisImage( pm, gbi.buffer );\r\n\t\t\tgbi.iconWidth = pm.width();\r\n\t\t\tgbi.iconHeight = pm.height();\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AggregatorInventory::setAvailableMats( GuiBuildRequiredItem& gbri )\r\n{\r\n\tif( !g ) return;\r\n\tauto mats = g->inv()->materialCountsForItem( gbri.itemID );\r\n\r\n\tgbri.availableMats.append( { \"any\", mats[\"any\"] } );\r\n\tfor ( auto key : mats.keys() )\r\n\t{\r\n\t\tif ( key != \"any\" )\r\n\t\t{\r\n\t\t\tgbri.availableMats.append( { key, mats[key] } );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorInventory::onSetActive( bool active, const GuiWatchedItem& gwi )\r\n{\r\n\tQString key = gwi.category + gwi.group + gwi.item + gwi.material;\r\n\tif( active )\r\n\t{\r\n\t\tm_watchedItems.insert( key );\r\n\t\tGameState::watchedItemList.append( gwi );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_watchedItems.remove( key );\r\n\t\tfor( int i = 0; i < GameState::watchedItemList.size(); ++i )\r\n\t\t{\r\n\t\t\tauto hwi = GameState::watchedItemList[i];\r\n\t\t\tif( gwi.category == hwi.category && gwi.group == hwi.group && gwi.item == hwi.item && gwi.material == hwi.material )\r\n\t\t\t{\r\n\t\t\t\tGameState::watchedItemList.removeAt( i );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tif( m_watchedItems.contains( gwi.category ) && gwi.category == key )\r\n\t{\r\n\t\tupdateWatchedItem( gwi.category );\r\n\t}\r\n\telse if( m_watchedItems.contains( gwi.category + gwi.group ) && gwi.category + gwi.group == key  )\r\n\t{\r\n\t\tupdateWatchedItem( gwi.category, gwi.group );\r\n\t}\r\n\telse if( m_watchedItems.contains( gwi.category + gwi.group + gwi.item ) && gwi.category + gwi.group + gwi.item == key )\r\n\t{\r\n\t\tupdateWatchedItem( gwi.category, gwi.group, gwi.item );\r\n\t}\r\n\telse //if( m_watchedItems.contains( gwi.category + gwi.group + gwi.item + gwi.material ) && gwi.category + gwi.group + gwi.item + gwi.material == key )\r\n\t{\r\n\t\tupdateWatchedItem( gwi.category, gwi.group, gwi.item, gwi.material );\r\n\t}\r\n\r\n\r\n\t//onRequestCategories();\r\n}\r\n\r\n    \r\nvoid AggregatorInventory::onAddItem( QString itemSID, QString materialSID )\r\n{\r\n\tQString cat = m_itemToCategoryCache.value( itemSID );\r\n\tQString group = m_itemToGroupCache.value( itemSID );\r\n\r\n\tif( m_watchedItems.contains( cat ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat );\r\n\t}\r\n\tif( m_watchedItems.contains( cat + group ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat, group );\r\n\t}\r\n\tif( m_watchedItems.contains( cat + group + itemSID ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat, group, itemSID );\r\n\t}\r\n\tif( m_watchedItems.contains( cat + group + itemSID + materialSID ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat, group, itemSID, materialSID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorInventory::onRemoveItem( QString itemSID, QString materialSID )\r\n{\r\n\tQString cat = m_itemToCategoryCache.value( itemSID );\r\n\tQString group = m_itemToGroupCache.value( itemSID );\r\n\r\n\tif( m_watchedItems.contains( cat ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat );\r\n\t}\r\n\tif( m_watchedItems.contains( cat + group ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat, group );\r\n\t}\r\n\tif( m_watchedItems.contains( cat + group + itemSID ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat, group, itemSID );\r\n\t}\r\n\tif( m_watchedItems.contains( cat + group + itemSID + materialSID ) )\r\n\t{\r\n\t\tupdateWatchedItem( cat, group, itemSID, materialSID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorInventory::updateWatchedItem( QString cat )\r\n{\r\n\tfor( auto& gwi : GameState::watchedItemList )\r\n\t{\r\n\t\tif( gwi.category == cat && gwi.group.isEmpty() && gwi.item.isEmpty() && gwi.material.isEmpty() )\r\n\t\t{\r\n\t\t\tgwi.count = 0;\r\n\t\t\tfor ( const auto& group : g->inv()->groups( cat ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& item : g->inv()->items( cat, group ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( const auto& mat : g->inv()->materials( cat, group, item ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tgwi.count += g->inv()->itemCount( item, mat );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tgwi.guiString = S::s( \"$CategoryName_\" + cat ) + \": \" + QString::number( gwi.count );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\temit signalWatchList( GameState::watchedItemList );\r\n}\r\n    \r\nvoid AggregatorInventory::updateWatchedItem( QString cat, QString group )\r\n{\r\n\tfor( auto& gwi : GameState::watchedItemList )\r\n\t{\r\n\t\tif( gwi.category == cat && gwi.group == group && gwi.item.isEmpty() && gwi.material.isEmpty() )\r\n\t\t{\r\n\t\t\tgwi.count = 0;\r\n\r\n\t\t\tfor ( const auto& item : g->inv()->items( cat, group ) )\r\n\t\t\t{\r\n\t\t\t\tfor ( const auto& mat : g->inv()->materials( cat, group, item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tgwi.count += g->inv()->itemCount( item, mat );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tgwi.guiString = S::s( \"$GroupName_\" + group ) + \": \" + QString::number( gwi.count );\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\temit signalWatchList( GameState::watchedItemList );\r\n}\r\n\r\nvoid AggregatorInventory::updateWatchedItem( QString cat, QString group, QString item )\r\n{\r\n\tfor( auto& gwi : GameState::watchedItemList )\r\n\t{\r\n\t\tif( gwi.category == cat && gwi.group == group && gwi.item == item && gwi.material.isEmpty() )\r\n\t\t{\r\n\t\t\tgwi.count = 0;\r\n\t\t\tfor ( const auto& mat : g->inv()->materials( cat, group, item ) )\r\n\t\t\t{\r\n\t\t\t\tgwi.count += g->inv()->itemCount( item, mat );\r\n\t\t\t}\r\n\t\t\tgwi.guiString = S::s( \"$ItemName_\" + item ) + \": \" + QString::number( gwi.count );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\temit signalWatchList( GameState::watchedItemList );\r\n}\r\n\r\nvoid AggregatorInventory::updateWatchedItem( QString cat, QString group, QString item, QString mat )\r\n{\r\n\tfor( auto& gwi : GameState::watchedItemList )\r\n\t{\r\n\t\tif( gwi.category == cat && gwi.group == group && gwi.item == item && gwi.material == mat )\r\n\t\t{\r\n\t\t\tgwi.count = g->inv()->itemCount( item, mat );\r\n\t\t\tgwi.guiString = S::s( \"$MaterialName_\" + mat ) + \" \" + S::s( \"$ItemName_\" + item ) + \": \" + QString::number( gwi.count );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\temit signalWatchList( GameState::watchedItemList );\r\n}\r\n\r\nvoid AggregatorInventory::update()\r\n{\r\n\tonRequestCategories();\r\n\r\n\temit signalWatchList( GameState::watchedItemList );\r\n}"
  },
  {
    "path": "src/gui/aggregatorinventory.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/enums.h\"\r\n\r\n#include <QObject>\r\n#include <QList>\r\n#include <QHash>\r\n\r\nclass Game;\r\n\r\nstruct GuiWatchedItem\r\n{\r\n    QString category = \"\";\r\n    QString group = \"\";\r\n    QString item = \"\";\r\n    QString material = \"\";\r\n    QString guiString = \"\";\r\n    int count = 0;\r\n};\r\nQ_DECLARE_METATYPE( GuiWatchedItem )\r\n\r\nstruct GuiInventoryMaterial\r\n{\r\n\tQString id;\r\n    QString name;\r\n    QString cat;\r\n    QString group;\r\n    QString item;\r\n\tunsigned int countTotal = 0;\r\n\tunsigned int countInJob = 0;\r\n\tunsigned int countInStockpiles = 0;\r\n\tunsigned int countEquipped = 0;\r\n\tunsigned int countConstructed = 0;\r\n\tunsigned int countLoose = 0;\r\n\tunsigned int totalValue = 0;\r\n    bool watched = false;\r\n};\r\nQ_DECLARE_METATYPE( GuiInventoryMaterial )\r\n\r\nstruct GuiInventoryItem\r\n{\r\n\tQString id;\r\n    QString name;\r\n    QString cat;\r\n    QString group;\r\n\tunsigned int countTotal = 0;\r\n\tunsigned int countInJob = 0;\r\n\tunsigned int countInStockpiles = 0;\r\n\tunsigned int countEquipped = 0;\r\n\tunsigned int countConstructed = 0;\r\n\tunsigned int countLoose = 0;\r\n\tunsigned int totalValue = 0;\r\n    bool watched = false;\r\n    QList<GuiInventoryMaterial> materials;\r\n};\r\nQ_DECLARE_METATYPE( GuiInventoryItem )\r\n\r\nstruct GuiInventoryGroup\r\n{\r\n    QString id;\r\n\tQString name;\r\n    QString cat;\r\n    unsigned int countTotal = 0;\r\n\tunsigned int countInJob = 0;\r\n\tunsigned int countInStockpiles = 0;\r\n\tunsigned int countEquipped = 0;\r\n\tunsigned int countConstructed = 0;\r\n\tunsigned int countLoose = 0;\r\n\tunsigned int totalValue = 0;\r\n    bool watched = false;\r\n    QList<GuiInventoryItem> items;\r\n};\r\nQ_DECLARE_METATYPE( GuiInventoryGroup )\r\n\r\nstruct GuiInventoryCategory\r\n{\r\n    QString id;\r\n\tQString name;\r\n    unsigned int countTotal = 0;\r\n\tunsigned int countInJob = 0;\r\n\tunsigned int countInStockpiles = 0;\r\n\tunsigned int countEquipped = 0;\r\n\tunsigned int countConstructed = 0;\r\n\tunsigned int countLoose = 0;\r\n\tunsigned int totalValue = 0;\r\n    bool watched = false;\r\n    QList<GuiInventoryGroup> groups;\r\n};\r\nQ_DECLARE_METATYPE( GuiInventoryCategory )\r\n\r\n\r\n\r\n\r\nstruct GuiBuildRequiredItem\r\n{\r\n    QString itemID;\r\n    int amount = 0;\r\n\r\n    QList< QPair<QString, int> > availableMats;\r\n};\r\nQ_DECLARE_METATYPE( GuiBuildRequiredItem )\r\n\r\nstruct GuiBuildItem\r\n{\r\n    QString id;\r\n    QString name;\r\n    BuildItemType biType;\r\n    std::vector<unsigned char> buffer;\r\n    int iconWidth = 0;\r\n    int iconHeight = 0;\r\n\r\n    QList<GuiBuildRequiredItem> requiredItems;\r\n};\r\nQ_DECLARE_METATYPE( GuiBuildItem )\r\n\r\n\r\n\r\nclass AggregatorInventory : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorInventory( QObject* parent = nullptr );\r\n\t~AggregatorInventory();\r\n\r\n    void init( Game* game );\r\n    void update();\r\n\r\nprivate:\r\n    QPointer<Game> g;\r\n\r\n    QList<GuiInventoryCategory> m_categories;\r\n    \r\n    QList<GuiBuildItem> m_buildItems;\r\n\r\n    QSet<QString> m_watchedItems;\r\n\r\n    QMap<BuildSelection, QString> m_buildSelection2String;\r\n    QMap<BuildSelection, BuildItemType> m_buildSelection2buildItem;\r\n\r\n    void setBuildItemValues( GuiBuildItem& gbi, BuildSelection selection );\r\n    void setAvailableMats( GuiBuildRequiredItem& gbri );\r\n    \r\n    QHash<QString, QString> m_itemToGroupCache;\r\n    QHash<QString, QString> m_itemToCategoryCache;\r\n\r\n    void updateWatchedItem( QString cat );\r\n    void updateWatchedItem( QString cat, QString group );\r\n    void updateWatchedItem( QString cat, QString group, QString item );\r\n    void updateWatchedItem( QString cat, QString group, QString item, QString mat );\r\n\r\npublic slots:\r\n\tvoid onRequestCategories();\r\n   \r\n    void onRequestBuildItems( BuildSelection buildSelection, QString category );\r\n\t\r\n    void onSetActive( bool active, const GuiWatchedItem& gwi );\r\n\r\n    void onAddItem( QString itemSID, QString materialSID );\r\n    void onRemoveItem( QString itemSID, QString materialSID );\r\n\r\nsignals:\r\n\tvoid signalInventoryCategories( const QList<GuiInventoryCategory>& categories );\r\n    \r\n    void signalBuildItems( const QList<GuiBuildItem>& items );\r\n\r\n    void signalWatchList( const QList<GuiWatchedItem>& watchedItemList );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorloadgame.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorloadgame.h\"\r\n\r\n#include \"../base/io.h\"\r\n\r\n#include <QDateTime>\r\n#include <QDebug>\r\n#include <QDir>\r\n#include <QDirIterator>\r\n#include <QFile>\r\n#include <QFileInfo>\r\n#include <QJsonArray>\r\n#include <QJsonDocument>\r\n#include <QJsonObject>\r\n#include <QJsonValue>\r\n#include <QStandardPaths>\r\n\r\nAggregatorLoadGame::AggregatorLoadGame( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n}\r\n\r\nAggregatorLoadGame::~AggregatorLoadGame()\r\n{\r\n}\r\n\r\nvoid AggregatorLoadGame::onRequestKingdoms()\r\n{\r\n\tQString sfolder = IO::getDataFolder() + \"/save\";\r\n\r\n\tm_kingdomList.clear();\r\n\r\n\tQDir dir( sfolder );\r\n\tdir.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );\r\n\r\n\tauto entryList = dir.entryList();\r\n\r\n\tfor ( auto sdir : entryList )\r\n\t{\r\n\t\tQString kingdomFolder = sfolder + \"/\" + sdir;\r\n\r\n\t\tQDir kdir( kingdomFolder );\r\n\t\tkdir.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );\r\n\t\tkdir.setSorting( QDir::Time );\r\n\r\n\t\tauto gdirs = kdir.entryList();\r\n\r\n\t\tif ( !gdirs.empty() )\r\n\t\t{\r\n\t\t\tfor( const auto& gdir : gdirs )\r\n\t\t\t{\r\n\t\t\t\tQString gameFolder = kingdomFolder + \"/\" + gdir;\r\n\t\t\t\tQJsonDocument jd;\r\n\t\t\t\tIO::loadFile( gameFolder + \"/game.json\", jd );\r\n\r\n\t\t\t\tif ( jd.isArray() )\r\n\t\t\t\t{\r\n\t\t\t\t\tQJsonArray ja = jd.array();\r\n\t\t\t\t\tauto vl = ja.toVariantList();\r\n\t\t\t\t\tif( vl.size() > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQVariantMap vm = vl.first().toMap();\r\n\r\n\t\t\t\t\t\tQFile file( gameFolder + \"/game.json\" );\r\n\t\t\t\t\t\tQFileInfo fi( file );\r\n\r\n\t\t\t\t\t\tGuiSaveInfo gsk;\r\n\t\t\t\t\t\tgsk.folder  = kingdomFolder;\r\n\t\t\t\t\t\tgsk.name    = vm.value( \"kingdomName\" ).toString();\r\n\t\t\t\t\t\tgsk.version = vm.value( \"Version\" ).toString();\r\n\t\t\t\t\t\tgsk.date    = fi.lastModified();\r\n\r\n\t\t\t\t\t\tm_kingdomList.append( gsk );\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}\r\n\t}\r\n\tstd::sort( m_kingdomList.begin(), m_kingdomList.end(), []( const GuiSaveInfo& a, const GuiSaveInfo& b ) {\r\n\t\treturn a.date > b.date;\r\n\t} );\r\n\r\n\temit signalKingdoms( m_kingdomList );\r\n}\r\n\r\nvoid AggregatorLoadGame::onRequestSaveGames( const QString path )\r\n{\r\n\tm_gameList.clear();\r\n\r\n\tQDir dir( path );\r\n\tdir.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );\r\n\r\n\tauto sdirs = dir.entryList();\r\n\r\n\tfor ( auto sdir : sdirs )\r\n\t{\r\n\t\tGuiSaveInfo gsi;\r\n\r\n\t\tgsi.folder = path + \"/\" + sdir;\r\n\t\tgsi.dir    = sdir;\r\n\r\n\t\tQJsonDocument jd;\r\n\t\tIO::loadFile( gsi.folder + \"/game.json\", jd );\r\n\r\n\t\tif( jd.isArray() )\r\n\t\t{\r\n\t\t\tQJsonArray ja  = jd.array();\r\n\t\t\tauto vl = ja.toVariantList();\r\n\t\t\tif( vl.size() > 0 )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap vm = vl.first().toMap();\r\n\r\n\t\t\t\tgsi.version    = IO::versionString( gsi.folder );\r\n\t\t\t\tgsi.compatible = true;\r\n\r\n\t\t\t\tif ( !IO::saveCompatible( gsi.folder ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tgsi.version += \" - not compatible - sorry broke save games again\";\r\n\t\t\t\t\tgsi.compatible = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgsi.name = vm.value( \"kingdomName\" ).toString();\r\n\r\n\t\t\t\tQFile file( gsi.folder + \"/game.json\" );\r\n\t\t\t\tQFileInfo fi( file );\r\n\t\t\t\tgsi.date = fi.lastModified();\r\n\r\n\t\t\t\tm_gameList.append( gsi );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tstd::sort( m_gameList.begin(), m_gameList.end(), []( const GuiSaveInfo& a, const GuiSaveInfo& b ) {\r\n\t\treturn a.date > b.date;\r\n\t} );\r\n\r\n\temit signalSaveGames( m_gameList );\r\n}\r\n"
  },
  {
    "path": "src/gui/aggregatorloadgame.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QObject>\r\n#include <QDateTime>\r\n\r\nstruct GuiSaveInfo\r\n{\r\n\tQString name;\r\n\tQString folder;\r\n\tQString dir;\r\n\tQString version;\r\n\tQDateTime date;\r\n\tbool compatible = true;\r\n};\r\n\r\nQ_DECLARE_METATYPE( GuiSaveInfo )\r\n\r\nclass AggregatorLoadGame : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorLoadGame( QObject* parent = nullptr );\r\n\t~AggregatorLoadGame();\r\n\r\nprivate:\r\n\tQList<GuiSaveInfo> m_kingdomList;\r\n\tQList<GuiSaveInfo> m_gameList;\r\n\r\npublic slots:\r\n\tvoid onRequestKingdoms();\r\n\tvoid onRequestSaveGames( const QString path );\r\n\r\nsignals:\r\n\tvoid signalKingdoms( const QList<GuiSaveInfo>& kingdoms );\r\n\tvoid signalSaveGames( const QList<GuiSaveInfo>& kingdoms );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatormilitary.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatormilitary.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/game.h\"\r\n\r\n#include \"../gui/strings.h\"\r\n\r\nAggregatorMilitary::AggregatorMilitary( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n}\r\n\r\nAggregatorMilitary::~AggregatorMilitary()\r\n{\r\n}\r\n\r\nvoid AggregatorMilitary::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorMilitary::sendSquadUpdate()\r\n{\r\n\tif( !g ) return;\r\n\tm_squads.clear();\r\n\r\n\tGuiSquad ngs;\r\n\tngs.name = \"no squad\";\r\n\tngs.id = 0;\r\n\tngs.showLeftArrow = false;\r\n\tngs.showRightArrow = false;\r\n\r\n\tfor( auto gnome : g->gm()->gnomes() )\r\n\t{\r\n\t\tif( !g->mil()->getSquadForGnome( gnome->id() ) )\r\n\t\t{\r\n\t\t\tngs.gnomes.append( { gnome->id(), gnome->name(), gnome->roleID() } );\r\n\t\t}\r\n\t}\r\n\tm_squads.append( ngs );\r\n\r\n\tfor( const auto& squad : g->mil()->squads() )\r\n\t{\r\n\t\tGuiSquad gs;\r\n\t\tgs.name = squad.name;\r\n\t\tgs.id = squad.id;\r\n\r\n\t\tfor( const auto& prio : squad.priorities )\r\n\t\t{\r\n\t\t\tGuiTargetPriority gtp;\r\n\t\t\tgtp.id = prio.type;\r\n\t\t\tgtp.name = S::s( \"$CreatureName_\" + prio.type );\r\n\t\t\tgtp.attitude = prio.attitude;\r\n\t\t\tgs.priorities.append( gtp );\r\n\t\t}\r\n\t\t\r\n\t\tfor( auto gnomeID : squad.gnomes )\r\n\t\t{\r\n\t\t\tGuiSquadGnome gsg;\r\n\t\t\tgsg.id = gnomeID;\r\n\t\t\tgsg.name = g->gm()->name( gnomeID );\r\n\t\t\tgsg.roleID = g->gm()->roleID( gnomeID );\r\n\r\n\t\t\tgs.gnomes.append( gsg );\r\n\t\t}\r\n\t\tm_squads.append( gs );\r\n\t}\r\n\r\n\tif ( m_squads.size() > 1 )\r\n\t{\r\n\t\tm_squads[1].showLeftArrow = false;\r\n\t\tm_squads.last().showRightArrow = false;\r\n\r\n\t}\r\n\r\n\temit signalSquads( m_squads );\r\n}\r\n\r\nvoid AggregatorMilitary::onRequestRoles()\r\n{\r\n\tsendRoleUpdate();\r\n}\r\n\r\nvoid AggregatorMilitary::sendRoleUpdate()\r\n{\r\n\tif( !g ) return;\r\n\tm_roles.clear();\r\n\r\n\tauto uniformSlots = DB::ids( \"Uniform\" );\r\n\r\n\tfor( auto& role : g->mil()->roles() )\r\n\t{\r\n\t\tGuiMilRole gmr;\r\n\t\tgmr.name = role.name;\r\n\t\tgmr.id = role.id;\r\n\t\tgmr.isCivilian = role.isCivilian;\r\n\r\n\t\tauto uniVM = role.uniform.serialize();\r\n\t\tauto items = uniVM.value( \"Items\" ).toMap();\r\n\r\n\t\tfor( auto slot : uniformSlots )\r\n\t\t{\r\n\t\t\tgmr.uniform.append( createUniformItem( slot, items.value( slot ).toMap() ) );\r\n\t\t}\r\n\t\t\r\n\r\n\t\tm_roles.append( gmr );\r\n\t}\r\n\temit signalRoles( m_roles );\r\n}\r\n\r\nGuiUniformItem AggregatorMilitary::createUniformItem( QString slot, QVariantMap uniVM )\r\n{\r\n\tGuiUniformItem gui;\r\n\tgui.slotName = slot;\r\n\tgui.armorType = uniVM.value( \"Type\" ).toString();\r\n\tgui.material = uniVM.value( \"Material\" ).toString();\r\n\r\n\tgui.possibleTypesForSlot.append( \"none\" );\r\n\r\n\tauto rows = DB::selectRows( \"Uniform_Slots\", gui.slotName );\r\n\r\n\tfor( auto row : rows )\r\n\t{\r\n\t\tgui.possibleTypesForSlot.append( row.value( \"Type\" ).toString() );\r\n\t}\r\n\r\n\treturn gui;\r\n}\r\n\r\nvoid AggregatorMilitary::sendPriorityUpdate( unsigned int squadID )\r\n{\r\n\tif( !g ) return;\r\n\tauto squad = g->mil()->squad( squadID );\r\n\tif( squad )\r\n\t{\r\n\t\tm_tmpPriorities.clear();\r\n\r\n\t\tfor( const auto& prio : squad->priorities )\r\n\t\t{\r\n\t\t\tGuiTargetPriority gtp;\r\n\t\t\tgtp.id = prio.type;\r\n\t\t\tgtp.name = S::s( \"$CreatureName_\" + prio.type );\r\n\t\t\tgtp.attitude = prio.attitude;\r\n\t\t\tm_tmpPriorities.append( gtp );\r\n\t\t}\r\n\r\n\t\temit signalPriorities( squadID, m_tmpPriorities );\r\n\t}\r\n}\r\n\r\nvoid AggregatorMilitary::onRequestMilitary()\r\n{\r\n\tsendSquadUpdate();\r\n}\r\n\r\nvoid AggregatorMilitary::onAddSquad()\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->addSquad();\r\n\tsendSquadUpdate();\r\n}\r\n\r\nvoid AggregatorMilitary::onRemoveSquad( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->removeSquad( id );\r\n\tsendSquadUpdate();\r\n}\r\n\t\r\nvoid AggregatorMilitary::onRenameSquad( unsigned int id, QString newName )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->renameSquad( id, newName );\r\n}\r\n\r\nvoid AggregatorMilitary::onMoveSquadLeft( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->moveSquadUp( id );\r\n\tsendSquadUpdate();\r\n}\r\n\t\r\nvoid AggregatorMilitary::onMoveSquadRight( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->moveSquadDown( id );\r\n\tsendSquadUpdate();\r\n}\r\n\r\nvoid AggregatorMilitary::onRemoveGnomeFromSquad( unsigned int gnomeID )\r\n{\r\n\tif( !g ) return;\r\n\tif( g->mil()->removeGnome( gnomeID ) )\r\n\t{\r\n\t\tsendSquadUpdate();\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorMilitary::onMoveGnomeLeft( unsigned int gnomeID )\r\n{\r\n\tif( !g ) return;\r\n\tif( g->mil()->moveGnomeUp( gnomeID ) )\r\n\t{\r\n\t\tsendSquadUpdate();\r\n\t}\r\n}\r\n\r\nvoid AggregatorMilitary::onMoveGnomeRight( unsigned int gnomeID )\r\n{\r\n\tif( !g ) return;\r\n\tif( g->mil()->moveGnomeDown( gnomeID ) )\r\n\t{\r\n\t\tsendSquadUpdate();\r\n\t}\r\n}\r\n\r\n\t\r\nvoid AggregatorMilitary::onMovePrioUp( unsigned int squadID, QString type )\r\n{\r\n\tif( !g ) return;\r\n\tif( g->mil()->movePrioUp( squadID, type ) )\r\n\t{\r\n\t\tsendPriorityUpdate( squadID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorMilitary::onMovePrioDown( unsigned int squadID, QString type )\r\n{\r\n\tif( !g ) return;\r\n\tif( g->mil()->movePrioDown( squadID, type ) )\r\n\t{\r\n\t\tsendPriorityUpdate( squadID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorMilitary::onAddRole()\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->addRole();\r\n\tsendRoleUpdate();\r\n}\r\n\t\r\nvoid AggregatorMilitary::onRemoveRole( unsigned int id )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->removeRole( id );\r\n\tsendRoleUpdate();\r\n}\r\n\r\nvoid AggregatorMilitary::onRenameRole( unsigned int id, QString newName )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->renameRole( id, newName );\r\n}\r\n\r\nvoid AggregatorMilitary::onSetArmorType( unsigned int roleID, QString slot, QString type, QString material )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->setArmorType( roleID, slot, type, material );\r\n\tQStringList mats;\r\n\tmats.append( \"any\" );\r\n\r\n\tauto matTypes = DB::select2( \"MaterialType\", \"Uniform_Slots\", \"Type\", type );\r\n\tif( matTypes.size() )\r\n\t{\r\n\t\tauto mt = matTypes.first().toString();\r\n\t\tauto ids = DB::select2( \"ID\", \"Materials\", \"Type\", mt );\r\n\t\tfor( auto id : ids  )\r\n\t\t{\r\n\t\t\tmats.append( id.toString() );\r\n\t\t}\r\n\t}\r\n\r\n\temit signalPossibleMaterials( roleID, slot, mats );\r\n}\r\n\r\nvoid AggregatorMilitary::onSetRole( unsigned int gnomeID, unsigned int roleID )\r\n{\r\n\tif( !g ) return;\r\n\tg->gm()->setRoleID( gnomeID, roleID );\r\n}\r\n\r\nvoid AggregatorMilitary::onSetRoleCivilian( unsigned int roleID, bool value )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->setRoleCivilian( roleID, value );\r\n}\r\n\r\nvoid AggregatorMilitary::onSetAttitude( unsigned int squadID, QString type, MilAttitude attitude )\r\n{\r\n\tif( !g ) return;\r\n\tg->mil()->onSetAttitude( squadID, type, attitude );\r\n}"
  },
  {
    "path": "src/gui/aggregatormilitary.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/militarymanager.h\"\r\n\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\n\r\nstruct GuiSquadGnome\r\n{\r\n\tunsigned int id = 0;\r\n\tQString name;\r\n\r\n\tunsigned int roleID = 0;\r\n};\r\nQ_DECLARE_METATYPE( GuiSquadGnome )\r\n\r\nstruct GuiTargetPriority\r\n{\r\n\tQString id;\r\n\tQString name;\r\n\tMilAttitude attitude;\r\n};\r\nQ_DECLARE_METATYPE( GuiTargetPriority )\r\n\r\n\r\n\r\nstruct GuiSquad\r\n{\r\n\tunsigned int id = 0;\r\n\tQString name;\r\n\tbool showLeftArrow = true;\r\n\tbool showRightArrow = true;\r\n\r\n\tQList<GuiTargetPriority> priorities;\r\n\r\n\tQList<GuiSquadGnome> gnomes;\r\n};\r\nQ_DECLARE_METATYPE( GuiSquad )\r\n\r\nstruct GuiUniformItem\r\n{\r\n\tQString slotName;\r\n\tQString armorType = \"none\"; // plate, heavy plate, chain and so on\r\n\tQString material = \"any\";\r\n\r\n\tQStringList possibleTypesForSlot; // some slots have no bone armor item, held slots or rings are completely different\r\n};\r\nQ_DECLARE_METATYPE( GuiUniformItem )\r\n\r\nstruct GuiMilRole\r\n{\r\n\tunsigned int id = 0;\r\n\tQString name;\r\n\tbool showLeftArrow = false;\r\n\tbool showRightArrow = false;\r\n\r\n\tbool isCivilian;\r\n\r\n\tQList<GuiUniformItem> uniform;\r\n};\r\nQ_DECLARE_METATYPE( GuiMilRole )\r\n\r\n\r\n\r\n\r\n\r\n\r\nclass AggregatorMilitary : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorMilitary( QObject* parent = nullptr );\r\n\t~AggregatorMilitary();\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQList<GuiSquad> m_squads;\r\n\tQList<GuiTargetPriority> m_tmpPriorities;\r\n\tQList<GuiMilRole> m_roles;\r\n\t\r\n\tvoid sendSquadUpdate();\r\n\tvoid sendPriorityUpdate( unsigned int squadID );\r\n\tvoid sendRoleUpdate();\r\n\r\n\tGuiUniformItem createUniformItem( const QString slot, QVariantMap uniVM );\r\n\r\npublic slots:\r\n\tvoid onRequestMilitary();\r\n\tvoid onRequestRoles();\r\n\r\n\tvoid onAddSquad();\r\n\tvoid onRemoveSquad( unsigned int id );\r\n\tvoid onRenameSquad( unsigned int id, QString newName );\r\n\tvoid onMoveSquadLeft( unsigned int id );\r\n\tvoid onMoveSquadRight( unsigned int id );\r\n\tvoid onRemoveGnomeFromSquad( unsigned int gnomeID );\r\n\tvoid onMoveGnomeLeft( unsigned int id );\r\n\tvoid onMoveGnomeRight( unsigned int id );\r\n\r\n\tvoid onMovePrioUp( unsigned int squadID, QString type );\r\n\tvoid onMovePrioDown( unsigned int squadID, QString type );\r\n\r\n\tvoid onAddRole();\r\n\tvoid onRemoveRole( unsigned int id );\r\n\tvoid onRenameRole( unsigned int id, QString newName );\r\n\tvoid onSetRole( unsigned int gnomeID, unsigned int roleID );\r\n\tvoid onSetRoleCivilian( unsigned int roleID, bool value );\r\n\r\n\tvoid onSetArmorType( unsigned int roleID, QString slot, QString type, QString material );\r\n\r\n\tvoid onSetAttitude( unsigned int squadID, QString type, MilAttitude attitude );\r\n\r\nsignals:\r\n\tvoid signalSquads( const QList<GuiSquad>& squads );\r\n\tvoid signalPriorities( unsigned int squadID, const QList<GuiTargetPriority>& priorities );\r\n\tvoid signalRoles( const QList<GuiMilRole>& roles );\r\n\tvoid signalPossibleMaterials( unsigned int roleID, const QString slot, const QStringList mats );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorneighbors.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorneighbors.h\"\r\n\r\n#include \"../game/game.h\"\r\n#include \"../game/neighbormanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n\r\n#include \"../gui/strings.h\"\r\n\r\nAggregatorNeighbors::AggregatorNeighbors( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\t\r\n}\r\n\r\nAggregatorNeighbors::~AggregatorNeighbors()\r\n{\r\n}\r\n\r\nvoid AggregatorNeighbors::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorNeighbors::onRequestNeighborsUpdate()\r\n{\r\n\tif( !g ) return;\r\n\tm_neighborsInfo.clear();\r\n\r\n\tfor( const auto& kingdom : g->nm()->kingdoms() )\r\n\t{\r\n\t\tGuiNeighborInfo gni;\r\n\r\n\t\tgni.id = kingdom.id;\r\n\r\n\t\t//if( kingdom.discovered || Global::debugMode )\r\n\t\t{\r\n\t\t\tgni.discovered = true;\r\n\r\n\t\t\tQString name = kingdom.name + \", \";\r\n\t\t\tswitch( kingdom.type )\r\n\t\t\t{\r\n\t\t\t\tcase KingdomType::GNOME:\r\n\t\t\t\tname += \" a gnome kingdom\";\r\n\t\t\t\tgni.diploMission = true;\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomType::GOBLIN:\r\n\t\t\t\tname += \" a goblin kingdom\";\r\n\t\t\t\t\r\n\t\t\t\tgni.spyMission = true;\r\n\t\t\t\tgni.sabotageMission = true;\r\n\t\t\t\tgni.raidMission = true;\r\n\t\t\t\tgni.diploMission = true;\r\n\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tname += \" we don't know what they are\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\r\n\t\t\tgni.name = name;\r\n\r\n\t\t\tQString distance = \"It takes about \";\r\n\t\t\tdistance += S::gi().numberWord( kingdom.distance / 24 );\r\n\t\t\tdistance += \" days to travel there.\";\r\n\t\t\tgni.distance = distance;\r\n\t\t\t\r\n\t\t\tQString wealth = \"They are \";\r\n\t\t\tswitch ( kingdom.wealth )\t\r\n\t\t\t{\r\n\t\t\t\tcase KingdomWealth::VERYPOOR:\r\n\t\t\t\twealth += \"very poor.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomWealth::POOR:\r\n\t\t\t\twealth += \"poor.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomWealth::AVERAGE:\r\n\t\t\t\twealth += \"doing ok.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomWealth::RICH:\r\n\t\t\t\twealth += \"rich.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomWealth::VERYRICH:\r\n\t\t\t\twealth += \"very rich.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tgni.wealth = wealth;\r\n\r\n\t\t\tQString economy = \"They specialize in \";\r\n\t\t\tswitch (kingdom.economy )\r\n\t\t\t{\r\n\t\t\t\tcase KingdomEconomy::FARMING:\r\n\t\t\t\teconomy += \"farming.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomEconomy::LOGGING:\r\n\t\t\t\teconomy += \"logging.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomEconomy::MINING:\r\n\t\t\t\teconomy += \"mining.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomEconomy::ANIMALBREEDING:\r\n\t\t\t\teconomy += \"breeding animals.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomEconomy::TRADING:\r\n\t\t\t\teconomy += \"trading.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tgni.economy = economy;\r\n\r\n\t\t\tQString military = \"Their military is \";\r\n\t\t\tswitch ( kingdom.military )\t\r\n\t\t\t{\r\n\t\t\t\tcase KingdomMilitary::VERYWEAK:\r\n\t\t\t\tmilitary += \"very weak.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomMilitary::WEAK:\r\n\t\t\t\tmilitary += \"weak.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomMilitary::AVERAGE:\r\n\t\t\t\tmilitary += \"about average.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomMilitary::STRONG:\r\n\t\t\t\tmilitary += \"strong.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase KingdomMilitary::VERYSTRONG:\r\n\t\t\t\tmilitary += \"very strong.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tgni.military = military;\r\n\t\r\n\t\t\tQString attitude = \"They are neutral towards us.\";\r\n\t\t\tif( kingdom.attitude < -75 )\r\n\t\t\t{\r\n\t\t\t\tattitude = \"They consider us their enemies.\";\r\n\t\t\t}\r\n\t\t\telse if( kingdom.attitude < -50  )\r\n\t\t\t{\r\n\t\t\t\tattitude = \"They are very hostile.\";\r\n\t\t\t}\r\n\t\t\telse if( kingdom.attitude < -25 )\r\n\t\t\t{\r\n\t\t\t\tattitude = \"They are hostile.\";\r\n\t\t\t}\r\n\t\t\telse if( kingdom.attitude > 25 )\r\n\t\t\t{\r\n\t\t\t\tattitude = \"They are friendly.\";\r\n\t\t\t}\r\n\t\t\telse if( kingdom.attitude > 50 )\r\n\t\t\t{\r\n\t\t\t\tattitude = \"They are very friendly\";\r\n\t\t\t}\r\n\t\t\telse if( kingdom.attitude > 75 )\r\n\t\t\t{\r\n\t\t\t\tattitude = \"They consider us their friends.\";\r\n\t\t\t}\r\n\t\t\tgni.attitude = attitude;\r\n\t\t}\r\n\r\n\t\tm_neighborsInfo.append( gni );\r\n\t}\r\n\r\n\temit signalNeighborsUpdate( m_neighborsInfo );\r\n}\r\n\r\nvoid AggregatorNeighbors::onRequestMissions()\r\n{\r\n\tif( !g ) return;\r\n\temit signalMissions( g->em()->missions() );\r\n}\r\n\r\nvoid AggregatorNeighbors::onRequestAvailableGnomes()\r\n{\r\n\tif( !g ) return;\r\n\tm_availableGnomes.clear();\r\n\r\n\tfor( auto gnome : g->gm()->gnomes() )\r\n\t{\r\n\t\tif( !gnome->isOnMission() )\r\n\t\t{\r\n\t\t\tm_availableGnomes.append( { gnome->id(), gnome->name() } );\r\n\t\t}\r\n\t}\r\n\r\n\temit signalAvailableGnomes( m_availableGnomes );\r\n}\r\n\r\nvoid AggregatorNeighbors::onStartMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID )\r\n{\r\n\tif( !g ) return;\r\n\tg->em()->startMission( type, action, targetKingdom, gnomeID );\r\n\r\n\temit signalMissions( g->em()->missions() );\r\n}\r\n\r\nvoid AggregatorNeighbors::onUpdateMission( const Mission& mission )\r\n{\r\n\tif( !g ) return;\r\n\temit signalUpdateMission( mission );\r\n}"
  },
  {
    "path": "src/gui/aggregatorneighbors.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/creature.h\"\r\n#include \"../game/eventmanager.h\"\r\n\r\n#include <QObject>\r\n\r\nstruct GuiNeighborInfo\r\n{\r\n\tunsigned int id          = 0;\r\n\tbool discovered          = false;\r\n\tQString distance = \"undiscovered\";\r\n\tQString name = \"undiscovered\";\r\n\tQString type = \"undiscovered\";\r\n\tQString attitude = \"undiscovered\";\r\n\tQString wealth = \"undiscovered\";\r\n\tQString economy = \"undiscovered\";\r\n\tQString military = \"undiscovered\";\r\n\r\n\tbool spyMission = false;\r\n\tbool sabotageMission = false;\r\n\tbool raidMission = false;\r\n\tbool diploMission = false;\r\n};\r\nQ_DECLARE_METATYPE( GuiNeighborInfo )\r\n\r\nstruct GuiAvailableGnome\r\n{\r\n\tunsigned int id = 0;\r\n\tQString name;\r\n};\r\nQ_DECLARE_METATYPE( GuiAvailableGnome )\r\n\r\n\r\n\r\nclass AggregatorNeighbors : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorNeighbors( QObject* parent = nullptr );\r\n\t~AggregatorNeighbors();\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tQList<GuiNeighborInfo> m_neighborsInfo;\r\n\tQList<GuiAvailableGnome> m_availableGnomes;\r\n\r\npublic slots:\r\n\tvoid onRequestNeighborsUpdate();\r\n\tvoid onRequestMissions();\r\n\tvoid onRequestAvailableGnomes();\r\n\tvoid onStartMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID );\r\n\tvoid onUpdateMission( const Mission& mission );\r\n\r\nsignals:\r\n\tvoid signalNeighborsUpdate( const QList<GuiNeighborInfo>& infos );\r\n\tvoid signalMissions( const QList<Mission>& missions );\r\n\tvoid signalAvailableGnomes( const QList<GuiAvailableGnome>& gnomes );\r\n\tvoid signalUpdateMission( const Mission& mission );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorpopulation.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorpopulation.h\"\r\n\r\n#include \"../base/counter.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n\r\nAggregatorPopulation::AggregatorPopulation( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\t//qRegisterMetaType<GuiGnomeScheduleInfo>();\r\n\tqRegisterMetaType<ScheduleActivity>();\r\n\r\n\tfor( auto group : DB::selectRows( \"SkillGroups\" ) )\r\n\t{\r\n\t\tfor( auto skillID : group.value( \"SkillID\" ).toString().split( \"|\" ) )\r\n\t\t{\r\n\t\t\tGuiSkillInfo gsi;\r\n\t\t\tgsi.sid = skillID;\r\n\t\t\tgsi.name = S::s( \"$SkillName_\" + skillID );\r\n\t\t\tgsi.group = group.value( \"ID\" ).toString();\r\n\t\t\tgsi.color = group.value( \"Color\" ).toString();\r\n\t\t\t\r\n\t\t\tm_skillIds.push_back( gsi );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorPopulation::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorPopulation::onRequestPopulationUpdate()\r\n{\r\n\tif( !g ) return;\r\n\r\n\temit signalProfessionList( g->gm()->professions() );\r\n\r\n\tm_populationInfo.gnomes.clear();\r\n\r\n\t//for( int i = 0; i < 100; ++i )\r\n\t{\r\n\t\tfor( auto gnome : g->gm()->gnomes() )\r\n\t\t{\r\n\t\t\tGuiGnomeInfo ggi;\r\n\r\n\t\t\tggi.name = gnome->name();\r\n\t\t\tggi.id = gnome->id();\r\n\t\t\tggi.profession = gnome->profession();\r\n\r\n\t\t\tfor( auto skill : m_skillIds )\r\n\t\t\t{\r\n\t\t\t\tGuiSkillInfo gsi = skill;\r\n\t\t\t\t\r\n\t\t\t\tgsi.level = gnome->getSkillLevel( skill.sid );\r\n\t\t\t\tgsi.active = gnome->getSkillActive( skill.sid );\r\n\t\t\t\tgsi.xpValue = gnome->getSkillXP( skill.sid );\r\n\r\n\t\t\t\tggi.skills.append( gsi );\r\n\t\t\t}\r\n\r\n\t\t\tm_populationInfo.gnomes.append( ggi );\r\n\t\t}\r\n\t}\r\n\tif( m_sortMode == \"Name\" )\r\n\t{\r\n\t\tstd::sort( m_populationInfo.gnomes.begin(), m_populationInfo.gnomes.end(), []( const GuiGnomeInfo& lhs, const GuiGnomeInfo& rhs ){ return lhs.name < rhs.name; } );\r\n\t}\r\n\telse if( m_sortMode == \"Prof\" )\r\n\t{\r\n\t\tstd::sort( m_populationInfo.gnomes.begin(), m_populationInfo.gnomes.end(), []( const GuiGnomeInfo& lhs, const GuiGnomeInfo& rhs ){ return lhs.profession < rhs.profession; } );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tstd::sort( m_populationInfo.gnomes.begin(), m_populationInfo.gnomes.end(), [=]( const GuiGnomeInfo& lhs, const GuiGnomeInfo& rhs ){ \r\n\t\t\tauto lg = g->gm()->gnome( lhs.id );\r\n\t\t\tif( lg )\r\n\t\t\t{\r\n\t\t\t\tauto rg = g->gm()->gnome( rhs.id );\r\n\t\t\t\tif( rg )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( m_revertSort )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn lg->getSkillLevel( m_sortMode ) < rg->getSkillLevel( m_sortMode );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\treturn lg->getSkillLevel( m_sortMode ) > rg->getSkillLevel( m_sortMode );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t} );\r\n\t}\r\n\r\n\temit signalPopulationUpdate( m_populationInfo );\r\n}\r\n\r\nvoid AggregatorPopulation::onUpdateSingleGnome( unsigned int gnomeID )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\r\n\t\tGuiGnomeInfo ggi;\r\n\r\n\t\tggi.name = gnome->name();\r\n\t\tggi.id = gnome->id();\r\n\t\tggi.profession = gnome->profession();\r\n\r\n\t\tfor( auto skill : m_skillIds )\r\n\t\t{\r\n\t\t\tGuiSkillInfo gsi = skill;\r\n\t\t\t\t\r\n\t\t\tgsi.level = gnome->getSkillLevel( skill.sid );\r\n\t\t\tgsi.active = gnome->getSkillActive( skill.sid );\r\n\t\t\tgsi.xpValue = gnome->getSkillXP( skill.sid );\r\n\r\n\t\t\tggi.skills.append( gsi );\r\n\t\t}\r\n\t\temit signalUpdateSingleGnome( ggi );\r\n\t}\r\n}\r\n\r\nvoid AggregatorPopulation::onSetSkillActive( unsigned int gnomeID, QString skillID, bool value )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\tgnome->setSkillActive( skillID, value );\r\n\t}\r\n}\r\n\r\nvoid AggregatorPopulation::onSetAllSkills( unsigned int gnomeID, bool value )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\tfor( const auto& skill : m_skillIds )\r\n\t\t{\r\n\t\t\tgnome->setSkillActive( skill.sid, value );\r\n\t\t}\r\n\t\tonUpdateSingleGnome( gnomeID );\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorPopulation::onSetAllGnomes( QString skillID, bool value )\r\n{\r\n\tif( !g ) return;\r\n\tfor( auto gnome : g->gm()->gnomes() )\r\n\t{\r\n\t\tgnome->setSkillActive( skillID, value );\r\n\t}\r\n\tonRequestPopulationUpdate();\r\n}\r\n\r\nvoid AggregatorPopulation::onSetProfession( unsigned int gnomeID, QString profession )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\tQString oldProf = gnome->profession();\r\n\t\tif( oldProf != profession )\r\n\t\t{\r\n\t\t\tgnome->selectProfession( profession );\r\n\t\t\tonUpdateSingleGnome( gnomeID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorPopulation::onSortGnomes( QString mode )\r\n{\r\n\tif( !g ) return;\r\n\tif( m_sortMode != mode )\r\n\t{\r\n\t\tm_revertSort = false;\r\n\t\tm_sortMode = mode;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_revertSort = !m_revertSort;\r\n\t}\r\n\tonRequestPopulationUpdate();\r\n}\r\n\r\nvoid AggregatorPopulation::onRequestSchedules()\r\n{\r\n\tif( !g ) return;\r\n\tm_scheduleInfo.schedules.clear();\r\n\tfor( auto gnome : g->gm()->gnomes() )\r\n\t{\r\n\t\tGuiGnomeScheduleInfo ggs;\r\n\t\tggs.id = gnome->id();\r\n\t\tggs.name = gnome->name();\r\n\t\tggs.schedule = gnome->schedule();\r\n\r\n\t\tm_scheduleInfo.schedules.append( ggs );\r\n\t}\r\n\r\n\temit signalScheduleUpdate( m_scheduleInfo );\r\n}\r\n\t\r\nvoid AggregatorPopulation::onSetSchedule( unsigned int gnomeID, int hour, ScheduleActivity activity )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\tgnome->setSchedule( hour, activity );\r\n\r\n\t\tGuiGnomeScheduleInfo ggs;\r\n\t\tggs.id = gnome->id();\r\n\t\tggs.name = gnome->name();\r\n\t\tggs.schedule = gnome->schedule();\r\n\r\n\t\temit signalScheduleUpdateSingleGnome( ggs );\r\n\t}\r\n}\r\n\r\nvoid AggregatorPopulation::onSetAllHours( unsigned int gnomeID, ScheduleActivity activity )\r\n{\r\n\tif( !g ) return;\r\n\tauto gnome = g->gm()->gnome( gnomeID );\r\n\tif( gnome )\r\n\t{\r\n\t\tfor( int i = 0; i < 24; ++i )\r\n\t\t{\r\n\t\t\tgnome->setSchedule( i, activity );\r\n\t\t}\r\n\r\n\t\tGuiGnomeScheduleInfo ggs;\r\n\t\tggs.id = gnome->id();\r\n\t\tggs.name = gnome->name();\r\n\t\tggs.schedule = gnome->schedule();\r\n\r\n\t\temit signalScheduleUpdateSingleGnome( ggs );\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorPopulation::onSetHourForAll( int hour, ScheduleActivity activity )\r\n{\r\n\tif( !g ) return;\r\n\tfor( auto gnome : g->gm()->gnomes() )\r\n\t{\r\n\t\tgnome->setSchedule( hour, activity );\r\n\t}\r\n\tonRequestSchedules();\r\n}\r\n\r\nvoid AggregatorPopulation::onRequestProfessions()\r\n{\r\n\tif( !g ) return;\r\n\temit signalProfessionList( g->gm()->professions() );\r\n}\r\n\t\r\nvoid AggregatorPopulation::onRequestSkills( QString profession )\r\n{\r\n\tif( !g ) return;\r\n\tm_profSkills.clear();\r\n\r\n\tauto skillIDs = g->gm()->professionSkills( profession );\r\n\tfor( auto skillID : skillIDs )\r\n\t{\r\n\t\tGuiSkillInfo gsi;\r\n\t\tgsi.sid = skillID;\r\n\t\tgsi.name = S::s( \"$SkillName_\" + skillID );\t\t\r\n\t\t\r\n\t\tm_profSkills.append( gsi );\r\n\t}\r\n\r\n\temit signalProfessionSkills( profession, m_profSkills );\r\n}\r\n\r\nvoid AggregatorPopulation::onUpdateProfession( QString name, QString newName, QStringList skills )\r\n{\r\n\tif( !g ) return;\r\n\tg->gm()->modifyProfession( name, newName, skills );\r\n}\r\n\r\nvoid AggregatorPopulation::onDeleteProfession( QString name )\r\n{\r\n\tif( !g ) return;\r\n\tg->gm()->removeProfession( name );\r\n\temit signalProfessionList( g->gm()->professions() );\r\n}\r\n\t\r\nvoid AggregatorPopulation::onNewProfession()\r\n{\r\n\tif( !g ) return;\r\n\tQString name = g->gm()->addProfession();\r\n\temit signalProfessionList( g->gm()->professions() );\r\n\temit signalSelectEditProfession( name );\r\n}\r\n"
  },
  {
    "path": "src/gui/aggregatorpopulation.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/creature.h\"\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\n\r\nstruct GuiSkillInfo\r\n{\r\n\tQString sid;\r\n\tQString name;\r\n\tint level;\r\n\tfloat xpValue;\r\n\tbool active;\r\n\tQString group;\r\n\tQString color;\r\n};\r\nQ_DECLARE_METATYPE( GuiSkillInfo )\r\n\r\n\r\nstruct GuiGnomeInfo\r\n{\r\n\tQString name;\r\n\tunsigned int id;\r\n\tQList<GuiSkillInfo> skills;\r\n\tQString profession;\r\n};\r\nQ_DECLARE_METATYPE( GuiGnomeInfo )\r\n\r\nstruct GuiPopulationInfo\r\n{\r\n\tQList<GuiGnomeInfo> gnomes;\r\n};\r\nQ_DECLARE_METATYPE( GuiPopulationInfo )\r\n\r\nstruct GuiGnomeScheduleInfo\r\n{\r\n\tQString name;\r\n\tunsigned int id;\r\n\tQList<ScheduleActivity> schedule;\r\n};\r\nQ_DECLARE_METATYPE( GuiGnomeScheduleInfo )\r\n\r\nstruct GuiScheduleInfo\r\n{\r\n\tQList<GuiGnomeScheduleInfo> schedules;\r\n};\r\nQ_DECLARE_METATYPE( GuiScheduleInfo )\r\n\r\n\r\n\r\nclass AggregatorPopulation : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorPopulation( QObject* parent = nullptr );\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tGuiPopulationInfo m_populationInfo;\r\n\r\n\tGuiScheduleInfo m_scheduleInfo;\r\n\r\n\tQList<GuiSkillInfo> m_skillIds;\r\n\t\r\n\tQList<GuiSkillInfo> m_profSkills;\r\n\r\n\tQString m_sortMode = \"Name\";\r\n\tbool m_revertSort = false;\r\n\r\npublic slots:\r\n\tvoid onRequestPopulationUpdate();\r\n\tvoid onUpdateSingleGnome( unsigned int gnomeID );\r\n\tvoid onSetSkillActive( unsigned int gnomeID, QString skillID, bool value );\r\n\tvoid onSetAllSkills( unsigned int gnomeID, bool value );\r\n\tvoid onSetAllGnomes( QString skillID, bool value );\r\n\tvoid onSetProfession( unsigned int gnomeID, QString profession );\r\n\tvoid onSortGnomes( QString mode );\r\n\r\n\tvoid onRequestSchedules();\r\n\tvoid onSetSchedule( unsigned int gnomeID, int hour, ScheduleActivity activity );\r\n\tvoid onSetAllHours( unsigned int gnomeID, ScheduleActivity activity );\r\n\tvoid onSetHourForAll( int hour, ScheduleActivity activity );\r\n\r\n\tvoid onRequestProfessions();\r\n\tvoid onRequestSkills( QString profession );\r\n\r\n\tvoid onUpdateProfession( QString name, QString newName, QStringList skills );\r\n\tvoid onDeleteProfession( QString name );\r\n\tvoid onNewProfession();\r\nsignals:\r\n\tvoid signalPopulationUpdate( const GuiPopulationInfo& info );\r\n\tvoid signalProfessionList( const QStringList& professions );\r\n\tvoid signalProfessionSkills( QString profession, const QList<GuiSkillInfo>& skills );\r\n\r\n\tvoid signalUpdateSingleGnome( const GuiGnomeInfo& gnome );\r\n\r\n\tvoid signalScheduleUpdate( const GuiScheduleInfo& info );\r\n\tvoid signalScheduleUpdateSingleGnome( const GuiGnomeScheduleInfo& info );\r\n\tvoid signalSelectEditProfession( const QString name );\r\n};"
  },
  {
    "path": "src/gui/aggregatorrenderer.cpp",
    "content": "/*\t\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as\n    published by the Free Software Foundation, either version 3 of the\n    License, or (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n#include \"aggregatorrenderer.h\"\n\n#include \"../base/global.h\"\n#include \"../game/game.h\"\n#include \"../game/creature.h\"\n#include \"../game/creaturemanager.h\"\n#include \"../game/gnomemanager.h\"\n#include \"../game/mechanismmanager.h\"\n#include \"../game/world.h\"\n#include \"../gfx/sprite.h\"\n#include \"../gfx/spritefactory.h\"\n\nAggregatorRenderer::AggregatorRenderer( QObject* parent ) :\n\tQObject( parent )\n{\n\tqRegisterMetaType<TileDataUpdateInfo>();\n\tqRegisterMetaType<ThoughtBubbleInfo>();\n\tqRegisterMetaType<AxleDataInfo>();\n}\n\nvoid AggregatorRenderer::init( Game* game )\n{\n\tg = game;\n}\n\nTileDataUpdate AggregatorRenderer::aggregateTile( unsigned int tileID ) const\n{\n\tif( !g ) return TileDataUpdate();\n\tconst auto& tile = g->w()->world()[tileID];\n\tTileData td;\n\tif ( tile.floorSpriteUID )\n\t{\n\t\tunsigned int rot  = ( tile.floorRotation % 4 ) * ROT_BIT;\n\t\ttd.floorSpriteUID = tile.floorSpriteUID + rot;\n\t}\n\n\tif ( tile.wallSpriteUID )\n\t{\n\t\tunsigned int rot = ( tile.wallRotation % 4 ) * ROT_BIT;\n\t\ttd.wallSpriteUID = tile.wallSpriteUID + rot;\n\t\tif ( tile.wallType & WallType::WT_SOLIDWALL )\n\t\t{\n\t\t\ttd.wallSpriteUID += WALL_BIT;\n\t\t}\n\t}\n\n\tif ( tile.itemSpriteUID )\n\t{\n\t\ttd.itemSpriteUID = tile.itemSpriteUID;\n\t}\n\n\tif ( g->w()->hasJob( Position( tileID ) ) )\n\t{\n\t\tQVariantMap job      = g->w()->jobSprite( Position( tileID ) );\n\t\tQVariantMap floorJob = job.value( \"Floor\" ).toMap();\n\t\tQVariantMap wallJob  = job.value( \"Wall\" ).toMap();\n\n\t\tif ( !floorJob.isEmpty() )\n\t\t{\n\t\t\tunsigned int suid    = floorJob.value( \"SpriteUID\" ).toUInt();\n\t\t\tunsigned int rot     = floorJob.value( \"Rot\" ).toUInt() * ROT_BIT;\n\t\t\ttd.jobSpriteFloorUID = suid + rot;\n\t\t}\n\t\tif ( !wallJob.isEmpty() )\n\t\t{\n\t\t\tunsigned int suid   = wallJob.value( \"SpriteUID\" ).toUInt();\n\t\t\tunsigned int rot    = wallJob.value( \"Rot\" ).toUInt() * ROT_BIT;\n\t\t\ttd.jobSpriteWallUID = suid + rot;\n\t\t}\n\t}\n\n\ttd.flags  = (quint64)tile.flags;\n\ttd.flags2 = (quint64)tile.flags >> 32;\n\n\ttd.lightLevel      = qMin( tile.lightLevel, (unsigned char)20 );\n\ttd.fluidLevel      = qMin( tile.fluidLevel, (unsigned char)10 );\n\ttd.vegetationLevel = qMin( tile.vegetationLevel, (unsigned char)100 );\n\n\treturn TileDataUpdate { tileID, td };\n}\n\nQHash<unsigned int, unsigned int> AggregatorRenderer::collectCreatures()\n{\n\tif( !g ) return QHash<unsigned int, unsigned int>();\n\tQHash<unsigned int, unsigned int> creatures;\n\n\tSprite* sprite    = nullptr;\n\n\tunsigned int posID = 0;\n\n\t//TODO remove when we create gnome corpses\n\tfor ( auto gn : g->gm()->deadGnomes() )\n\t{\n\t\tposID = gn->getPos().toInt();\n\t\t{\n\t\t\tunsigned int spriteID = 0;\n\t\t\tsprite                = g->sf()->getCreatureSprite( gn->id(), spriteID );\n\t\t\tif ( sprite )\n\t\t\t{\n\t\t\t\tspriteID += gn->facing() * ROT_BIT;\n\t\t\t}\n\t\t\tcreatures[posID] = spriteID;\n\t\t}\n\t}\n\n\tfor ( auto gn : g->gm()->gnomes() )\n\t{\n\t\tif ( !gn->goneOffMap() )\n\t\t{\n\t\t\tposID = gn->getPos().toInt();\n\t\t\t{\n\t\t\t\tunsigned int spriteID = 0;\n\t\t\t\tsprite                = g->sf()->getCreatureSprite( gn->id(), spriteID );\n\t\t\t\tif ( sprite )\n\t\t\t\t{\n\t\t\t\t\tspriteID += gn->facing() * ROT_BIT;\n\t\t\t\t}\n\t\t\t\tcreatures[posID] = spriteID;\n\t\t\t}\n\t\t}\n\t}\n\tfor ( auto gn : g->gm()->specialGnomes() )\n\t{\n\t\tposID = gn->getPos().toInt();\n\t\t{\n\t\t\tunsigned int spriteID = 0;\n\t\t\tsprite                = g->sf()->getCreatureSprite( gn->id(), spriteID );\n\t\t\tif ( sprite )\n\t\t\t{\n\t\t\t\tspriteID += gn->facing() * ROT_BIT;\n\t\t\t}\n\t\t\tcreatures[posID] = spriteID;\n\t\t}\n\t}\n\n\tfor ( auto a : g->gm()->automatons() )\n\t{\n\t\tposID = a->getPos().toInt();\n\t\t{\n\t\t\tunsigned int spriteID = 0;\n\t\t\tsprite                = g->sf()->getCreatureSprite( a->id(), spriteID );\n\t\t\tif ( sprite )\n\t\t\t{\n\t\t\t\tspriteID += a->facing() * ROT_BIT;\n\t\t\t}\n\t\t\tcreatures[posID] = spriteID;\n\t\t}\n\t}\n\n\tconst auto& creatureList = g->cm()->creatures();\n\n\tfor( const auto& creature : creatureList )\n\t{\n\t\tswitch( creature->type() )\n\t\t{\n\t\t\tcase CreatureType::ANIMAL:\n\t\t\t{\n\t\t\t\tauto a = dynamic_cast<Animal*>( creature );\n\t\t\t\tunsigned int posID = a->getPos().toInt();\n\t\t\t\tif ( !creatures.contains( posID ) && !a->isDead() )\n\t\t\t\t{\n\t\t\t\t\tif ( a->isMulti() )\n\t\t\t\t\t{\n\t\t\t\t\t\tauto sprites = a->multiSprites();\n\t\t\t\t\t\tfor ( auto def : sprites )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tposID                 = def.first.toInt();\n\t\t\t\t\t\t\tunsigned int spriteID = def.second;\n\t\t\t\t\t\t\tcreatures[posID]      = spriteID;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tSprite* sprite        = g->sf()->getSprite( a->spriteUID() );\n\t\t\t\t\t\tunsigned int spriteID = 0;\n\t\t\t\t\t\tif ( sprite )\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tspriteID = sprite->uID;\n\t\t\t\t\t\t\tspriteID += a->facing() * ROT_BIT;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcreatures[posID] = spriteID;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t\tcase CreatureType::MONSTER:\n\t\t\t{\n\t\t\t\tauto m = dynamic_cast<Monster*>( creature );\n\t\t\t\tunsigned int posID = m->getPos().toInt();\n\t\t\t\tif ( !creatures.contains( posID ) && !m->isDead() )\n\t\t\t\t{\n\t\t\t\t\tunsigned int spriteID = 0;\n\t\t\t\t\tsprite                = g->sf()->getCreatureSprite( m->id(), spriteID );\n\t\t\t\t\tif ( sprite )\n\t\t\t\t\t{\n\t\t\t\t\t\tspriteID += m->facing() * ROT_BIT;\n\t\t\t\t\t}\n\t\t\t\t\tcreatures[posID] = spriteID;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\treturn creatures;\n}\n\nvoid AggregatorRenderer::onAllTileInfo()\n{\n\tif( !g ) return;\n\t// Bake tile updates\n\tauto creatures = collectCreatures();\n\tfor ( auto tile = creatures.keyBegin(); tile != creatures.keyEnd(); ++tile )\n\t{\n\t\t//tiles.insert(*tile);\n\t}\n\tconstexpr size_t batchSize = 1 << 16;\n\tTileDataUpdateInfo tileUpdates;\n\ttileUpdates.updates.reserve( batchSize );\n\tconst unsigned int worldSize = (unsigned int)g->w()->world().size();\n\tfor ( unsigned int tileUID = 0; tileUID < worldSize; ++tileUID )\n\t{\n\t\tauto update = aggregateTile( tileUID );\n\n\t\tconst auto creatureSprite = creatures.find( tileUID );\n\t\tif ( creatureSprite != creatures.end() )\n\t\t{\n\t\t\tupdate.tile.creatureSpriteUID = creatureSprite.value();\n\t\t}\n\n\t\ttileUpdates.updates.push_back( update );\n\n\t\tif ( tileUpdates.updates.size() >= batchSize )\n\t\t{\n\t\t\t{\n\t\t\t\temit signalTileUpdates( tileUpdates );\n\t\t\t\ttileUpdates.updates.clear();\n\t\t\t}\n\t\t\ttileUpdates.updates.reserve( batchSize );\n\t\t}\n\t}\n\tif ( !tileUpdates.updates.empty() )\n\t{\n\t\temit signalTileUpdates( tileUpdates );\n\t}\n}\n\nvoid AggregatorRenderer::onUpdateAnyTileInfo( const QSet<unsigned int>& changeSet )\n{\n\tif( !g ) return;\n\t// Bake tile updates\n\tauto creatures = collectCreatures();\n\tfor ( auto tile = creatures.keyBegin(); tile != creatures.keyEnd(); ++tile )\n\t{\n\t\t//tiles.insert(*tile);\n\t}\n\tconstexpr size_t batchSize = 1 << 16;\n\tTileDataUpdateInfo tileUpdates;\n\ttileUpdates.updates.reserve( batchSize );\n\tfor ( auto tileUID : changeSet )\n\t{\n\t\tauto update = aggregateTile( tileUID );\n\n\t\tconst auto creatureSprite = creatures.find( tileUID );\n\t\tif ( creatureSprite != creatures.end() )\n\t\t{\n\t\t\tupdate.tile.creatureSpriteUID = creatureSprite.value();\n\t\t}\n\n\t\ttileUpdates.updates.push_back( update );\n\n\t\tif ( tileUpdates.updates.size() >= batchSize )\n\t\t{\n\t\t\t{\n\t\t\t\temit signalTileUpdates( tileUpdates );\n\t\t\t\ttileUpdates.updates.clear();\n\t\t\t}\n\t\t\ttileUpdates.updates.reserve( batchSize );\n\t\t}\n\t}\n\tif ( !tileUpdates.updates.empty() )\n\t{\n\t\temit signalTileUpdates( tileUpdates );\n\t}\n\n\tif ( g->mcm()->axlesChanged() )\n\t{\n\t\tonAxleDataUpdate();\n\t}\n\tonThoughtBubbleUpdate();\n}\n\nvoid AggregatorRenderer::onThoughtBubbleUpdate()\n{\n\tif( !g ) return;\n\tThoughtBubbleInfo info;\n\tfor ( const auto& gn : g->gm()->gnomes() )\n\t{\n\t\tQString thoughtBubble = gn->thoughtBubble();\n\t\tif ( !thoughtBubble.isEmpty() )\n\t\t{\n\t\t\tinfo.thoughtBubbles.push_back( { gn->getPos(), g->sf()->thoughtBubbleID( thoughtBubble ) } );\n\t\t}\n\t}\n\n\tfor ( const auto& gn : g->cm()->animals() )\n\t{\n\t\tQString thoughtBubble = gn->thoughtBubble();\n\t\tif ( !thoughtBubble.isEmpty() )\n\t\t{\n\t\t\tinfo.thoughtBubbles.push_back( { gn->getPos(), g->sf()->thoughtBubbleID( thoughtBubble ) } );\n\t\t}\n\t}\n\temit signalThoughtBubbles( info );\n}\n\nvoid AggregatorRenderer::onAxleDataUpdate()\n{\n\tif( !g ) return;\n\tAxleDataInfo data;\n\tdata.data = g->mcm()->axleData();\n\temit signalAxleData( data );\n}\n\nvoid AggregatorRenderer::onCenterCamera( const Position& location )\n{\n\tif ( !g ) return;\n\temit signalCenterCamera( location );\n}\n\nvoid AggregatorRenderer::onWorldParametersChanged()\n{\n\tif( !g ) return;\n\temit signalWorldParametersChanged();\n}\n"
  },
  {
    "path": "src/gui/aggregatorrenderer.h",
    "content": "/*\t\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as\n    published by the Free Software Foundation, either version 3 of the\n    License, or (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n#pragma once\n\n#include \"../base/position.h\"\n#include \"../base/tile.h\"\n\n#include <QObject>\n#include <QVector>\n\nclass Game;\n\nstruct TileData\n{\n\tunsigned int flags  = 0;\n\tunsigned int flags2 = 0;\n\n\tunsigned int floorSpriteUID = 0;\n\tunsigned int wallSpriteUID  = 0;\n\n\tunsigned int itemSpriteUID     = 0;\n\tunsigned int creatureSpriteUID = 0;\n\n\tunsigned int jobSpriteFloorUID = 0;\n\tunsigned int jobSpriteWallUID  = 0;\n\n\tunsigned char fluidLevel      = 0;\n\tunsigned char lightLevel      = 0;\n\tunsigned char vegetationLevel = 0;\n\tunsigned char unused3         = 0;\n};\nQ_DECLARE_TYPEINFO( TileData, Q_PRIMITIVE_TYPE );\n\nstruct TileDataUpdate\n{\n\tunsigned int id = 0;\n\tTileData tile;\n};\nQ_DECLARE_TYPEINFO( TileDataUpdate, Q_PRIMITIVE_TYPE );\n\nstruct TileDataUpdateInfo\n{\n\tQVector<TileDataUpdate> updates;\n};\nQ_DECLARE_METATYPE( TileDataUpdateInfo );\n\nstruct SelectionData\n{\n\tPosition pos;\n\tunsigned short spriteID = 0;\n\tbool valid              = true;\n\tbool isFloor            = false;\n\tquint8 localRot         = 0;\n};\n//Q_DECLARE_TYPEINFO( SelectionData, Q_PRIMITIVE_TYPE );\nQ_DECLARE_METATYPE( SelectionData );\n\nstruct ThoughtBubble\n{\n\tPosition pos;\n\tunsigned int sprite;\n};\nQ_DECLARE_TYPEINFO( ThoughtBubble, Q_PRIMITIVE_TYPE );\n\nstruct ThoughtBubbleInfo\n{\n\tQVector<ThoughtBubble> thoughtBubbles;\n};\nQ_DECLARE_METATYPE( ThoughtBubbleInfo );\n\nstruct AxleDataInfo\n{\n\tQHash<unsigned int, AxleData> data;\n};\nQ_DECLARE_METATYPE( AxleDataInfo );\n\nconstexpr size_t TD_SIZE  = sizeof( TileData ) / sizeof( unsigned int );\nconstexpr size_t ROT_BIT  = 0x10000;\nconstexpr size_t ANIM_BIT = 0x40000;\nconstexpr size_t WALL_BIT = 0x80000;\n\nclass AggregatorRenderer : public QObject\n{\n\tQ_OBJECT\n\npublic:\n\tAggregatorRenderer( QObject* parent = nullptr );\n\n\tvoid init( Game* game );\n\nprivate:\n\tQPointer<Game> g;\n\n\tQHash<unsigned int, unsigned int> collectCreatures();\n\tTileDataUpdate aggregateTile( unsigned int tileID ) const;\n\npublic slots:\n\tvoid onWorldParametersChanged();\n\tvoid onAllTileInfo();\n\tvoid onUpdateAnyTileInfo( const QSet<unsigned int>& changeSet );\n\tvoid onThoughtBubbleUpdate();\n\tvoid onAxleDataUpdate();\n\tvoid onCenterCamera( const Position& location );\n\nsignals:\n\tvoid signalWorldParametersChanged();\n\tvoid signalTileUpdates( const TileDataUpdateInfo& updates );\n\tvoid signalThoughtBubbles( const ThoughtBubbleInfo& bubbles );\n\tvoid signalAxleData( const AxleDataInfo& data );\n\tvoid signalCenterCamera( const Position& location );\n};"
  },
  {
    "path": "src/gui/aggregatorselection.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorselection.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/selection.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nAggregatorSelection::AggregatorSelection( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tqRegisterMetaType<SelectionData>();\r\n}\r\n\r\nAggregatorSelection::~AggregatorSelection()\r\n{\r\n}\r\n\r\nvoid AggregatorSelection::onActionChanged( const QString action )\r\n{\r\n\temit signalAction( action );\r\n}\r\n\r\nvoid AggregatorSelection::onUpdateCursorPos( const QString pos )\r\n{\r\n\temit signalCursorPos( pos );\r\n}\r\n\r\nvoid AggregatorSelection::onUpdateFirstClick( const QString pos )\r\n{\r\n\temit signalFirstClick( pos );\r\n}\r\n\r\nvoid AggregatorSelection::onUpdateSize( const QString size )\r\n{\r\n\temit signalSize( size );\r\n}\r\n\r\nvoid AggregatorSelection::onRenderParams( int width, int height, int moveX, int moveY, float scale, int rotation )\r\n{\r\n\tm_width    = width;\r\n\tm_height   = height;\r\n\tm_moveX    = moveX;\r\n\tm_moveY    = moveY;\r\n\tm_scale    = scale;\r\n\tm_rotation = rotation;\r\n}\r\n\r\nvoid AggregatorSelection::onMouse( int mouseX, int mouseY, bool shift, bool ctrl )\r\n{\r\n\tif ( Global::sel )\r\n\t{\r\n\t\tm_cursorPos = calcCursor( mouseX, mouseY, Global::sel->isFloor(), shift );\r\n\t\tGlobal::sel->updateSelection( m_cursorPos, shift, ctrl );\r\n\t\tGlobal::sel->setControlActive( ctrl );\r\n\r\n\t\tonUpdateCursorPos( m_cursorPos.toString() );\r\n\t\tupdateSelection();\r\n\t}\r\n}\r\n\r\nvoid AggregatorSelection::onLeftClick( bool shift, bool ctrl )\r\n{\r\n\tif ( Global::sel )\r\n\t{\r\n\t\tif ( Global::sel->hasAction() )\r\n\t\t{\r\n\t\t\tGlobal::sel->leftClick( m_cursorPos, shift, ctrl );\r\n\t\t\tGlobal::sel->updateSelection( m_cursorPos, shift, ctrl );\r\n\t\t\tupdateSelection();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunsigned int tileID = m_cursorPos.toInt();\r\n\t\t\temit signalSelectTile( tileID );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorSelection::onRightClick()\r\n{\r\n\tif ( Global::sel )\r\n\t{\r\n\t\tGlobal::sel->rightClick( m_cursorPos );\r\n\t\tupdateSelection();\r\n\t}\r\n}\r\n\r\nvoid AggregatorSelection::onRotateSelection()\r\n{\r\n\tif ( Global::sel )\r\n\t{\r\n\t\tGlobal::sel->rotate();\r\n\t\tupdateSelection();\r\n\t}\r\n}\r\n\r\nstatic bool isSelectableWall( const Position& pos )\r\n{\r\n\tconst auto w     = Global::eventConnector->game()->w();\r\n\tconst auto& tile = w->getTile( pos );\r\n\tif ( tile.wallType & WallType::WT_SOLIDWALL )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tif ( Global::showJobs && w->jobSprite( pos ).contains( \"Wall\" ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nstatic bool isSelectableFloor( const Position& pos, bool snapToWallBelow )\r\n{\r\n\tconst auto w     = Global::eventConnector->game()->w();\r\n\tconst auto& tile = w->getTile( pos );\r\n\tif ( tile.floorType != FloorType::FT_NOFLOOR )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\tconst auto& tileBelow = w->getTile( pos.belowOf() );\r\n\tif ( snapToWallBelow )\r\n\t{\r\n\t\tif ( isSelectableWall( pos.belowOf() ) )\r\n\t\t{\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\tif ( Global::showJobs && w->jobSprite( pos ).contains( \"Floor\" ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nPosition AggregatorSelection::calcCursor( int mouseX, int mouseY, bool isFloor, bool useViewLevel ) const\r\n{\r\n\tif ( !Global::sel || !Global::eventConnector || !Global::eventConnector->game() || !Global::eventConnector->game()->w() )\r\n\t{\r\n\t\treturn Position( 0, 0, 0 );\r\n\t}\r\n\r\n\tPosition cursorPos;\r\n\tint dim = Global::dimX;\r\n\tif ( dim == 0 )\r\n\t{\r\n\t\tcursorPos = Position( 0, 0, 0 );\r\n\t\treturn cursorPos;\r\n\t}\r\n\tint viewLevel = GameState::viewLevel;\r\n\tint w2        = ( m_width / m_scale ) / 2;\r\n\tint h2        = ( m_height / m_scale ) / 2;\r\n\r\n\tint x0 = m_moveX + w2;\r\n\tint y0 = m_moveY + h2 + 360;\r\n\r\n\tint rot = m_rotation;\r\n\r\n\tint dimZ = Global::dimZ;\r\n\r\n\tbool zFloorFound = false;\r\n\r\n\tint origViewLevel = viewLevel;\r\n\tint zDiff         = 0;\r\n\twhile ( !zFloorFound && zDiff < 20 )\r\n\t{\r\n\t\tzDiff  = origViewLevel - viewLevel;\r\n\t\tint z0 = qMax( 0, viewLevel - ( viewLevel - 20 ) );\r\n\r\n\t\tint mouseXScaled = (double)( mouseX ) / m_scale;\r\n\t\tint mouseYScaled = (double)( mouseY ) / m_scale - ( zDiff * 4 ) - 3;\r\n\r\n\t\tint column = ( mouseXScaled - x0 ) / 32;\r\n\t\tif ( mouseXScaled < x0 )\r\n\t\t\tcolumn -= 1;\r\n\t\tint row = ( mouseYScaled - y0 - 8 + z0 * 20 ) / 16;\r\n\r\n\t\tfloat quadX = ( mouseXScaled - x0 ) % 32;\r\n\t\tfloat quadY = ( ( mouseYScaled - y0 - 8 + z0 * 20 ) % 16 ) * 2;\r\n\r\n\t\tif ( quadX < 0 )\r\n\t\t{\r\n\t\t\tif ( quadX == -32 )\r\n\t\t\t\tquadX = 0;\r\n\t\t\tquadX = 31 + quadX;\r\n\t\t}\r\n\t\tif ( quadY < 0 )\r\n\t\t\tquadY = 31 + quadY;\r\n\r\n\t\tbool lower  = ( quadX / quadY ) >= 1.0;\r\n\t\tbool lower2 = ( ( 32. - quadX ) / quadY ) > 1.0;\r\n\r\n\t\tbool north = lower && lower2;\r\n\t\tbool south = !lower && !lower2;\r\n\t\tbool east  = lower && !lower2;\r\n\t\tbool west  = !lower && lower2;\r\n\r\n\t\tint selX = 0;\r\n\t\tint selY = 0;\r\n\r\n\t\tif ( south )\r\n\t\t{\r\n\t\t\t//qDebug() << \"south\" << quadX << \" \" << quadY << \" \" << row << \" \" <<  column;\r\n\t\t\tselX = row + 1 + column;\r\n\t\t\tselY = row + 1 - column;\r\n\t\t}\r\n\t\tif ( west )\r\n\t\t{\r\n\t\t\t//qDebug() << \"west\" << quadX << \" \" << quadY << \" \" << row << \" \" <<  column;\r\n\t\t\tselX = row + column;\r\n\t\t\tselY = row + 1 - column;\r\n\t\t}\r\n\t\tif ( north )\r\n\t\t{\r\n\t\t\t//qDebug() << \"north\" << quadX << \" \" << quadY << \" \" << row << \" \" <<  column;\r\n\t\t\tselX = row + column;\r\n\t\t\tselY = row - column;\r\n\t\t}\r\n\t\tif ( east )\r\n\t\t{\r\n\t\t\t//qDebug() << \"east\" << quadX << \" \" << quadY << \" \" << row << \" \" <<  column;\r\n\t\t\tselX = row + 1 + column;\r\n\t\t\tselY = row - column;\r\n\t\t}\r\n\r\n\t\tswitch ( rot )\r\n\t\t{\r\n\t\t\tcase 0:\r\n\t\t\t\tcursorPos.x = qMin( qMax( 0, selX - zDiff - 1 ), dim - 1 );\r\n\t\t\t\tcursorPos.y = qMin( qMax( 0, selY - zDiff - 1 ), dim - 1 );\r\n\t\t\t\tcursorPos.z = qMin( qMax( 0, viewLevel ), dimZ - 1 );\r\n\r\n\t\t\t\tif ( !Global::wallsLowered && cursorPos.valid() && isSelectableWall( cursorPos.seOf() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tcursorPos.x += 1;\r\n\t\t\t\t\tcursorPos.y += 1;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\t\t\tcase 1:\r\n\t\t\t\tcursorPos.x = qMin( qMax( 0, selY - zDiff - 1 ), dim - 1 );\r\n\t\t\t\tcursorPos.y = qMin( qMax( 0, dim - selX + zDiff ), dim - 1 );\r\n\t\t\t\tcursorPos.z = qMin( qMax( 0, viewLevel ), dimZ - 1 );\r\n\t\t\t\tif ( !Global::wallsLowered && cursorPos.valid() && isSelectableWall( cursorPos.neOf() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tcursorPos.x += 1;\r\n\t\t\t\t\tcursorPos.y -= 1;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tcursorPos.x = qMin( qMax( 0, dim - selX + zDiff ), dim - 1 );\r\n\t\t\t\tcursorPos.y = qMin( qMax( 0, dim - selY + zDiff ), dim - 1 );\r\n\t\t\t\tcursorPos.z = qMin( qMax( 0, viewLevel ), dimZ - 1 );\r\n\t\t\t\tif ( !Global::wallsLowered && cursorPos.valid() && isSelectableWall( cursorPos.nwOf() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tcursorPos.x -= 1;\r\n\t\t\t\t\tcursorPos.y -= 1;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tcursorPos.x = qMin( qMax( 0, dim - selY + zDiff ), dim - 1 );\r\n\t\t\t\tcursorPos.y = qMin( qMax( 0, selX - zDiff - 1 ), dim - 1 );\r\n\t\t\t\tcursorPos.z = qMin( qMax( 0, viewLevel ), dimZ - 1 );\r\n\t\t\t\tif ( !Global::wallsLowered && cursorPos.valid() && isSelectableWall( cursorPos.swOf() ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tcursorPos.x -= 1;\r\n\t\t\t\t\tcursorPos.y += 1;\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tif ( cursorPos.z > 0 )\r\n\t\t{\r\n\t\t\tif ( isSelectableFloor(cursorPos, isFloor ) )\r\n\t\t\t{\r\n\t\t\t\tzFloorFound = true;\r\n\t\t\t}\r\n\t\t\telse if ( useViewLevel )\r\n\t\t\t{\r\n\t\t\t\tzFloorFound = true;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t--viewLevel;\r\n\t\t\t\tif ( viewLevel == 1 )\r\n\t\t\t\t{\r\n\t\t\t\t\tzFloorFound = true;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tzFloorFound = true;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( useViewLevel )\r\n\t{\r\n\t\tcursorPos.z = viewLevel;\r\n\t}\r\n\treturn cursorPos;\r\n}\r\n\r\nvoid AggregatorSelection::updateSelection()\r\n{\r\n\tif ( Global::sel->changed() )\r\n\t{\r\n\t\t//DebugScope s( \"update selection\" );\r\n\r\n\t\tQString action = Global::sel->action();\r\n\t\tm_selectionData.clear();\r\n\t\tif ( !action.isEmpty() )\r\n\t\t{\r\n\t\t\tbool isFloor = Global::sel->isFloor();\r\n\r\n\t\t\tQList<QPair<Position, bool>> selection = Global::sel->getSelection();\r\n\r\n\t\t\tQList<QPair<Sprite*, QPair<Position, unsigned char>>> sprites;\r\n\t\t\tQList<QPair<Sprite*, QPair<Position, unsigned char>>> spritesInv;\r\n\r\n\t\t\tint rotation = Global::sel->rotation();\r\n\r\n\t\t\tQList<QVariantMap> spriteIDs;\r\n\r\n\t\t\tif ( action == \"BuildWall\" || action == \"BuildFancyWall\" || action == \"BuildFloor\" || action == \"BuildFancyFloor\" || action == \"BuildRamp\" || action == \"BuildRampCorner\" || action == \"BuildStairs\" )\r\n\t\t\t{\r\n\t\t\t\tspriteIDs = DB::selectRows( \"Constructions_Sprites\", \"ID\", Global::sel->itemID() );\r\n\t\t\t}\r\n\t\t\telse if ( action == \"BuildWorkshop\" )\r\n\t\t\t{\r\n\t\t\t\tspriteIDs = DB::selectRows( \"Workshops_Components\", \"ID\", Global::sel->itemID() );\r\n\t\t\t}\r\n\t\t\telse if ( action == \"BuildItem\" )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap sprite;\r\n\t\t\t\tsprite.insert( \"SpriteID\", DBH::spriteID( Global::sel->itemID() ) );\r\n\t\t\t\tsprite.insert( \"Offset\", \"0 0 0\" );\r\n\t\t\t\tsprite.insert( \"Type\", \"Furniture\" );\r\n\t\t\t\tsprite.insert( \"Material\", Global::sel->material() );\r\n\t\t\t\tspriteIDs.push_back( sprite );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tspriteIDs = DB::selectRows( \"Actions_Tiles\", \"ID\", action );\r\n\t\t\t}\r\n\t\t\tfor ( auto asi : spriteIDs )\r\n\t\t\t{\r\n\t\t\t\tQVariantMap entry = asi;\r\n\t\t\t\tif ( !entry.value( \"SpriteID\" ).toString().isEmpty() )\r\n\t\t\t\t{\r\n\t\t\t\t\tif ( entry.value( \"SpriteID\" ).toString() == \"none\" )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ( !entry.value( \"SpriteIDOverride\" ).toString().isEmpty() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tentry.insert( \"SpriteID\", entry.value( \"SpriteIDOverride\" ).toString() );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// TODO repair rot\r\n\t\t\t\t\tunsigned char localRot = Global::util->rotString2Char( entry.value( \"WallRotation\" ).toString() );\r\n\r\n\t\t\t\t\tSprite* addSpriteValid = nullptr;\r\n\r\n\t\t\t\t\tQStringList mats;\r\n\t\t\t\t\tfor ( auto mv : entry.value( \"Material\" ).toList() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tmats.push_back( mv.toString() );\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( entry.contains( \"Material\" ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\taddSpriteValid = Global::eventConnector->game()->sf()->createSprite( entry[\"SpriteID\"].toString(), mats );\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\taddSpriteValid = Global::eventConnector->game()->sf()->createSprite( entry[\"SpriteID\"].toString(), { \"None\" } );\r\n\t\t\t\t\t}\r\n\t\t\t\t\tPosition offset( 0, 0, 0 );\r\n\t\t\t\t\tif ( entry.contains( \"Offset\" ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQString os      = entry[\"Offset\"].toString();\r\n\t\t\t\t\t\tQStringList osl = os.split( \" \" );\r\n\r\n\t\t\t\t\t\tif ( osl.size() == 3 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\toffset.x = osl[0].toInt();\r\n\t\t\t\t\t\t\toffset.y = osl[1].toInt();\r\n\t\t\t\t\t\t\toffset.z = osl[2].toInt();\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tint rotX = offset.x;\r\n\t\t\t\t\t\tint rotY = offset.y;\r\n\t\t\t\t\t\tswitch ( rotation )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\t\t\toffset.x = -1 * rotY;\r\n\t\t\t\t\t\t\t\toffset.y = rotX;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\t\t\toffset.x = -1 * rotX;\r\n\t\t\t\t\t\t\t\toffset.y = -1 * rotY;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\t\t\toffset.x = rotY;\r\n\t\t\t\t\t\t\t\toffset.y = -1 * rotX;\r\n\t\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\tsprites.push_back( QPair<Sprite*, QPair<Position, unsigned char>>( addSpriteValid, { offset, localRot } ) );\r\n\t\t\t\t\tspritesInv.push_back( QPair<Sprite*, QPair<Position, unsigned char>>( addSpriteValid, { offset, localRot } ) );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tQString os      = entry[\"Offset\"].toString();\r\n\t\t\t\t\tQStringList osl = os.split( \" \" );\r\n\t\t\t\t\tPosition offset( 0, 0, 0 );\r\n\t\t\t\t\tif ( osl.size() == 3 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\toffset.x = osl[0].toInt();\r\n\t\t\t\t\t\toffset.y = osl[1].toInt();\r\n\t\t\t\t\t\toffset.z = osl[2].toInt();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tint rotX = offset.x;\r\n\t\t\t\t\tint rotY = offset.y;\r\n\t\t\t\t\tswitch ( rotation )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tcase 1:\r\n\t\t\t\t\t\t\toffset.x = -1 * rotY;\r\n\t\t\t\t\t\t\toffset.y = rotX;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\t\toffset.x = -1 * rotX;\r\n\t\t\t\t\t\t\toffset.y = -1 * rotY;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\t\toffset.x = rotY;\r\n\t\t\t\t\t\t\toffset.y = -1 * rotX;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tsprites.push_back( QPair<Sprite*, QPair<Position, unsigned char>>( Global::eventConnector->game()->sf()->createSprite( \"SolidSelectionFloor\", { \"None\" } ), { offset, 0 } ) );\r\n\t\t\t\t\tspritesInv.push_back( QPair<Sprite*, QPair<Position, unsigned char>>( Global::eventConnector->game()->sf()->createSprite( \"SolidSelectionFloor\", { \"None\" } ), { offset, 0 } ) );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tunsigned int tileID = 0;\r\n\t\t\tfor ( auto p : selection )\r\n\t\t\t{\r\n\t\t\t\tif ( p.second )\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto as : sprites )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( as.first )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tSelectionData sd;\r\n\t\t\t\t\t\t\tsd.spriteID = as.first->uID;\r\n\t\t\t\t\t\t\tsd.localRot = ( ( rotation + as.second.second ) % 4 );\r\n\t\t\t\t\t\t\tsd.pos      = Position( p.first + as.second.first );\r\n\t\t\t\t\t\t\tsd.pos.setToBounds();\r\n\t\t\t\t\t\t\tsd.isFloor = isFloor;\r\n\t\t\t\t\t\t\tsd.valid   = true;\r\n\t\t\t\t\t\t\tm_selectionData.insert( posToInt( sd.pos, m_rotation ), sd );\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\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tfor ( auto as : spritesInv )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( as.first )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tSelectionData sd;\r\n\t\t\t\t\t\t\tsd.spriteID = as.first->uID;\r\n\t\t\t\t\t\t\tsd.localRot = ( ( rotation + as.second.second ) % 4 );\r\n\t\t\t\t\t\t\tsd.pos      = Position( p.first + as.second.first );\r\n\t\t\t\t\t\t\tsd.pos.setToBounds();\r\n\t\t\t\t\t\t\tsd.isFloor = isFloor;\r\n\t\t\t\t\t\t\tsd.valid   = false;\r\n\t\t\t\t\t\t\tm_selectionData.insert( posToInt( sd.pos, m_rotation ), sd );\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\tbool noDepthTest = ( action == \"DigStairsDown\" || action == \"DigRampDown\" );\r\n\r\n\t\temit signalUpdateSelection( m_selectionData, noDepthTest );\r\n\t}\r\n}\r\n\r\nunsigned int AggregatorSelection::posToInt( Position pos, quint8 rotation )\r\n{\r\n\t//return x + Global::dimX * y + Global::dimX * Global::dimX * z;\r\n\r\n\tswitch ( rotation )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\treturn pos.toInt();\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\treturn pos.x + Global::dimX * ( Global::dimX - pos.y ) + Global::dimX * Global::dimX * pos.z;\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\treturn ( Global::dimX - pos.x ) + Global::dimX * ( Global::dimX - pos.y ) + Global::dimX * Global::dimX * pos.z;\r\n\t\t\tbreak;\r\n\t\tcase 3:\r\n\t\t\treturn ( Global::dimX - pos.x ) + Global::dimX * pos.y + Global::dimX * Global::dimX * pos.z;\r\n\t\t\tbreak;\r\n\t}\r\n\treturn 0;\r\n}"
  },
  {
    "path": "src/gui/aggregatorselection.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"aggregatorrenderer.h\"\r\n\r\n#include \"../base/position.h\"\r\n\r\n#include <QObject>\r\n\r\nclass AggregatorSelection : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorSelection( QObject* parent = nullptr );\r\n\t~AggregatorSelection();\r\n\r\nprivate:\r\n\tPosition calcCursor( int mouseX, int mouseY, bool isFloor, bool useViewLevel ) const;\r\n    void updateSelection();\r\n    unsigned int posToInt( Position pos, quint8 rotation );\r\n\r\n    int m_width = 0;\r\n    int m_height = 0;\r\n    int m_moveX = 0;\r\n    int m_moveY = 0;\r\n    float m_scale = 1.0;\r\n    int m_rotation = 0;\r\n\r\n    Position m_cursorPos;\r\n\r\n    QMap<unsigned int, SelectionData> m_selectionData;\r\n\r\npublic slots:\r\n    void onActionChanged( const QString action );\r\n    void onUpdateCursorPos( const QString pos );\r\n    void onUpdateFirstClick( const QString pos );\r\n    void onUpdateSize( const QString size );\r\n\r\n    void onRenderParams( int width, int height, int moveX, int moveY, float scale, int rotation );\r\n    void onMouse( int mouseX, int mouseY, bool shift, bool ctrl );\r\n    void onLeftClick( bool shift, bool ctrl );\r\n    void onRightClick();\r\n    void onRotateSelection();\r\n\r\nsignals:\r\n    void signalAction( const QString action );\r\n    void signalCursorPos( const QString pos );\r\n    void signalFirstClick( const QString pos );\r\n    void signalSize( const QString size );\r\n\r\n    void signalSelectTile( unsigned int );\r\n\r\n    void signalUpdateSelection( const QMap<unsigned int, SelectionData>& data, bool noDepthTest );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorsettings.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorsettings.h\"\r\n\r\n#include \"../base/config.h\"\r\n\r\n#include <QDebug>\r\n\r\nAggregatorSettings::AggregatorSettings( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\r\n}\r\n\r\nAggregatorSettings::~AggregatorSettings()\r\n{\r\n}\r\n\r\nvoid AggregatorSettings::onRequestSettings()\r\n{\r\n    m_settings.fullscreen = Global::cfg->get( \"fullscreen\" ).toBool();\r\n    m_settings.scale = qMax( 0.5f, Global::cfg->get( \"uiscale\" ).toFloat() );\r\n    m_settings.keyboardSpeed = qMax( 0, qMin( Global::cfg->get( \"keyboardMoveSpeed\" ).toInt(), 200) );\r\n    m_settings.languages.clear();\r\n    m_settings.languages.append( \"en_US\" );\r\n    m_settings.languages.append( \"fr_FR\" );\r\n\r\n    m_settings.language = Global::cfg->get( \"language\" ).toString();\r\n\r\n    m_settings.lightMin = Global::cfg->get( \"lightMin\" ).toFloat() * 100; \r\n\r\n    m_settings.toggleMouseWheel = Global::cfg->get( \"toggleMouseWheel\" ).toBool();\r\n\t \r\n\t m_settings.audioMasterVolume = Global::cfg->get( \"AudioMasterVolume\" ).toFloat() * 100; \r\n\r\n    emit signalUpdateSettings( m_settings );\r\n}\r\n\r\nvoid AggregatorSettings::onSetLanguage( QString language )\r\n{\r\n    Global::cfg->set( \"language\", language );\r\n    //emit signalSetLanguage( language );\r\n}\r\n    \r\nvoid AggregatorSettings::onSetUIScale( float scale )\r\n{\r\n    Global::cfg->set( \"uiscale\", scale );\r\n    emit signalUIScale( scale );\r\n}\r\n\r\nvoid AggregatorSettings::onSetFullScreen( bool value )\r\n{\r\n    Global::cfg->set( \"fullscreen\", value );\r\n    emit signalFullScreen( value );\r\n}\r\n\r\nvoid AggregatorSettings::onSetKeyboardSpeed( int value )\r\n{\r\n    Global::cfg->set( \"keyboardMoveSpeed\", value );\r\n}\r\n\r\nvoid AggregatorSettings::onSetLightMin( int value )\r\n{\r\n    Global::cfg->set( \"lightMin\", (float)value / 100. );\r\n}\r\n\r\nvoid AggregatorSettings::onSetToggleMouseWheel( bool value )\r\n{\r\n    Global::cfg->set( \"toggleMouseWheel\", value );\r\n}\r\n\r\nvoid AggregatorSettings::onRequestUIScale()\r\n{\r\n    float scale = Global::cfg->get( \"uiscale\" ).toFloat();\r\n    emit signalUIScale( scale );\r\n}\r\nvoid AggregatorSettings::onRequestVersion()\r\n{\r\n    QString version = Global::cfg->get( \"CurrentVersion\" ).toString();\r\n    emit signalVersion( version );\r\n}\r\n\r\nvoid AggregatorSettings::onSetAudioMasterVolume( float value )\r\n{\r\n\tGlobal::cfg->set( \"AudioMasterVolume\", (float)value);\r\n}\r\n"
  },
  {
    "path": "src/gui/aggregatorsettings.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QObject>\r\n\r\n\r\nstruct GuiSettings\r\n{\r\n    bool fullscreen = false;\r\n    float scale = 1.0;\r\n    QList<QString> languages;\r\n    QString language;\r\n    int keyboardSpeed = 20;\r\n    int lightMin = 30;\r\n    bool toggleMouseWheel = false;\r\n    float audioMasterVolume = 50.0;\r\n};\r\n\r\nQ_DECLARE_METATYPE( GuiSettings )\r\n\r\nclass AggregatorSettings : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorSettings( QObject* parent = nullptr );\r\n\t~AggregatorSettings();\r\n\r\nprivate:\r\n\tGuiSettings m_settings;\r\n\r\npublic slots:\r\n\tvoid onRequestSettings();\r\n\r\n    void onRequestUIScale();\r\n    void onRequestVersion();\r\n\r\n    void onSetLanguage( QString language );\r\n    void onSetUIScale( float scale );\r\n    void onSetKeyboardSpeed( int value );\r\n    void onSetFullScreen( bool value );\r\n    void onSetLightMin( int value );\r\n    void onSetToggleMouseWheel( bool value );\r\n\tvoid onSetAudioMasterVolume( float value );\r\n\r\nsignals:\r\n\tvoid signalUpdateSettings( const GuiSettings& info );\r\n\r\n    void signalFullScreen( bool value );\r\n    void signalUIScale( float value );\r\n    void signalSetLanguage( QString language );\r\n    void signalVersion( QString version );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorsound.cpp",
    "content": "/*\t\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\n\tCopyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\n\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Affero General Public License as\n\tpublished by the Free Software Foundation, either version 3 of the\n\tLicense, or (at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU Affero General Public License for more details.\n\n\tYou should have received a copy of the GNU Affero General Public License\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n#include \"aggregatorsound.h\"\n\n#include \"../base/config.h\"\n#include \"../base/db.h\"\n#include \"../base/gamestate.h\"\n#include \"../base/position.h\"\n#include \"../game/game.h\"\n#include \"../game/soundmanager.h\"\n#include \"../game/world.h\"\n#include \"../gui/eventconnector.h\"\n#include \"../gui/mainwindowrenderer.h\"\n\n#include <QDebug>\n#include <QJsonDocument>\n\nAggregatorSound::AggregatorSound( QObject* parent ) :\n\tQObject( parent )\n{\n\t//sf::SoundBuffer buffer;\n\tQString exePath = QCoreApplication::applicationDirPath();\n\n\tconnect( Global::eventConnector, &EventConnector::signalCameraPosition, this, &AggregatorSound::onCameraPosition );\n\tauto device    = std::make_shared<AL::Device>();\n\tm_audioContext = std::make_shared<AL::Context>( device );\n\tAL::Context::Lock lock( m_audioContext );\n\tm_audioListener = std::make_shared<AL::Listener>( m_audioContext );\n\ttry\n\t{\n\t\tfor ( size_t i = 0; i < maxOcclusion; ++i )\n\t\t{\n\t\t\tm_occlusionFilter.push_back( std::make_shared<AL::Filter>( m_audioContext ) );\n\t\t\tm_occlusionFilter.back()->setGain( pow( 0.75, i ), pow( 0.75, i ), pow( 0.5, i ) );\n\t\t}\n\t}\n\tcatch ( const std::exception& e )\n\t{\n\t\tqInfo() << \"No OpenAL filter support - falling back to pure volume hacks: \" << e.what();\n\t}\n}\n\nAggregatorSound::~AggregatorSound()\n{\n}\n\nvoid AggregatorSound::init( Game* game )\n{\n\tg = game;\n\n\tAL::Context::Lock lock( m_audioContext );\n\tm_audioListener->setVolume( Global::cfg->get( \"AudioMasterVolume\" ).toFloat() );\n\tQList<QVariantMap> soundList = DB::selectRows( \"Sounds\" );\n\tfor ( auto& sound : soundList )\n\t{\n\t\tQString soundID  = sound.value( \"ID\" ).toString() + \".\" + sound.value( \"Material\" ).toString();\n\t\tQString filename = sound.value( \"SoundFile\" ).toString();\n\t\tQString exePath  = QCoreApplication::applicationDirPath();\n\t\tfilename         = exePath + \"/content/audio/\" + filename;\n\n\t\ttry\n\t\t{\n\t\t\tm_buffers.insert( soundID, std::make_shared<AL::Buffer>( m_audioContext, filename.toStdString() ) );\n\t\t\tqDebug() << \"loaded sound \" << soundID << \" \" << filename;\n\t\t}\n\t\tcatch ( ... )\n\t\t{\n\t\t\tqDebug() << \"unable to load sound\" << soundID << \" \" << filename;\n\t\t}\n\t}\n}\n\nvoid AggregatorSound::onPlayEffect( const SoundEffect& effectRequest )\n{\n\tAL::Context::Lock lock( m_audioContext );\n\n\tQString soundID       = effectRequest.type + \".\";\n\tQString soundMaterial = effectRequest.material;\n\tif ( m_buffers.contains( soundID ) || m_buffers.contains( soundID + soundMaterial ) )\n\t{\n\t\tif ( m_buffers.contains( soundID + soundMaterial ) )\n\t\t{\n\t\t\tsoundID = soundID + soundMaterial;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tQString mat = soundID + soundMaterial;\n\t\t\tif ( Global::debugSound )\n\t\t\t{\n\t\t\t\tqDebug() << \"Unknown sound material \" << mat;\n\t\t\t}\n\t\t}\n\t\tm_activeEffects.append( ActiveEffect {\n\t\t\tfalse,\n\t\t\teffectRequest.origin,\n\t\t\tstd::make_shared<AL::Source>( m_audioContext, m_buffers[soundID] ) } );\n\t\tauto& sound = m_activeEffects.back().sound;\n\t\tsound->setPosition( effectRequest.origin.x, effectRequest.origin.y, effectRequest.origin.z );\n\t\tsound->setRelativeToListener( false );\n\t\tauto pitchVariation = ( ( static_cast<float>( rand() ) / RAND_MAX ) - 0.5 ) * 2;\n\t\t//TODO Factor 1.2 should be configurable per sound effect\n\t\tsound->setPitch( pow( 1.2, pitchVariation ) );\n\t\tif ( rebalanceSound( m_activeEffects.back() ) )\n\t\t{\n\t\t\tsound->play();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_activeEffects.pop_back();\n\t\t}\n\t}\n\tgarbageCollection();\n}\n\nvoid AggregatorSound::onPlayNotify( const SoundEffect& effectRequest )\n{\n\tAL::Context::Lock lock( m_audioContext );\n\n\tQString soundID       = effectRequest.type + \".\";\n\tQString soundMaterial = effectRequest.material;\n\tif ( m_buffers.contains( soundID ) || m_buffers.contains( soundID + soundMaterial ) )\n\t{\n\t\tif ( m_buffers.contains( soundID + soundMaterial ) )\n\t\t{\n\t\t\tsoundID = soundID + soundMaterial;\n\t\t}\n\t\telse\n\t\t{\n\n\t\t\tif ( Global::debugSound )\n\t\t\t{\n\t\t\t\tQString mat = soundID + soundMaterial;\n\t\t\t\tqDebug() << \"Unknown sound material \" << mat;\n\t\t\t}\n\t\t}\n\t\tm_activeEffects.append( ActiveEffect {\n\t\t\ttrue,\n\t\t\tPosition(),\n\t\t\tstd::make_shared<AL::Source>( m_audioContext, m_buffers[soundID] ) } );\n\t\tauto& sound = m_activeEffects.back().sound;\n\t\tsound->setPosition( 0, 0, 0 );\n\t\tsound->setRelativeToListener( true );\n\t\tsound->setPitch( 1 );\n\t\tif ( rebalanceSound( m_activeEffects.back() ) )\n\t\t{\n\t\t\tsound->play();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_activeEffects.pop_back();\n\t\t}\n\t}\n\tgarbageCollection();\n}\n\nbool AggregatorSound::rebalanceSound( ActiveEffect& effect )\n{\n\t//TODO Check if we can get OpenAL band pass and reverb filters somehow working\n\t// Need them to properly do obstructed sound sources and \"stone\" environments\n\teffect.sound->setRelativeToListener( effect.isAbsolute );\n\tif ( !effect.isAbsolute )\n\t{\n\t\tif ( m_viewDirection.z == 0 )\n\t\t{\n\t\t\t//TODO Camera parameters are not known until changed at least once\n\t\t\treturn true;\n\t\t}\n\t\t// Simple line-of-sight check from viewing position\n\t\tPosition trace = effect.pos;\n\t\t// Half loudness per floor, and even less per wall\n\t\tshort occlusion = 0;\n\t\t// Always tone down sounds out of view\n\t\tif ( trace.z > m_viewLevel )\n\t\t{\n\t\t\tocclusion += 1;\n\t\t}\n\t\twhile ( trace.valid() && trace.z != m_viewLevel )\n\t\t{\n\t\t\tif ( trace.z < m_viewLevel )\n\t\t\t{\n\t\t\t\ttrace = trace - m_viewDirection;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrace = trace + m_viewDirection;\n\t\t\t}\n\t\t\tif ( g->w()->wallType( trace ) & WT_SOLIDWALL )\n\t\t\t{\n\t\t\t\tocclusion += 2;\n\t\t\t}\n\t\t\tif ( g->w()->floorType( trace ) & FT_SOLIDFLOOR )\n\t\t\t{\n\t\t\t\tocclusion += 1;\n\t\t\t}\n\t\t}\n\t\tif ( m_occlusionFilter.empty() && occlusion < maxOcclusion )\n\t\t{\n\t\t\t// Without filter support, apply plain loudness reduction\n\t\t\teffect.sound->setVolume( std::pow( 0.75, occlusion ) );\n\t\t}\n\t\telse if ( occlusion < m_occlusionFilter.size() )\n\t\t{\n\t\t\teffect.sound->setDryPathFilter( m_occlusionFilter[occlusion] );\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nvoid AggregatorSound::garbageCollection()\n{\n\t//TODO Get the slot fed externally!\n\tm_audioListener->setVolume( Global::cfg->get( \"AudioMasterVolume\" ).toFloat() );\n\n\tfor ( auto it = m_activeEffects.begin(); it != m_activeEffects.end(); )\n\t{\n\t\tif ( it->sound->getPlayState() == AL::Source::STOPPED )\n\t\t{\n\t\t\tit = m_activeEffects.erase( it );\n\t\t}\n\t\telse\n\t\t{\n\t\t\t++it;\n\t\t}\n\t}\n}\n\nvoid AggregatorSound::onCameraPosition( float x, float y, float z, int r, float scale )\n{\n\tAL::Context::Lock lock( m_audioContext );\n\tgarbageCollection();\n\tm_viewLevel = z;\n\n\t// Compute new listener position\n\tstatic constexpr QVector3D up = {\n\t\t0.f,\n\t\t0.f,\n\t\t1.f\n\t};\n\tfloat angle = 0;\n\tfloat x_rotated;\n\tfloat y_rotated;\n\tswitch ( r )\n\t{\n\t\tcase 0:\n\t\t{\n\t\t\tangle           = ( ( -45. ) * 3.1415 ) / 180.;\n\t\t\tm_viewDirection = { 1, 1, -1 };\n\t\t\tbreak;\n\t\t}\n\t\tcase 1:\n\t\t{\n\t\t\tangle           = ( ( -45. - 90 ) * 3.1415 ) / 180.;\n\t\t\tm_viewDirection = { 1, -1, -1 };\n\t\t\tbreak;\n\t\t}\n\t\tcase 2:\n\t\t{\n\t\t\tangle           = ( ( -45. - 90 - 90 ) * 3.1415 ) / 180.;\n\t\t\tm_viewDirection = { -1, -1, -1 };\n\t\t\tbreak;\n\t\t}\n\t\tcase 3:\n\t\t{\n\t\t\tangle           = ( ( -45. - 90 - 90 - 90 ) * 3.1415 ) / 180.;\n\t\t\tm_viewDirection = { -1, 1, -1 };\n\t\t\tbreak;\n\t\t}\n\t}\n\tQVector3D direction = { static_cast<float>( m_viewDirection.x ), static_cast<float>( m_viewDirection.y ), static_cast<float>( m_viewDirection.z ) };\n\tdirection.normalize();\n\n\tauto right = QVector3D::crossProduct( up, direction );\n\tauto relUp = -QVector3D::crossProduct( right, direction ).normalized();\n\n\tconst float up3f[3]        = { relUp.x(), relUp.y(), relUp.z() };\n\tconst float direction3f[3] = { direction.x(), direction.y(), direction.z() };\n\tm_audioListener->setOrientation( direction3f, up3f );\n\n\tx = -x / 32 + Global::dimX / 2;\n\ty = -y / 16;\n\tx = x - Global::dimX / 2;\n\ty = y - Global::dimY / 2;\n\tx = x * 1.41421; // sqrt(2)\n\ty = y * 1.41421;\n\n\tfloat s = sin( angle );\n\tfloat c = cos( angle );\n\n\tx_rotated = x;\n\ty_rotated = y;\n\n\tfloat xnew = x_rotated * c - y_rotated * s;\n\tfloat ynew = x_rotated * s + y_rotated * c;\n\n\tx_rotated = xnew + Global::dimX / 2;\n\ty_rotated = ynew + Global::dimY / 2;\n\n\t// Center of view on the currently active top-most layer\n\tQVector3D centerOfView = { x_rotated, y_rotated, z };\n\t// Virtual listener is actually floating above\n\tQVector3D listener = centerOfView - direction * 100.f / scale;\n\n\tconst float position3f[3] = { listener.x(), listener.y(), listener.z() };\n\tm_audioListener->setPosition( position3f );\n\n\t// Cull sounds according to new view\n\tauto newEnd = std::remove_if(\n\t\tm_activeEffects.begin(), m_activeEffects.end(),\n\t\t[this]( ActiveEffect& effect )\n\t\t{ return !rebalanceSound( effect ); } );\n\tm_activeEffects.erase( newEnd, m_activeEffects.end() );\n}\n"
  },
  {
    "path": "src/gui/aggregatorsound.h",
    "content": "/*\t\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\n\tCopyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\n\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Affero General Public License as\n\tpublished by the Free Software Foundation, either version 3 of the\n\tLicense, or (at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU Affero General Public License for more details.\n\n\tYou should have received a copy of the GNU Affero General Public License\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n#pragma once\n\n#include \"../base/position.h\"\n\n#include <QList>\n\n#include \"openalwrapper.h\"\n\nclass Job;\nclass Game;\nstruct SoundEffect;\n\nstruct ActiveEffect\n{\n\tbool isAbsolute;\n\tPosition pos;\n\tstd::shared_ptr<AL::Source> sound;\n};\n\n//TODO THe logic in this class doesn't belong in the \"Aggregator\" (server side!), it belongs with the UI\nclass AggregatorSound : public QObject\n{\n\tQ_OBJECT\n\npublic:\n\tAggregatorSound( QObject* parent = nullptr );\n\t~AggregatorSound();\n\n\tvoid init( Game* game );\n\nprivate:\n\tQPointer<Game> g;\n\tQList<ActiveEffect> m_activeEffects;\n\tQMap<QString, std::shared_ptr<AL::Buffer>> m_buffers;\n\tstd::shared_ptr<AL::Context> m_audioContext;\n\tstd::shared_ptr<AL::Listener> m_audioListener;\n\tstatic constexpr size_t maxOcclusion = 8;\n\tstd::vector<std::shared_ptr<AL::Filter>> m_occlusionFilter;\n\n\tint m_viewLevel = 100;\n\tPosition m_viewDirection;\n\n\tbool rebalanceSound( ActiveEffect& effect );\n\tvoid garbageCollection();\npublic slots:\n\tvoid onCameraPosition( float x, float y, float z, int r, float scale );\n\n\tvoid onPlayEffect( const SoundEffect& effect );\n\tvoid onPlayNotify( const SoundEffect& effect );\n};\n"
  },
  {
    "path": "src/gui/aggregatorstockpile.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorstockpile.h\"\r\n\r\n#include \"../base/counter.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gui/strings.h\"\r\n\r\nAggregatorStockpile::AggregatorStockpile( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\tqRegisterMetaType<GuiStockpileInfo>();\r\n}\r\n\r\nAggregatorStockpile::~AggregatorStockpile()\r\n{\r\n}\r\n\r\nvoid AggregatorStockpile::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorStockpile::onOpenStockpileInfoOnTile( unsigned int tileID )\r\n{\r\n\tif( !g ) return;\r\n\tPosition pos( tileID );\r\n\tauto sp = g->spm()->getStockpileAtPos( pos );\r\n\tif ( sp )\r\n\t{\r\n\t\temit signalOpenStockpileWindow( sp->id() );\r\n\t\tonUpdateStockpileInfo( sp->id() );\r\n\t}\r\n}\r\n\r\nvoid AggregatorStockpile::onOpenStockpileInfo( unsigned int stockpileID )\r\n{\r\n\tif( !g ) return;\r\n\temit signalOpenStockpileWindow( stockpileID );\r\n\tonUpdateStockpileInfo( stockpileID );\r\n}\r\n\r\nvoid AggregatorStockpile::onUpdateStockpileInfo( unsigned int stockpileID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( aggregate( stockpileID ) )\r\n\t{\r\n\t\temit signalUpdateInfo( m_info );\r\n\t}\r\n}\r\n\r\nbool AggregatorStockpile::aggregate( unsigned int stockpileID )\r\n{\r\n\tif( !g ) return false;\r\n\tauto sp = g->spm()->getStockpile( stockpileID );\r\n\tif ( sp )\r\n\t{\r\n\t\tm_info.stockpileID       = stockpileID;\r\n\t\tm_info.name              = sp->name();\r\n\t\tm_info.priority          = sp->priority();\r\n\t\tm_info.maxPriority       = g->spm()->maxPriority();\r\n\t\tm_info.suspended         = !sp->active();\r\n\t\tm_info.allowPullFromHere = sp->allowsPull();\r\n\t\tm_info.pullFromOthers    = sp->pullsOthers();\r\n\r\n\t\tm_info.filter = sp->filter();\r\n\r\n\t\tm_info.summary.clear();\r\n\r\n\t\tauto active = m_info.filter.getActive();\r\n\t\tfor ( auto entry : active )\r\n\t\t{\r\n\t\t\tint count = sp->count( entry.first, entry.second );\r\n\t\t\t//if( count > 0 )\r\n\t\t\t{\r\n\t\t\t\t//QIcon icon( Global::util->smallPixmap( Global::sf().createSprite( entry.first, { entry.second } ), season, 0 ) );\r\n\t\t\t\tItemsSummary is;\r\n\t\t\t\tis.itemName     = S::s( \"$ItemName_\" + entry.first );\r\n\t\t\t\tis.materialName = S::s( \"$MaterialName_\" + entry.second );\r\n\t\t\t\tis.count        = count;\r\n\r\n\t\t\t\tm_info.summary.append( is );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid AggregatorStockpile::onUpdateStockpileContent( unsigned int stockpileID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_info.stockpileID == stockpileID )\r\n\t{\r\n\t\tm_contentDirty = true;\r\n\t}\r\n}\r\n\r\nvoid AggregatorStockpile::onUpdateAfterTick()\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_info.stockpileID && m_contentDirty )\r\n\t{\r\n\t\tauto sp       = g->spm()->getStockpile( m_info.stockpileID );\r\n\t\tm_info.filter = sp->filter();\r\n\t\tm_info.summary.clear();\r\n\t\tauto active = m_info.filter.getActive();\r\n\t\tfor ( auto entry : active )\r\n\t\t{\r\n\t\t\tint count = sp->count( entry.first, entry.second );\r\n\t\t\t//if( count > 0 )\r\n\t\t\t{\r\n\t\t\t\t//QIcon icon( Global::util->smallPixmap( Global::sf().createSprite( entry.first, { entry.second } ), season, 0 ) );\r\n\t\t\t\tItemsSummary is;\r\n\t\t\t\tis.itemName     = S::s( \"$ItemName_\" + entry.first );\r\n\t\t\t\tis.materialName = S::s( \"$MaterialName_\" + entry.second );\r\n\t\t\t\tis.count        = count;\r\n\r\n\t\t\t\tm_info.summary.append( is );\r\n\t\t\t}\r\n\t\t}\r\n\t\temit signalUpdateContent( m_info );\r\n\t\tm_contentDirty = false;\r\n\t}\r\n}\r\n\r\nvoid AggregatorStockpile::onSetBasicOptions( unsigned int stockpileID, QString name, int priority, bool suspended, bool pull, bool allowPull )\r\n{\r\n\tif( !g ) return;\r\n\tauto sp = g->spm()->getStockpile( stockpileID );\r\n\tif ( sp )\r\n\t{\r\n\t\t//qDebug() << stockpileID << name << priority << suspended << pull << allowPull;\r\n\t\tsp->setName( name );\r\n\t\tg->spm()->setPriority( stockpileID, priority );\r\n\t\tsp->setActive( !suspended );\r\n\t\tsp->setAllowPull( allowPull );\r\n\t\tsp->setPullOthers( pull );\r\n\t}\r\n}\r\n\r\nvoid AggregatorStockpile::onSetActive( unsigned int stockpileID, bool active, QString category, QString group, QString item, QString material )\r\n{\r\n\tif( !g ) return;\r\n\tqDebug() << \"set active:\" << stockpileID << active << category << group << item << material;\r\n\tauto sp = g->spm()->getStockpile( stockpileID );\r\n\tif ( sp )\r\n\t{\r\n\t\tauto filter = sp->pFilter();\r\n\t\tif ( filter )\r\n\t\t{\r\n\t\t\tif ( group.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tfilter->setCheckState( category, active );\r\n\t\t\t}\r\n\t\t\telse if ( item.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tfilter->setCheckState( category, group, active );\r\n\t\t\t}\r\n\t\t\telse if ( material.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tfilter->setCheckState( category, group, item, active );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tfilter->setCheckState( category, group, item, material, active );\r\n\t\t\t}\r\n\t\t}\r\n\t\tonUpdateStockpileInfo( stockpileID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorStockpile::onCloseWindow()\r\n{\r\n\tm_info.stockpileID = 0;\r\n}\r\n"
  },
  {
    "path": "src/gui/aggregatorstockpile.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/filter.h\"\r\n#include \"../game/stockpile.h\"\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\n\r\nstruct ItemsSummary\r\n{\r\n\tQString itemName;\r\n\tQString materialName;\r\n\tint count;\r\n\t//QList<unsigned int> ids;\r\n};\r\n\r\nstruct GuiStockpileInfo\r\n{\r\n\tunsigned int stockpileID = 0;\r\n\r\n\tQString name;\r\n\tint priority           = 1;\r\n\tint maxPriority        = 1;\r\n\tbool suspended         = false;\r\n\tbool allowPullFromHere = false;\r\n\tbool pullFromOthers    = false;\r\n\tint capacity           = 0;\r\n\tint itemCount          = 0;\r\n\tint reserved           = 0;\r\n\r\n\tFilter filter;\r\n\r\n\tQList<ItemsSummary> summary;\r\n};\r\n\r\nQ_DECLARE_METATYPE( GuiStockpileInfo )\r\n\r\nclass AggregatorStockpile : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorStockpile( QObject* parent = nullptr );\r\n\t~AggregatorStockpile();\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n\tQPointer<Game> g;\r\n\r\n\tbool m_infoDirty    = false;\r\n\tbool m_contentDirty = false;\r\n\r\n\tGuiStockpileInfo m_info;\r\n\r\n\tbool aggregate( unsigned int stockpileID );\r\n\r\npublic slots:\r\n\tvoid onOpenStockpileInfoOnTile( unsigned int tileID );\r\n\tvoid onOpenStockpileInfo( unsigned int stockpileID );\r\n\tvoid onUpdateStockpileInfo( unsigned int stockpileID );\r\n\tvoid onUpdateStockpileContent( unsigned int stockpileID );\r\n\tvoid onUpdateAfterTick();\r\n\r\n\tvoid onSetBasicOptions( unsigned int stockpileID, QString name, int priority, bool suspended, bool pull, bool allowPull );\r\n\tvoid onSetActive( unsigned int stockpileID, bool active, QString category, QString group, QString item, QString material );\r\n\r\n\tvoid onCloseWindow();\r\nsignals:\r\n\tvoid signalOpenStockpileWindow( unsigned int stockpileID );\r\n\tvoid signalUpdateInfo( const GuiStockpileInfo& info );\r\n\tvoid signalUpdateContent( const GuiStockpileInfo& info );\r\n};"
  },
  {
    "path": "src/gui/aggregatortileinfo.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"aggregatortileinfo.h\"\r\n\r\n#include \"../base/counter.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/farmingmanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/stockpilemanager.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gui/strings.h\"\r\n\r\nAggregatorTileInfo::AggregatorTileInfo( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\tqRegisterMetaType<GuiTileInfo>();\r\n}\r\n\r\nAggregatorTileInfo::~AggregatorTileInfo()\r\n{\r\n}\r\n\r\nvoid AggregatorTileInfo::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorTileInfo::onShowTileInfo( unsigned int tileID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_currentTileID != tileID )\r\n\t{\r\n\t\tm_currentTileID = tileID;\r\n\t\tm_tileInfoDirty = true;\r\n\t}\r\n\temit signalShowTileInfo( tileID );\r\n\tonUpdateTileInfo( tileID );\r\n}\r\n\r\nvoid AggregatorTileInfo::onUpdateAnyTileInfo( const QSet<unsigned int>& changeSet )\r\n{\r\n\tif( !g ) return;\r\n\tif ( changeSet.contains( m_currentTileID ) )\r\n\t{\r\n\t\tonUpdateTileInfo( m_currentTileID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorTileInfo::onUpdateTileInfo( unsigned int tileID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_currentTileID == tileID )\r\n\t{\r\n\t\tPosition pos( tileID );\r\n\t\tm_tileInfo.tileID      = tileID;\r\n\t\tm_tileInfo.numGnomes   = g->gm()->gnomesAtPosition( pos ).size();\r\n\t\tm_tileInfo.numAnimals  = g->cm()->animalsAtPosition( pos ).size();\r\n\t\tm_tileInfo.numMonsters = g->cm()->monstersAtPosition( pos ).size();\r\n\t\tm_tileInfo.numItems    = g->inv()->countItemsAtPos( pos );\r\n\r\n\t\tTile& tile   = g->w()->getTile( pos );\r\n\r\n\t\tm_tileInfo.flags = tile.flags;\r\n\r\n\t\tm_tileInfo.possibleTennants.clear();\r\n\r\n\t\tm_tileInfo.wall        = \"\";\r\n\t\tm_tileInfo.floor       = \"\";\r\n\t\tm_tileInfo.embedded    = \"\";\r\n\t\tm_tileInfo.plant       = \"\";\r\n\t\tm_tileInfo.water       = \"\";\r\n\t\tm_tileInfo.constructed = \"\";\r\n\r\n\t\tif ( (bool)( tile.wallType & WT_SOLIDWALL ) && (bool)tile.wallMaterial )\r\n\t\t{\r\n\t\t\tQString wallSID = DBH::materialSID( tile.wallMaterial );\r\n\t\t\tQString wType   = DB::select( \"Type\", \"Materials\", wallSID ).toString();\r\n\t\t\tm_tileInfo.wall = \"Wall: \" + S::s( \"$MaterialName_\" + wallSID ) + \" \" + S::s( \"$GroupName_\" + wType ).toLower();\r\n\t\t}\r\n\r\n\t\tif ( tile.embeddedMaterial )\r\n\t\t{\r\n\t\t\tQString embeddedSID = DBH::materialSID( tile.embeddedMaterial );\r\n\t\t\tQString eType       = DB::select( \"Type\", \"Materials\", embeddedSID ).toString();\r\n\t\t\tm_tileInfo.embedded = \"Embedded: \" + S::s( \"$MaterialName_\" + embeddedSID ) + \" \" + S::s( \"$GroupName_\" + eType ).toLower();\r\n\t\t}\r\n\r\n\t\tif ( tile.floorMaterial )\r\n\t\t{\r\n\t\t\tQString floorSID = DBH::materialSID( tile.floorMaterial );\r\n\t\t\tQString fType    = DB::select( \"Type\", \"Materials\", floorSID ).toString();\r\n\t\t\tm_tileInfo.floor = \"Floor: \" + S::s( \"$MaterialName_\" + floorSID ) + \" \" + S::s( \"$GroupName_\" + fType ).toLower();\r\n\t\t}\r\n\r\n\t\tif ( g->w()->plants().contains( pos.toInt() ) )\r\n\t\t{\r\n\t\t\tPlant& plant                  = g->w()->plants()[pos.toInt()];\r\n\t\t\tm_tileInfo.plant              = \"Plant: \" + plant.getDesignation();\r\n\t\t\tm_tileInfo.plantIsTree        = plant.isTree();\r\n\t\t\tm_tileInfo.plantIsHarvestable = plant.harvestable();\r\n\t\t}\r\n\r\n\t\tif ( tile.fluidLevel )\r\n\t\t{\r\n\t\t\tm_tileInfo.water = \"Water: \" + QString::number( ( 100 / 10 ) * tile.fluidLevel ) + \"% \";\r\n\t\t}\r\n\r\n\t\tm_tileInfo.creatures.clear();\r\n\t\tm_tileInfo.items.clear();\r\n\r\n\t\tif ( m_tileInfo.numItems )\r\n\t\t{\r\n\t\t\tPositionEntry pe;\r\n\r\n\t\t\tg->inv()->getObjectsAtPosition( pos, pe );\r\n\r\n\t\t\tCounter<QString> counter;\r\n\t\t\tfor ( auto item : pe )\r\n\t\t\t{\r\n\t\t\t\tQString itext = \"\";\r\n\t\t\t\tQString info = S::s( \"$MaterialName_\" + g->inv()->materialSID( item ) ) + \" \" + S::s( \"$ItemName_\" + g->inv()->itemSID( item ) );\r\n\t\t\t\t\r\n\t\t\t\tif( g->inv()->isConstructed( item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( g->mcm()->hasMechanism( pos ) )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tunsigned int id = g->mcm()->mechanismID( pos );\r\n\t\t\t\t\t\tm_tileInfo.mechInfo = g->mcm()->mechanismData( id );\r\n\t\t\t\t\t\tm_tileInfo.mechInfo.name = info;\r\n\t\t\t\t\t\tif( item == id )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\telse\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tm_tileInfo.mechInfo.itemID = 0;\r\n\t\t\t\t\t}\r\n\t\t\t\t\titext += \"b\";\r\n\t\t\t\t}\r\n\t\t\t\tif( g->inv()->isInStockpile( item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\titext += \"s\";\r\n\t\t\t\t}\r\n\t\t\t\tif( g->inv()->isInContainer( item ) )\r\n\t\t\t\t{\r\n\t\t\t\t\titext += \"c\";\r\n\t\t\t\t}\r\n\t\t\t\tif( itext.size() )\r\n\t\t\t\t{\r\n\t\t\t\t\tinfo += \"(\";\r\n\t\t\t\t\tinfo += itext;\r\n\t\t\t\t\tinfo += \")\";\r\n\t\t\t\t}\r\n\t\t\t\tcounter.add( info );\r\n\t\t\t}\r\n\t\t\tfor ( auto key : counter.keys() )\r\n\t\t\t{\r\n\t\t\t\tGuiItemInfo git;\r\n\t\t\t\tgit.text = QString::number( counter.count( key ) ) + \"x \" + key;\r\n\t\t\t\t//git.id = item;\r\n\t\t\t\tm_tileInfo.items.append( git );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( ( m_tileInfo.numAnimals + m_tileInfo.numGnomes + m_tileInfo.numMonsters ) > 0 )\r\n\t\t{\r\n\t\t\tif ( m_tileInfo.numGnomes )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto gnome : g->gm()->gnomesAtPosition( pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tGuiTICreatureInfo gct;\r\n\t\t\t\t\tgct.text = \"Gnome: \" + gnome->name();\r\n\t\t\t\t\tgct.id   = gnome->id();\r\n\t\t\t\t\tgct.type = gnome->type();\r\n\t\t\t\t\tif( gct.type == CreatureType::AUTOMATON )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tauto automat = dynamic_cast<Automaton*>( gnome );\r\n\t\t\t\t\t\tgct.text = \"Automaton: \" + gnome->name();\r\n\t\t\t\t\t\tgct.refuel = automat->getRefuelFlag();\r\n\t\t\t\t\t\tgct.coreItem = automat->coreType();\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tm_tileInfo.creatures.append( gct );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( m_tileInfo.numAnimals )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto animal : g->cm()->animalsAtPosition( pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tGuiTICreatureInfo gct;\r\n\t\t\t\t\tgct.text = \"Animal: \" + S::s( \"$CreatureName_\" + animal->name() );\r\n\t\t\t\t\tgct.id   = animal->id();\r\n\t\t\t\t\tm_tileInfo.creatures.append( gct );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif ( m_tileInfo.numMonsters )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto monster : g->cm()->monstersAtPosition( pos ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tGuiTICreatureInfo gct;\r\n\t\t\t\t\tgct.text = \"Monster: \" + S::s( \"$CreatureName_\" + monster->name() );\r\n\t\t\t\t\tgct.id   = monster->id();\r\n\t\t\t\t\tm_tileInfo.creatures.append( gct );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\t// wrap job into a sub-object?\r\n\t\tauto job                         = g->jm()->getJobAtPos( pos );\r\n\t\tm_tileInfo.jobName               = \"\";\r\n\t\tm_tileInfo.jobWorker             = \"\";\r\n\t\tm_tileInfo.jobPriority           = \"\";\r\n\t\tm_tileInfo.requiredTool          = \"\";\r\n\t\tm_tileInfo.requiredToolAvailable = \"\"; // currently just 'exists'\r\n\t\tm_tileInfo.requiredItems.clear();      // exists & is reachable\r\n\t\tm_tileInfo.workPositions = \"\";\r\n\t\tif ( job )\r\n\t\t{\r\n\t\t\tm_tileInfo.jobName = job->type();\r\n\t\t\tauto gnome         = g->gm()->gnome( job->workedBy() );\r\n\t\t\tif ( gnome )\r\n\t\t\t{\r\n\t\t\t\tm_tileInfo.jobWorker = gnome->name();\r\n\t\t\t}\r\n\r\n\t\t\tauto rt = job->requiredTool();\r\n\t\t\tif ( !rt.type.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tm_tileInfo.requiredTool = rt.type + \" level \" + QString::number( rt.level );\r\n\t\t\t}\r\n\r\n\t\t\tm_tileInfo.jobPriority           = QString::number( job->priority() );\r\n\t\t\tm_tileInfo.requiredSkill         = job->requiredSkill();\r\n\t\t\tm_tileInfo.requiredToolAvailable = rt.available ? \"Yes\" : \"No\";\r\n\r\n\t\t\tfor ( auto rim : job->requiredItems() )\r\n\t\t\t{\r\n\t\t\t\tGuiItemInfo git;\r\n\t\t\t\tgit.text     = rim.itemSID;\r\n\t\t\t\tgit.count    = rim.count;\r\n\t\t\t\tgit.material = rim.materialSID;\r\n\r\n\t\t\t\tm_tileInfo.requiredItems.append( git );\r\n\t\t\t}\r\n\r\n\t\t\t// gnome available\r\n\t\t\t// use the CanWork?\r\n\t\t\t// use the gnomemanager to query whether a gnome exists with that skill enabled?\r\n\r\n\t\t\tm_tileInfo.workPositions = QVariant( job->possibleWorkPositions().size() > 0 ).toString();\r\n\t\t}\r\n\r\n\t\tm_tileInfo.designationID   = 0;\r\n\t\tm_tileInfo.designationName = \"\";\r\n\t\tm_tileInfo.designationFlag = m_tileInfo.flags - ~( TileFlag::TF_WORKSHOP + TileFlag::TF_STOCKPILE + TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE + TileFlag::TF_ROOM );\r\n\t\tswitch ( m_tileInfo.designationFlag )\r\n\t\t{\r\n\t\t\tcase TileFlag::TF_WORKSHOP:\r\n\t\t\t{\r\n\t\t\t\tauto ws = g->wsm()->workshopAt( pos );\r\n\t\t\t\tif ( ws )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tileInfo.designationID   = ws->id();\r\n\t\t\t\t\tm_tileInfo.designationName = ws->name();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_STOCKPILE:\r\n\t\t\t{\r\n\t\t\t\tauto sp = g->spm()->getStockpileAtPos( pos );\r\n\t\t\t\tif ( sp )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tileInfo.designationID   = sp->id();\r\n\t\t\t\t\tm_tileInfo.designationName = sp->name();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_GROVE:\r\n\t\t\t{\r\n\t\t\t\tauto gr = g->fm()->getGroveAtPos( pos );\r\n\t\t\t\tif ( gr )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tileInfo.designationID   = gr->id();\r\n\t\t\t\t\tm_tileInfo.designationName = gr->name();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_FARM:\r\n\t\t\t{\r\n\t\t\t\tauto fa = g->fm()->getFarmAtPos( pos );\r\n\t\t\t\tif ( fa )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tileInfo.designationID   = fa->id();\r\n\t\t\t\t\tm_tileInfo.designationName = fa->name();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_PASTURE:\r\n\t\t\t{\r\n\t\t\t\tauto pa = g->fm()->getPastureAtPos( pos );\r\n\t\t\t\tif ( pa )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tileInfo.designationID   = pa->id();\r\n\t\t\t\t\tm_tileInfo.designationName = pa->name();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_ROOM:\r\n\t\t\t{\r\n\t\t\t\tauto ro = g->rm()->getRoomAtPos( pos );\r\n\t\t\t\tif ( ro )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_tileInfo.designationID   = ro->id();\r\n\t\t\t\t\tm_tileInfo.designationName = ro->name();\r\n\t\t\t\t\tm_tileInfo.roomType        = ro->type();\r\n\t\t\t\t\tm_tileInfo.tennant         = ro->owner();\r\n\t\t\t\t\tro->checkEnclosed();\r\n\t\t\t\t\tm_tileInfo.isEnclosed = ro->enclosed();\r\n\t\t\t\t\tro->checkRoofed();\r\n\t\t\t\t\tm_tileInfo.hasRoof      = ro->roofed();\r\n\t\t\t\t\tm_tileInfo.hasAlarmBell = ro->hasAlarmBell();\r\n\t\t\t\t\tm_tileInfo.alarm        = GameState::alarm;\r\n\t\t\t\t\tm_tileInfo.roomValue    = ro->value();              \r\n\r\n\t\t\t\t\tQList<unsigned int> beds = ro->beds();\r\n\t\t\t\t\tint countFree            = beds.size();\r\n\t\t\t\t\tfor ( auto b : beds )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( g->inv()->isInJob( b ) )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t--countFree;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tm_tileInfo.beds = QString::number( countFree ) + \" / \" + QString::number( beds.size() );\r\n\r\n\t\t\t\t\tfor ( auto gnome : g->gm()->gnomes() )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tGuiTICreatureInfo gci { gnome->name(), gnome->id(), gnome->type(), false, \"\" };\r\n\t\t\t\t\t\tif ( gnome->ownedRoom() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif ( gnome->ownedRoom() == ro->id() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tm_tileInfo.tennant = gnome->id();\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tgci.text += \" (R)\";\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tm_tileInfo.possibleTennants.append( gci );\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\temit signalUpdateTileInfo( m_tileInfo );\r\n\t}\r\n}\r\n\r\nvoid AggregatorTileInfo::onRequestStockpileItems( unsigned int tileID )\r\n{\r\n\tif( !g ) return;\r\n\tauto sp = g->spm()->getStockpileAtTileID( tileID );\r\n\r\n\tif ( sp )\r\n\t{\r\n\t\tm_spInfo.stockpileID       = sp->id();\r\n\t\tm_spInfo.name              = sp->name();\r\n\t\tm_spInfo.priority          = sp->priority();\r\n\t\tm_spInfo.maxPriority       = g->spm()->maxPriority();\r\n\t\tm_spInfo.suspended         = !sp->active();\r\n\t\tm_spInfo.allowPullFromHere = sp->allowsPull();\r\n\t\tm_spInfo.pullFromOthers    = sp->pullsOthers();\r\n\t\tm_spInfo.capacity          = sp->capacity( tileID );\r\n\t\tm_spInfo.itemCount         = sp->itemCount( tileID );\r\n\t\tm_spInfo.reserved          = sp->reserved( tileID );\r\n\r\n\t\tm_spInfo.filter = sp->filter();\r\n\r\n\t\tm_spInfo.summary.clear();\r\n\r\n\t\tauto active = m_spInfo.filter.getActive();\r\n\t\tfor ( auto entry : active )\r\n\t\t{\r\n\t\t\tint count = sp->count( entry.first, entry.second );\r\n\t\t\tif ( count > 0 )\r\n\t\t\t{\r\n\t\t\t\t//QIcon icon( Global::util->smallPixmap( Global::sf().createSprite( entry.first, { entry.second } ), season, 0 ) );\r\n\t\t\t\tItemsSummary is;\r\n\t\t\t\tis.itemName     = S::s( \"$ItemName_\" + entry.first );\r\n\t\t\t\tis.materialName = S::s( \"$MaterialName_\" + entry.second );\r\n\t\t\t\tis.count        = count;\r\n\r\n\t\t\t\tm_spInfo.summary.append( is );\r\n\t\t\t}\r\n\t\t}\r\n\t\temit signalUpdateSPInfo( m_spInfo );\r\n\t}\r\n}\r\n\r\nvoid AggregatorTileInfo::onSetTennant( unsigned int designationID, unsigned int gnomeID )\r\n{\r\n\tif( !g ) return;\r\n\tauto room = g->rm()->getRoom( designationID );\r\n\tif ( room )\r\n\t{\r\n\t\tauto oldOwner = room->owner();\r\n\r\n\t\troom->setOwner( gnomeID );\r\n\t\tauto gnome = g->gm()->gnome( gnomeID );\r\n\t\tif ( gnome )\r\n\t\t{\r\n\t\t\tgnome->setOwnedRoom( designationID );\r\n\t\t}\r\n\r\n\t\tauto oldGnome = g->gm()->gnome( oldOwner );\r\n\t\tif ( oldGnome )\r\n\t\t{\r\n\t\t\toldGnome->setOwnedRoom( 0 );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorTileInfo::onSetAlarm( unsigned int designationID, bool value )\r\n{\r\n\tif( !g ) return;\r\n\tswitch ( GameState::alarm )\r\n\t{\r\n\t\tcase 0:\r\n\t\t\t// create alarm job\r\n\t\t\tif ( g->rm()->createAlarmJob( designationID ) )\r\n\t\t\t{\r\n\t\t\t\tGameState::alarm = 1;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase 1:\r\n\t\t\t//cancel alarm job;\r\n\t\t\tg->rm()->cancelAlarmJob( designationID );\r\n\t\tcase 2:\r\n\t\t\tGameState::alarmRoomID = 0;\r\n\t\t\tGameState::alarm       = 0;\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AggregatorTileInfo::onToggleMechActive( unsigned int id )\r\n{\r\n\tg->mcm()->changeActive( id );\r\n}\r\n\t\r\nvoid AggregatorTileInfo::onToggleMechInvert( unsigned int id )\r\n{\r\n\tg->mcm()->changeInverted( id );\r\n}\r\n\r\nvoid AggregatorTileInfo::onSetAutomatonRefuel( unsigned int id, bool refuel )\r\n{\r\n\tauto automat = g->gm()->automaton( id );\r\n\tif( automat )\r\n\t{\r\n\t\tautomat->setRefuelFlag( refuel );\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorTileInfo::onSetAutomatonCore( unsigned int id, QString core )\r\n{\r\n\tauto automat = g->gm()->automaton( id );\r\n\tif( automat )\r\n\t{\r\n\t\tautomat->setCoreType( core );\r\n\t}\r\n}"
  },
  {
    "path": "src/gui/aggregatortileinfo.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/tile.h\"\r\n#include \"../game/creature.h\"\r\n#include \"../game/roommanager.h\"\r\n#include \"../game/mechanismmanager.h\"\r\n#include \"aggregatorstockpile.h\"\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\n\r\nstruct GuiTICreatureInfo\r\n{\r\n\tQString text;\r\n\tunsigned int id = 0;\r\n\tCreatureType type;\r\n\tbool refuel;\r\n\tQString coreItem;\r\n};\r\n\r\nstruct GuiItemInfo\r\n{\r\n\tQString text;\r\n\tunsigned int id = 0;\r\n\tQString material;\r\n\tunsigned int count = 0;\r\n\tbool inStockpile = false;\r\n\tbool inContainer = false;\r\n};\r\n\r\nstruct GuiTileInfo\r\n{\r\n\tunsigned int tileID = 0;\r\n\tTileFlag flags      = TileFlag::TF_NONE;\r\n\r\n\tint numGnomes   = 0;\r\n\tint numAnimals  = 0;\r\n\tint numMonsters = 0;\r\n\r\n\tint numItems = 0;\r\n\r\n\tQString wall;\r\n\tQString floor;\r\n\tQString embedded;\r\n\tQString plant;\r\n\tbool plantIsTree;\r\n\tbool plantIsHarvestable;\r\n\tQString water;\r\n\tQString constructed;\r\n\r\n\tQString jobName;\r\n\tQString jobWorker;\r\n\tQString jobPriority;\r\n\tQString requiredSkill;\r\n\tQString requiredTool;\r\n\tQString requiredToolAvailable;\r\n\tQList<GuiItemInfo> requiredItems;\r\n\tQString workPositions;\r\n\r\n\tQList<GuiTICreatureInfo> creatures;\r\n\tQList<GuiItemInfo> items;\r\n\tQList<GuiTICreatureInfo> possibleTennants;\r\n\tunsigned int tennant = 0;\r\n\r\n\tunsigned int designationID = 0;\r\n\tTileFlag designationFlag   = TileFlag::TF_NONE;\r\n\tQString designationName;\r\n\r\n\tRoomType roomType = RoomType::NotSet;\r\n\tbool hasAlarmBell = false;\r\n\tbool isEnclosed   = false;\r\n\tbool hasRoof      = false;\r\n\tQString beds;\r\n\tbool alarm = false;\r\n\tunsigned int roomValue = 0;\r\n\r\n\tMechanismData mechInfo;\r\n};\r\n\r\nQ_DECLARE_METATYPE( GuiTileInfo )\r\n\r\nclass AggregatorTileInfo : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorTileInfo( QObject* parent = nullptr );\r\n\t~AggregatorTileInfo();\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n    QPointer<Game> g;\r\n\r\n\tunsigned int m_currentTileID = 0;\r\n\tbool m_tileInfoDirty         = false;\r\n\tGuiTileInfo m_tileInfo;\r\n\tGuiStockpileInfo m_spInfo;\r\n\r\npublic slots:\r\n\tvoid onShowTileInfo( unsigned int tileID );\r\n\tvoid onUpdateAnyTileInfo( const QSet<unsigned int>& changeSet );\r\n\tvoid onUpdateTileInfo( unsigned int tileID );\r\n\tvoid onRequestStockpileItems( unsigned int tileID );\r\n\tvoid onSetTennant( unsigned int designationID, unsigned int gnomeID );\r\n\tvoid onSetAlarm( unsigned int designationID, bool value );\r\n\tvoid onToggleMechActive( unsigned int id );\r\n\tvoid onToggleMechInvert( unsigned int id );\r\n\tvoid onSetAutomatonRefuel( unsigned int id, bool refuel );\r\n\tvoid onSetAutomatonCore( unsigned int id, QString core );\r\n\r\nsignals:\r\n\tvoid signalShowTileInfo( unsigned int id );\r\n\tvoid signalUpdateTileInfo( const GuiTileInfo& info );\r\n\tvoid signalUpdateSPInfo( const GuiStockpileInfo& info );\r\n};\r\n"
  },
  {
    "path": "src/gui/aggregatorworkshop.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"aggregatorworkshop.h\"\r\n\r\n#include \"../base/counter.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/dbhelper.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/creaturemanager.h\"\r\n#include \"../game/gnomemanager.h\"\r\n#include \"../game/gnometrader.h\"\r\n#include \"../game/inventory.h\"\r\n#include \"../game/workshopmanager.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gui/strings.h\"\r\n\r\n#include <QDebug>\r\n\r\nvoid GuiWorkshopComponent::updateMaterials( QVariantMap row )\r\n{\r\n\tif( !g ) return;\r\n\tmaterials.clear();\r\n\r\n\tauto mats = g->inv()->materialCountsForItem( sid );\r\n\r\n\tauto allowedMats = Global::util->possibleMaterials( row.value( \"AllowedMaterial\" ).toString(), row.value( \"AllowedMaterialType\" ).toString() );\r\n\tif ( !allowedMats.isEmpty() )\r\n\t{\r\n\t\tfor ( auto mat : allowedMats )\r\n\t\t{\r\n\t\t\tmaterials.append( GuiWorkshopMaterial { mat, mats[mat] } );\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\tQString anyString = \"any\";\r\n\tif ( row.value( \"RequireSame\" ).toBool() )\r\n\t{\r\n\t\tanyString += \" (same)\";\r\n\t}\r\n\tmaterials.append( GuiWorkshopMaterial { anyString, mats[\"any\"] } );\r\n\r\n\tmats.remove( \"any\" );\r\n\tfor ( auto key : mats.keys() )\r\n\t{\r\n\t\tmaterials.append( GuiWorkshopMaterial { key, mats[key] } );\r\n\t}\r\n}\r\n\r\nvoid GuiWorkshopProduct::updateComponents()\r\n{\r\n\tif( !g ) return;\r\n\tcomponents.clear();\r\n\r\n\tfor ( auto row : DB::selectRows( \"Crafts_Components\", sid ) )\r\n\t{\r\n\t\tGuiWorkshopComponent gwp { g, row.value( \"ItemID\" ).toString(), row.value( \"Amount\" ).toInt(), row.value( \"RequireSame\" ).toBool(), {} };\r\n\t\tgwp.updateMaterials( row );\r\n\t\tcomponents.append( gwp );\r\n\t}\r\n}\r\n\r\nAggregatorWorkshop::AggregatorWorkshop( QObject* parent ) :\r\n\tQObject(parent)\r\n{\r\n\tqRegisterMetaType<GuiWorkshopInfo>();\r\n}\r\n\r\nAggregatorWorkshop::~AggregatorWorkshop()\r\n{\r\n}\r\n\r\nvoid AggregatorWorkshop::init( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nvoid AggregatorWorkshop::onOpenWorkshopInfoOnTile( unsigned int tileID )\r\n{\r\n\tif( !g ) return;\r\n\tPosition pos( tileID );\r\n\tauto ws = g->wsm()->workshopAt( pos );\r\n\tif ( ws )\r\n\t{\r\n\t\tm_info.workshopID = ws->id();\r\n\t\temit signalOpenWorkshopWindow( ws->id() );\r\n\t\tonUpdateWorkshopInfo( ws->id() );\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onOpenWorkshopInfo( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tm_info.workshopID = workshopID;\r\n\temit signalOpenWorkshopWindow( workshopID );\r\n\tonUpdateWorkshopInfo( workshopID );\r\n}\r\n\r\nvoid AggregatorWorkshop::onUpdateWorkshopInfo( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( aggregate( workshopID ) )\r\n\t{\r\n\t\temit signalUpdateInfo( m_info );\r\n\t}\r\n}\r\n\r\nbool AggregatorWorkshop::aggregate( unsigned int workshopID )\r\n{\r\n\tif( !g ) return false;\r\n\tif ( m_info.workshopID == workshopID )\r\n\t{\r\n\t\tauto ws = g->wsm()->workshop( workshopID );\r\n\t\tif ( ws )\r\n\t\t{\r\n\t\t\tm_info.name             = ws->name();\r\n\t\t\tm_info.priority         = g->wsm()->priority( workshopID );\r\n\t\t\tm_info.maxPriority      = g->wsm()->maxPriority();\r\n\t\t\tm_info.suspended        = !ws->active();\r\n\t\t\tm_info.gui              = ws->gui();\r\n\t\t\tm_info.acceptGenerated  = ws->isAcceptingGenerated();\r\n\t\t\tm_info.autoCraftMissing = ws->getAutoCraftMissing();\r\n\t\t\tm_info.linkStockpile    = (bool)ws->linkedStockpile();\r\n\r\n\t\t\tm_info.products.clear();\r\n\r\n\t\t\tif ( m_info.gui.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tfor ( auto craft : ws->crafts() )\r\n\t\t\t\t{\r\n\t\t\t\t\tGuiWorkshopProduct gwp;\r\n\t\t\t\t\tgwp.g = g;\r\n\t\t\t\t\tgwp.sid = craft;\r\n\t\t\t\t\tgwp.updateComponents();\r\n\t\t\t\t\tm_info.products.append( gwp );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse if ( m_info.gui == \"Butcher\" )\r\n\t\t\t{\r\n\t\t\t\tm_info.butcherExcess  = ws->butcherExcess();\r\n\t\t\t\tm_info.butcherCorpses = ws->butcherCorpses();\r\n\t\t\t}\r\n\t\t\tm_info.catchFish = ws->fish();\r\n\t\t\tm_info.processFish = ws->processFish();\r\n\r\n\t\t\tm_info.jobList = ws->jobList();\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool AggregatorWorkshop::updateCraftList( unsigned int workshopID )\r\n{\r\n\tif( !g ) return false;\r\n\tif ( m_info.workshopID == workshopID )\r\n\t{\r\n\t\tauto ws = g->wsm()->workshop( workshopID );\r\n\t\tif ( ws )\r\n\t\t{\r\n\t\t\tm_info.jobList = ws->jobList();\r\n\t\t\temit signalUpdateCraftList( m_info );\r\n\r\n\t\t\treturn true;\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid AggregatorWorkshop::onCraftListChanged( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tupdateCraftList( workshopID );\r\n}\r\n\r\nvoid AggregatorWorkshop::onUpdateWorkshopContent( unsigned int WorkshopID )\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_info.workshopID == WorkshopID )\r\n\t{\r\n\t\tm_contentDirty = true;\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onUpdateAfterTick()\r\n{\r\n\tif( !g ) return;\r\n\tif ( m_info.workshopID && m_contentDirty )\r\n\t{\r\n\t\tif ( aggregate( m_info.workshopID ) )\r\n\t\t{\r\n\t\t\temit signalUpdateContent( m_info );\r\n\t\t\tm_contentDirty = false;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onSetBasicOptions( unsigned int workshopID, QString name, int priority, bool suspended, bool acceptGenerated, bool autoCraftMissing, bool connectStockpile )\r\n{\r\n\tif( !g ) return;\r\n\tauto ws = g->wsm()->workshop( workshopID );\r\n\tif ( ws )\r\n\t{\r\n\t\tws->setName( name );\r\n\t\tg->wsm()->setPriority( workshopID, priority );\r\n\t\tws->setActive( !suspended );\r\n\t\tws->setAcceptGenerated( acceptGenerated );\r\n\t\tws->setAutoCraftMissing( autoCraftMissing );\r\n\t\tws->setLinkedStockpile( connectStockpile );\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onSetButcherOptions( unsigned int workshopID, bool butcherCorpses, bool butcherExcess )\r\n{\r\n\tif( !g ) return;\r\n\tauto ws = g->wsm()->workshop( workshopID );\r\n\tif ( ws )\r\n\t{\r\n\t\tws->setButcherCorpses( butcherCorpses );\r\n\t\tws->setButcherExcess( butcherExcess );\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onSetFisherOptions( unsigned int workshopID, bool catchFish, bool processFish )\r\n{\r\n\tif( !g ) return;\r\n\tauto ws = g->wsm()->workshop( workshopID );\r\n\tif ( ws )\r\n\t{\r\n\t\tws->setFish( catchFish );\r\n\t\tws->setProcessFish( processFish );\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onCraftItem( unsigned int workshopID, QString craftID, int mode, int number, QStringList mats )\r\n{\r\n\tif( !g ) return;\r\n\tauto ws = g->wsm()->workshop( workshopID );\r\n\tif ( ws )\r\n\t{\r\n\t\tws->addJob( craftID, mode, number, mats );\r\n\t\tupdateCraftList( workshopID );\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onCloseWindow()\r\n{\r\n\tm_info.workshopID = 0;\r\n}\r\n\r\nvoid AggregatorWorkshop::onCraftJobCommand( unsigned int workshopID, unsigned int craftJobID, QString command )\r\n{\r\n\tif( !g ) return;\r\n\tauto ws = g->wsm()->workshop( workshopID );\r\n\tif ( ws )\r\n\t{\r\n\t\tif ( command == \"Cancel\" )\r\n\t\t{\r\n\t\t\tws->cancelJob( craftJobID );\r\n\t\t\tupdateCraftList( workshopID );\r\n\t\t}\r\n\t\telse if ( command == \"Up\" || command == \"Top\" || command == \"Down\" || command == \"Bottom\" )\r\n\t\t{\r\n\t\t\tif ( ws->moveJob( craftJobID, command ) )\r\n\t\t\t{\r\n\t\t\t\tupdateCraftList( workshopID );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onCraftJobParams( unsigned int workshopID, unsigned int craftJobID, int mode, int numToCraft, bool suspended, bool moveBack )\r\n{\r\n\tif( !g ) return;\r\n\tauto ws = g->wsm()->workshop( workshopID );\r\n\tif ( ws )\r\n\t{\r\n\t\tws->setJobParams( craftJobID, mode, numToCraft, suspended, moveBack );\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onRequestAllTradeItems( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tupdateTraderStock( workshopID );\r\n\t\r\n\tupdatePlayerStock( workshopID );\r\n}\r\n\r\nvoid AggregatorWorkshop::updateTraderStock( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tauto workshop = g->wsm()->workshop( workshopID );\r\n\r\n\tif( workshop )\r\n\t{\r\n\t\tunsigned int traderID = workshop->assignedGnome();\r\n\r\n\t\tm_traderID = traderID;\r\n\r\n\t\tm_traderStock.clear();\r\n\r\n\t\tif( traderID )\r\n\t\t{\r\n\t\t\tGnomeTrader* gt = g->gm()->trader( traderID );\r\n\t\t\tif( gt )\r\n\t\t\t{\r\n\t\t\t\tauto& items = gt->inventory();\r\n\t\t\t\t\t\r\n\t\t\t\tupdateTraderStock( items );\r\n\r\n\t\t\t\temit signalTraderStock( m_traderStock );\r\n\r\n\t\t\t\tupdateTraderValue();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::updateTraderStock( const QList<TraderItem>& source )\r\n{\r\n\tif( !g ) return;\r\n\tm_traderStock.clear();\r\n\r\n\tfor( auto item : source )\r\n\t{\r\n\t\tGuiTradeItem gti;\r\n\t\tgti.itemSID = item.itemSID;\r\n\t\tgti.value = item.value;\r\n\t\tgti.count = item.amount;\r\n\t\tgti.reserved = item.reserved;\r\n\t\tgti.quality = item.quality;\r\n\r\n\t\tif( item.type == \"Animal\" )\r\n\t\t{\r\n\t\t\tgti.materialSIDorGender = item.gender;\r\n\t\t\tgti.name = \tgti.materialSIDorGender + \" \" + S::s( \"$CreatureName_\" + gti.itemSID ) + \" (\" + QString::number( gti.value ) + \")\";\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tgti.materialSIDorGender = item.materialSID;\r\n\t\t\t\r\n\t\t\tQString qName;\r\n\t\t\tQString qID;\r\n\t\t\tif( DB::select( \"HasQuality\", \"Items\", gti.itemSID ).toBool() )\r\n\t\t\t{\r\n\t\t\t\tqID = DBH::qualitySID( 3 );\r\n\t\t\t\tqName= S::s( \"$QualityName_\" + qID ) + \" \";\r\n\t\t\t}\r\n\r\n\t\t\tgti.name = qName + S::s( \"$MaterialName_\" + gti.materialSIDorGender ) + \" \" + S::s( \"$ItemName_\" + gti.itemSID ) + \" (\" + QString::number( gti.value ) + \")\";\r\n\t\t}\r\n\t\tm_traderStock.append( gti );\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorWorkshop::updatePlayerStock( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tm_playerStock.clear();\r\n\r\n\tfor( auto category : g->inv()->categories() )\r\n\t{\r\n\t\tfor( auto group : g->inv()->groups( category ) )\r\n\t\t{\r\n\t\t\tfor( auto item : g->inv()->items( category, group ) )\r\n\t\t\t{\r\n\t\t\t\tQList<QString> mats = g->inv()->materials( category, group, item );\r\n\t\t\t\tfor( auto mat : mats )\r\n\t\t\t\t{\r\n\t\t\t\t\tint count = g->inv()->itemCountInStockpile( item, mat );\r\n\t\t\t\t\tif( count > 0 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tQList<unsigned int> itemList = g->inv()->tradeInventory( item, mat );\r\n\r\n\t\t\t\t\t\tCounter<unsigned int> counter;\r\n\t\t\t\t\t\tQMap<unsigned int, unsigned int>values;\r\n\t\t\t\t\t\tQMap<int, QList<unsigned int>> vlItems;\r\n\t\t\t\t\t\tfor( auto itemUID : itemList )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( DB::select( \"HasQuality\", \"Items\", item ).toBool() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tint qual = g->inv()->quality( itemUID );\r\n\t\t\t\t\t\t\t\tcounter.add( qual );\r\n\t\t\t\t\t\t\t\tvlItems[qual].append( itemUID );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse \r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tcounter.add( 2 ); // Rank 2 is 1.0 modifier\r\n\t\t\t\t\t\t\t\tvlItems[2].append( itemUID );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tfor( auto key : counter.keys() )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tGuiTradeItem gti;\r\n\r\n\t\t\t\t\t\t\tQString qName;\r\n\t\t\t\t\t\t\tQString qID;\r\n\t\t\t\t\t\t\tif( DB::select( \"HasQuality\", \"Items\", item ).toBool() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tqID = DBH::qualitySID( (int)key );\r\n\t\t\t\t\t\t\t\tqName= S::s( \"$QualityName_\" + qID ) + \" \";\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tgti.itemSID = item;\r\n\t\t\t\t\t\t\tgti.materialSIDorGender = mat;\r\n\t\t\t\t\t\t\tgti.value = g->inv()->getTradeValue( item, mat, key );\r\n\t\t\t\t\t\t\tgti.quality = key; \r\n\t\t\t\t\t\t\tgti.count = vlItems[(int)key].size();\r\n\r\n\t\t\t\t\t\t\tgti.name = qName + S::s( \"$MaterialName_\" + mat ) + \" \" + S::s( \"$ItemName_\" + item ) + \" (\" + QString::number( gti.value ) + \")\";\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\tm_playerStock.append( gti );\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\temit signalPlayerStock( m_playerStock );\r\n\r\n}\r\n\r\nvoid AggregatorWorkshop::onTraderStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\tif( !g ) return;\r\n\tauto workshop = g->wsm()->workshop( workshopID );\r\n\r\n\tif( workshop )\r\n\t{\r\n\t\tunsigned int traderID = workshop->assignedGnome();\r\n\t\t\r\n\t\tm_traderID = traderID;\r\n\r\n\t\tif( traderID )\r\n\t\t{\r\n\t\t\tGnomeTrader* gt = g->gm()->trader( traderID );\r\n\t\t\tif( gt )\r\n\t\t\t{\r\n\t\t\t\tauto& items = gt->inventory();\r\n\t\t\t\t\t\r\n\t\t\t\tfor( auto& item : items )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( item.itemSID == itemSID && ( item.materialSID == materialSID || item.gender == materialSID ) && item.quality == quality )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\titem.reserved = qMin( item.amount, item.reserved + count );\r\n\r\n\t\t\t\t\t\tfor( auto& gti : m_traderStock )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( gti.itemSID == itemSID && gti.materialSIDorGender == materialSID && gti.quality == quality )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tgti.reserved = item.reserved;\r\n\t\t\t\t\t\t\t\temit signalUpdateTraderStockItem( gti );\r\n\t\t\t\t\t\t\t\tupdateTraderValue();\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}\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}\r\n\t}\r\n}\r\n\t\r\nvoid AggregatorWorkshop::onTraderOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\tif( !g ) return;\r\n\tauto workshop = g->wsm()->workshop( workshopID );\r\n\r\n\tif( workshop )\r\n\t{\r\n\t\tunsigned int traderID = workshop->assignedGnome();\r\n\t\t\r\n\t\tm_traderID = traderID;\r\n\r\n\t\tif( traderID )\r\n\t\t{\r\n\t\t\tGnomeTrader* gt = g->gm()->trader( traderID );\r\n\t\t\tif( gt )\r\n\t\t\t{\r\n\t\t\t\tauto& items = gt->inventory();\r\n\t\t\t\t\t\r\n\t\t\t\tfor( auto& item : items )\r\n\t\t\t\t{\r\n\t\t\t\t\tif( item.itemSID == itemSID && (item.materialSID == materialSID || item.gender == materialSID) && item.quality == quality )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\titem.reserved = qMax( 0, item.reserved - count );\r\n\r\n\t\t\t\t\t\tfor( auto& gti : m_traderStock )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( gti.itemSID == itemSID && gti.materialSIDorGender == materialSID && gti.quality == quality )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tgti.reserved = item.reserved;\r\n\t\t\t\t\t\t\t\temit signalUpdateTraderStockItem( gti );\r\n\t\t\t\t\t\t\t\tupdateTraderValue();\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}\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}\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onPlayerStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\tif( !g ) return;\r\n\tfor( auto& item : m_playerStock )\r\n\t{\r\n\t\tif( item.itemSID == itemSID && item.materialSIDorGender == materialSID && item.quality == quality )\r\n\t\t{\r\n\t\t\tif (count > 0)\r\n\t\t\t{\r\n\t\t\t\titem.reserved = qMin( item.count, item.reserved + count );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\titem.reserved = item.count;\r\n\t\t\t}\r\n\t\t\r\n\t\t\temit signalUpdatePlayerStockItem( item );\r\n\t\t\tupdatePlayerValue();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::onPlayerOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\tif( !g ) return;\r\n\tfor( auto& item : m_playerStock )\r\n\t{\r\n\t\tif( item.itemSID == itemSID && item.materialSIDorGender == materialSID && item.quality == quality )\r\n\t\t{\r\n\t\t\tif (count > 0)\r\n\t\t\t{\r\n\t\t\t\titem.reserved = qMax( 0, item.reserved - count );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\titem.reserved = 0;\r\n\t\t\t}\r\n\t\t\r\n\t\t\temit signalUpdatePlayerStockItem( item );\r\n\t\t\tupdatePlayerValue();\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid AggregatorWorkshop::updateTraderValue()\r\n{\r\n\tif( !g ) return;\r\n\tm_traderOfferValue = 0;\r\n\tfor( const auto& item : m_traderStock )\r\n\t{\r\n\t\tm_traderOfferValue += item.reserved * item.value;\r\n\t}\r\n\temit signalUpdateTraderValue( m_traderOfferValue );\r\n}\r\n\t\r\nvoid AggregatorWorkshop::updatePlayerValue()\r\n{\r\n\tif( !g ) return;\r\n\tm_playerOfferValue = 0;\r\n\tfor( const auto& item : m_playerStock )\r\n\t{\r\n\t\tm_playerOfferValue += item.reserved * item.value;\r\n\t}\r\n\temit signalUpdatePlayerValue( m_playerOfferValue );\r\n}\r\n\r\nvoid AggregatorWorkshop::onTrade( unsigned int workshopID )\r\n{\r\n\tif( !g ) return;\r\n\tauto workshop = g->wsm()->workshop( workshopID );\r\n\r\n\tif( workshop )\r\n\t{\r\n\t\tunsigned int traderID = workshop->assignedGnome();\r\n\r\n\t\tm_traderID = traderID;\r\n\r\n\t\tif( traderID )\r\n\t\t{\r\n\t\t\tGnomeTrader* gt = g->gm()->trader( traderID );\r\n\t\t\tif( gt )\r\n\t\t\t{\r\n\t\t\t\tif( m_playerOfferValue >= m_traderOfferValue )\r\n\t\t\t\t{\r\n\t\t\t\t\tQList<unsigned int> allItemsToSell;\r\n\t\t\t\t\tint currentValue = 0;\r\n\t\t\t\t\tfor( auto& item : m_playerStock )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tif ( item.reserved > 0 )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tQList<unsigned int> sellItems;\r\n\t\t\t\t\t\t\tif ( DB::select( \"HasQuality\", \"Items\", item.itemSID ).toBool() )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tsellItems = g->inv()->tradeInventory( item.itemSID, item.materialSIDorGender, item.quality );\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tsellItems = g->inv()->tradeInventory( item.itemSID, item.materialSIDorGender );\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tauto valuePerItem = g->inv()->getTradeValue( item.itemSID, item.materialSIDorGender, item.quality );\r\n\r\n\t\t\t\t\t\t\tif ( sellItems.size() < item.reserved )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\titem.reserved = sellItems.size();\r\n\t\t\t\t\t\t\t\temit signalUpdatePlayerStockItem( item );\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tfor ( int i = 0; i < item.reserved; ++i )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tallItemsToSell.append( sellItems[i] );\r\n\t\t\t\t\t\t\t\tcurrentValue += valuePerItem;\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\tif( currentValue >= m_traderOfferValue )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tfor( auto itemID : allItemsToSell )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tg->inv()->pickUpItem( itemID, 1 );\r\n\t\t\t\t\t\t\tg->inv()->destroyObject( itemID );\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tupdatePlayerStock( workshopID );\r\n\t\t\t\t\t\tupdatePlayerValue();\r\n\r\n\t\t\t\t\t\tauto& traderItems = gt->inventory();\r\n\t\t\t\t\t\tfor( auto& item : traderItems )\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tif( item.type == \"Animal\" )\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tfor( int i = 0; i < item.reserved; ++i )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tGender gender = item.gender == \"Male\" ? Gender::MALE : Gender::FEMALE;\r\n\r\n\t\t\t\t\t\t\t\t\tg->cm()->addCreature( CreatureType::ANIMAL, item.itemSID, workshop->outputPos(), gender, true, true );\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\telse\r\n\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\tfor( int i = 0; i < item.reserved; ++i )\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tg->inv()->createItem( workshop->outputPos(), item.itemSID, item.materialSID );\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\titem.amount = qMax( 0, item.amount - item.reserved );\r\n\t\t\t\t\t\t\titem.reserved = 0;\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tupdateTraderStock( traderItems );\r\n\r\n\t\t\t\t\t\temit signalTraderStock( m_traderStock );\r\n\r\n\t\t\t\t\t\tupdateTraderValue();\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"
  },
  {
    "path": "src/gui/aggregatorworkshop.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../game/workshop.h\"\r\n\r\n\r\n#include <QObject>\r\n\r\nclass Game;\r\nstruct TraderItem;\r\n\r\nstruct GuiWorkshopMaterial\r\n{\r\n\tQString sid;\r\n\tint amount;\r\n};\r\n\r\nstruct GuiWorkshopComponent\r\n{\r\n\tQPointer<Game> g;\r\n\tQString sid;\r\n\tint amount;\r\n\tbool requireSame;\r\n\r\n\tvoid updateMaterials( QVariantMap row );\r\n\r\n\t// the available materials with count for that item\r\n\tQList<GuiWorkshopMaterial> materials;\r\n};\r\n\r\nstruct GuiWorkshopProduct\r\n{\r\n\tQPointer<Game> g;\r\n\tQString sid;\r\n\r\n\tvoid updateComponents();\r\n\r\n\tQList<GuiWorkshopComponent> components;\r\n};\r\n\r\nstruct GuiWorkshopInfo\r\n{\r\n\tunsigned int workshopID = 0;\r\n\r\n\tQString name;\r\n\tint priority          = 1;\r\n\tint maxPriority       = 1;\r\n\tbool suspended        = false;\r\n\tbool autoCraftMissing = false;\r\n\tbool acceptGenerated  = false;\r\n\tbool linkStockpile    = false;\r\n\tbool butcherExcess    = false;\r\n\tbool butcherCorpses   = false;\r\n\tbool catchFish        = false;\r\n\tbool processFish      = false;\r\n\r\n\tQString gui;\r\n\r\n\tQList<GuiWorkshopProduct> products;\r\n\r\n\tQList<CraftJob> jobList;\r\n};\r\nQ_DECLARE_METATYPE( GuiWorkshopInfo )\r\n\r\n\r\nstruct GuiTradeItem\r\n{\r\n\tQString name;\r\n\tQString itemSID;\r\n\tQString materialSIDorGender;\r\n\tunsigned char quality = 0;\r\n\tint count = 0;\r\n\tint reserved = 0;\r\n\tint value = 0;\r\n};\r\nQ_DECLARE_METATYPE( GuiTradeItem )\r\n\r\n\r\n\r\nclass AggregatorWorkshop : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAggregatorWorkshop( QObject* parent = nullptr );\r\n\t~AggregatorWorkshop();\r\n\r\n\tvoid init( Game* game );\r\n\r\nprivate:\r\n    QPointer<Game> g;\r\n\r\n\tbool m_infoDirty    = false;\r\n\tbool m_contentDirty = false;\r\n\r\n\tGuiWorkshopInfo m_info;\r\n\r\n\tbool aggregate( unsigned int workshopID );\r\n\tbool updateCraftList( unsigned int workshopID );\r\n\r\n\tQList<GuiTradeItem> m_traderStock;\r\n\tQList<GuiTradeItem> m_playerStock;\r\n\r\n\tunsigned int m_traderID = 0;\r\n\r\n\tint m_traderOfferValue = 0;\r\n\tint m_playerOfferValue = 0;\r\n\r\n\tvoid updateTraderStock( unsigned int workshopID );\r\n\tvoid updatePlayerStock( unsigned int workshopID );\r\n\r\n\tvoid updateTraderStock( const QList<TraderItem>& source );\r\n\r\n\tvoid updateTraderValue();\r\n\tvoid updatePlayerValue();\r\n\r\npublic slots:\r\n\tvoid onOpenWorkshopInfoOnTile( unsigned int tileID );\r\n\tvoid onOpenWorkshopInfo( unsigned int workshopID );\r\n\tvoid onUpdateWorkshopInfo( unsigned int workshopID );\r\n\tvoid onUpdateWorkshopContent( unsigned int workshopID );\r\n\tvoid onUpdateAfterTick();\r\n\r\n\tvoid onSetBasicOptions( unsigned int workshopID, QString name, int priority, bool suspended, bool acceptGenerated, bool autoCraftMissing, bool connectStockpile );\r\n\tvoid onSetButcherOptions( unsigned int WorkshopID, bool butcherCorpses, bool butcherExcess );\r\n\tvoid onSetFisherOptions( unsigned int WorkshopID, bool catchFish, bool processFish );\r\n\tvoid onCraftItem( unsigned int workshopID, QString craftID, int mode, int number, QStringList mats );\r\n\tvoid onCraftJobCommand( unsigned int workshopID, unsigned int craftJobID, QString command );\r\n\tvoid onCraftJobParams( unsigned int workshopID, unsigned int craftJobID, int mode, int numToCraft, bool suspended, bool moveBack );\r\n\tvoid onCraftListChanged( unsigned int workshopID );\r\n\r\n\tvoid onRequestAllTradeItems( unsigned int workshopID );\r\n\r\n\tvoid onTraderStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid onTraderOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid onPlayerStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid onPlayerOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\r\n\tvoid onTrade( unsigned int workshopID );\r\n\r\n\tvoid onCloseWindow();\r\nsignals:\r\n\tvoid signalOpenWorkshopWindow( unsigned int workshopID );\r\n\tvoid signalUpdateInfo( const GuiWorkshopInfo& info );\r\n\tvoid signalUpdateContent( const GuiWorkshopInfo& info );\r\n\tvoid signalUpdateCraftList( const GuiWorkshopInfo& info );\r\n\r\n\tvoid signalTraderStock( const QList<GuiTradeItem>& items );\r\n\tvoid signalPlayerStock( const QList<GuiTradeItem>& items );\r\n\t\r\n\tvoid signalUpdateTraderStockItem( const GuiTradeItem& item );\r\n\tvoid signalUpdatePlayerStockItem( const GuiTradeItem& item );\r\n\r\n\tvoid signalUpdateTraderValue( int value );\r\n\tvoid signalUpdatePlayerValue( int value );\r\n};"
  },
  {
    "path": "src/gui/eventconnector.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"eventconnector.h\"\r\n\r\n#include \"aggregatoragri.h\"\r\n#include \"aggregatorcreatureinfo.h\"\r\n#include \"aggregatordebug.h\"\r\n#include \"aggregatorinventory.h\"\r\n#include \"aggregatorpopulation.h\"\r\n#include \"aggregatorrenderer.h\"\r\n#include \"aggregatorstockpile.h\"\r\n#include \"aggregatortileinfo.h\"\r\n#include \"aggregatorworkshop.h\"\r\n#include \"aggregatorneighbors.h\"\r\n#include \"aggregatormilitary.h\"\r\n#include \"aggregatorsettings.h\"\r\n#include \"aggregatorloadgame.h\"\r\n#include \"aggregatorselection.h\"\r\n#include \"aggregatorsound.h\"\r\n\r\n#include \"../base/db.h\"\r\n#include \"../base/config.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/selection.h\"\r\n#include \"../game/gamemanager.h\"\r\n#include \"../game/game.h\"\r\n#include \"../game/job.h\"\r\n#include \"../game/jobmanager.h\"\r\n#include \"../game/soundmanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n\r\n#include <QDebug>\r\n\r\nEventConnector::EventConnector( GameManager* parent ) :\r\n\tgm( parent ),\r\n\tQObject( parent )\r\n{\r\n\tm_tiAggregator           = new AggregatorTileInfo( this );\r\n\tm_spAggregator           = new AggregatorStockpile( this );\r\n\tm_wsAggregator           = new AggregatorWorkshop( this );\r\n\tm_acAggregator           = new AggregatorAgri( this );\r\n\tm_rAggregator            = new AggregatorRenderer( this );\r\n\tm_popAggregator          = new AggregatorPopulation( this );\r\n\tm_creatureInfoAggregator = new AggregatorCreatureInfo( this );\r\n\tm_debugAggregator        = new AggregatorDebug( this );\r\n\tm_neighborsAggregator    = new AggregatorNeighbors( this );\r\n\tm_militaryAggregator     = new AggregatorMilitary( this );\r\n\tm_settingsAggregator\t = new AggregatorSettings( this );\r\n\tm_inventoryAggregator    = new AggregatorInventory( this );\r\n\tm_loadGameAggregator\t = new AggregatorLoadGame( this );\r\n\tm_selectionAggregator\t = new AggregatorSelection( this );\r\n\tm_soundAggregator\t = new AggregatorSound( this );\r\n\r\n\tconnect( m_selectionAggregator, &AggregatorSelection::signalSelectTile, m_tiAggregator, &AggregatorTileInfo::onShowTileInfo );\r\n}\r\n\r\nvoid EventConnector::setGamePtr( Game* game )\r\n{\r\n\tg = game;\r\n}\r\n\r\nEventConnector::~EventConnector()\r\n{\r\n}\r\n\r\nvoid EventConnector::onExit()\r\n{\r\n\temit signalExit();\r\n}\r\n\r\nvoid EventConnector::onWindowSize( int w, int h )\r\n{\r\n\temit signalWindowSize( w, h );\r\n}\r\n\r\nvoid EventConnector::onTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus )\r\n{\r\n\temit signalTimeAndDate( minute, hour, day, season, year, sunStatus );\r\n}\r\n\r\nvoid EventConnector::onKingdomInfo( QString name, QString info1, QString info2, QString info3 )\r\n{\r\n\temit signalKingdomInfo( name, info1, info2, info3 );\r\n}\r\n\r\nvoid EventConnector::onHeartbeat( int value)\r\n{\r\n\temit signalHeartbeat( value );\r\n}\r\n\r\nvoid EventConnector::onHeartbeatResponse( int value)\r\n{\r\n\tgm->setHeartbeatResponse( value );\r\n}\r\n\r\nvoid EventConnector::onViewLevel( int level )\r\n{\r\n\temit signalViewLevel( level );\r\n}\r\n\r\nvoid EventConnector::onSetPause( bool paused )\r\n{\r\n\tgm->setPaused( paused );\r\n}\r\n\r\nvoid EventConnector::onSetGameSpeed( GameSpeed speed )\r\n{\r\n\tgm->setGameSpeed( speed );\r\n}\r\n\r\nvoid EventConnector::onKeyPress( int key )\r\n{\r\n\tswitch ( key )\r\n\t{\r\n\t\tcase Qt::Key_Escape:\r\n\t\t\temit signalKeyEsc();\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid EventConnector::onTogglePause()\r\n{\r\n\temit signalUpdatePause( !gm->paused() );\r\n}\r\n\r\nvoid EventConnector::onPropagateEscape()\r\n{\r\n\temit signalPropagateKeyEsc();\r\n}\r\n\r\nvoid EventConnector::onBuild()\r\n{\r\n\temit signalBuild();\r\n}\r\n\r\nvoid EventConnector::onTerrainCommand( unsigned int tileID, QString cmd )\r\n{\r\n\tif ( cmd == \"Mine\" )\r\n\t\tg->jm()->addJob( \"Mine\", Position( tileID ), 0 );\r\n\telse if ( cmd == \"Remove\" )\r\n\t\tg->jm()->addJob( \"RemoveFloor\", Position( tileID ), 0 );\r\n\telse if ( cmd == \"Fell\" )\r\n\t\tg->jm()->addJob( \"FellTree\", Position( tileID ), 0 );\r\n\telse if ( cmd == \"Destroy\" )\r\n\t\tg->jm()->addJob( \"RemovePlant\", Position( tileID ), 0 );\r\n\telse if ( cmd == \"Harvest\" )\r\n\t{\r\n\t\tif ( gm->game() && gm->game()->world() && gm->game()->world()->plants().contains( tileID ) )\r\n\t\t{\r\n\t\t\tPlant& plant = gm->game()->world()->plants()[tileID];\r\n\t\t\tif ( plant.isTree() )\r\n\t\t\t{\r\n\t\t\t\tg->jm()->addJob( \"HarvestTree\", Position( tileID ), 0 );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tg->jm()->addJob( \"Harvest\", Position( tileID ), 0 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid EventConnector::onManageCommand( unsigned int tileID )\r\n{\r\n\tif ( gm->game() && gm->game()->world() )\r\n\t{\r\n\t\tTile& tile = gm->game()->world()->getTile( tileID );\r\n\r\n\t\tTileFlag designation = tile.flags - ~( TileFlag::TF_WORKSHOP + TileFlag::TF_STOCKPILE + TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE + TileFlag::TF_ROOM );\r\n\t\tswitch ( designation )\r\n\t\t{\r\n\t\t\tcase TileFlag::TF_WORKSHOP:\r\n\t\t\t\tm_wsAggregator->onOpenWorkshopInfoOnTile( tileID );\r\n\t\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_STOCKPILE:\r\n\t\t\t{\r\n\t\t\t\tm_spAggregator->onOpenStockpileInfoOnTile( tileID );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_GROVE:\r\n\t\t\tcase TileFlag::TF_FARM:\r\n\t\t\tcase TileFlag::TF_PASTURE:\r\n\t\t\t{\r\n\t\t\t\tm_acAggregator->onOpen( designation, tileID );\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_ROOM:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid EventConnector::onSetRenderOptions( bool designations, bool jobs, bool walls, bool axles )\r\n{\r\n\t\r\n\tGlobal::wallsLowered = walls;\r\n\tGlobal::showDesignations = designations;\r\n\tGlobal::showJobs = jobs;\r\n\tGlobal::showAxles = axles;\r\n\t\r\n\t\r\n}\r\n\r\nvoid EventConnector::onUpdateRenderOptions()\r\n{\r\n\temit signalUpdateRenderOptions( Global::showDesignations, Global::showJobs, Global::wallsLowered, Global::showAxles );\r\n}\r\n\r\nvoid EventConnector::onPlayEffect( QVariantMap effect)\r\n{\r\n\temit signalPlayEffect( effect);\r\n}\r\n\r\nvoid EventConnector::onCameraPosition( float x, float y, float z, int r, float scale )\r\n{\r\n\temit signalCameraPosition( x, y, z, r, scale );\r\n}\r\n\r\nvoid EventConnector::emitStartGame()\r\n{\r\n\temit startGame();\r\n}\r\n\t\r\nvoid EventConnector::emitStopGame()\r\n{\r\n\temit stopGame();\r\n}\r\n\r\nvoid EventConnector::emitInitView()\r\n{\r\n\temit signalInitView();\r\n}\r\n\r\nvoid EventConnector::emitInMenu( bool value )\r\n{\r\n\temit signalInMenu( value );\r\n}\r\n\t\r\nvoid EventConnector::onStartNewGame()\r\n{\r\n\tgm->startNewGame();\r\n}\r\n\r\nvoid EventConnector::onContinueLastGame()\r\n{\r\n\tgm->continueLastGame();\r\n}\r\n\r\nvoid EventConnector::onLoadGame( QString folder )\r\n{\r\n\tgm->loadGame( folder );\r\n}\r\n\r\nvoid EventConnector::onSaveGame()\r\n{\r\n\tgm->saveGame();\r\n}\r\n\r\nvoid EventConnector::onSetShowMainMenu( bool value )\r\n{\r\n\tgm->setShowMainMenu( value );\r\n}\r\n\r\nvoid EventConnector::onEndGame()\r\n{\r\n\tgm->endCurrentGame();\r\n}\r\n\r\nvoid EventConnector::sendResume()\r\n{\r\n\temit signalResume();\r\n}\r\n\t\r\nvoid EventConnector::sendLoadGameDone( bool value )\r\n{\r\n\temit signalLoadGameDone( value );\r\n}\r\n\r\nvoid EventConnector::emitPause( bool paused )\r\n{\r\n\temit signalUpdatePause( paused );\r\n}\r\n\t\r\nvoid EventConnector::emitGameSpeed( GameSpeed speed )\r\n{\r\n\temit signalUpdateGameSpeed( speed );\r\n}\r\n\r\nvoid EventConnector::onSetSelectionAction( QString action )\r\n{\r\n\tGlobal::sel->setAction( action );\r\n}\r\n\t\r\nvoid EventConnector::onSetSelectionItem( QString item )\r\n{\r\n\tGlobal::sel->setItemID( item );\r\n}\r\n\r\nvoid EventConnector::onSetSelectionMaterials( QStringList mats )\r\n{\r\n\tGlobal::sel->setMaterials( mats );\r\n}\r\n\r\nvoid EventConnector::onCmdBuild( BuildItemType type, QString param, QString item, QStringList mats )\r\n{\r\n\tswitch ( type )\r\n\t{\r\n\t\tcase BuildItemType::Workshop:\r\n\t\t{\r\n\t\t\tGlobal::sel->setAction( \"BuildWorkshop\" );\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase BuildItemType::Terrain:\r\n\t\t{\r\n\t\t\tQString type = DB::select( \"Type\", \"Constructions\", item ).toString();\r\n\t\t\t\r\n\t\t\tif( !param.isEmpty() )\r\n\t\t\t{\r\n\t\t\t\tif( param == \"FillHole\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::sel->setAction( param );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::sel->setAction( param + type );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif( type == \"Stairs\" && item == \"Scaffold\" )\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::sel->setAction( \"BuildScaffold\" );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::sel->setAction( \"Build\" + type );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t\tcase BuildItemType::Item:\r\n\t\t{\r\n\t\t\tGlobal::sel->setAction( \"BuildItem\" );\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\tGlobal::sel->setMaterials( mats );\r\n\tGlobal::sel->setItemID( item );\r\n\r\n\temit signalBuild();\r\n}\r\n\r\nvoid EventConnector::onEvent( unsigned int id, QString title, QString msg, bool pause, bool yesno )\r\n{\r\n\temit signalEvent( id, title, msg, pause, yesno );\r\n}\r\n\r\nvoid EventConnector::onAnswer( unsigned int id, bool answer )\r\n{\r\n\tg->em()->onAnswer( id, answer );\r\n}\r\n\r\nGame* EventConnector::game()\r\n{\r\n\treturn g;\r\n}"
  },
  {
    "path": "src/gui/eventconnector.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QObject>\r\n\r\nclass GameManager;\r\n\r\nclass AggregatorTileInfo;     \r\nclass AggregatorStockpile;    \r\nclass AggregatorWorkshop;     \r\nclass AggregatorAgri;         \r\nclass AggregatorRenderer;\r\nclass AggregatorPopulation;\r\nclass AggregatorCreatureInfo;\r\nclass AggregatorDebug;\r\nclass AggregatorNeighbors;\r\nclass AggregatorMilitary;   \r\nclass AggregatorSettings;     \r\nclass AggregatorInventory;    \r\nclass AggregatorLoadGame;     \r\nclass AggregatorSelection;\r\nclass AggregatorSound;\r\n\r\n\r\nclass Game;\r\n\r\nclass EventConnector : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\t// Private Constructor\r\n\tEventConnector( GameManager* parent );\r\n\t~EventConnector();\r\n\r\n\tvoid setGamePtr( Game* game );\r\n\r\n\tAggregatorTileInfo* aggregatorTileInfo()\r\n\t{\r\n\t\treturn m_tiAggregator;\r\n\t}\r\n\tAggregatorStockpile* aggregatorStockpile()\r\n\t{\r\n\t\treturn m_spAggregator;\r\n\t}\r\n\tAggregatorWorkshop* aggregatorWorkshop()\r\n\t{\r\n\t\treturn m_wsAggregator;\r\n\t}\r\n\tAggregatorAgri* aggregatorAgri()\r\n\t{\r\n\t\treturn m_acAggregator;\r\n\t}\r\n\tAggregatorRenderer* aggregatorRenderer()\r\n\t{\r\n\t\treturn m_rAggregator;\r\n\t}\r\n\tAggregatorPopulation* aggregatorPopulation()\r\n\t{\r\n\t\treturn m_popAggregator;\r\n\t}\r\n\tAggregatorCreatureInfo* aggregatorCreatureInfo()\r\n\t{\r\n\t\treturn m_creatureInfoAggregator;\r\n\t}\r\n\tAggregatorDebug* aggregatorDebug()\r\n\t{\r\n\t\treturn m_debugAggregator;\r\n\t}\r\n\tAggregatorNeighbors* aggregatorNeighbors()\r\n\t{\r\n\t\treturn m_neighborsAggregator;\r\n\t}\r\n\tAggregatorMilitary* aggregatorMilitary()\r\n\t{\r\n\t\treturn m_militaryAggregator;\r\n\t}\r\n\tAggregatorSettings* aggregatorSettings()\r\n\t{\r\n\t\treturn m_settingsAggregator;\r\n\t}\r\n\tAggregatorInventory* aggregatorInventory()\r\n\t{\r\n\t\treturn m_inventoryAggregator;\r\n\t}\r\n\tAggregatorLoadGame* aggregatorLoadGame()\r\n\t{\r\n\t\treturn m_loadGameAggregator;\r\n\t}\r\n\tAggregatorSelection* aggregatorSelection()\r\n\t{\r\n\t\treturn m_selectionAggregator;\r\n\t}\r\n\tAggregatorSound* aggregatorSound()\r\n\t{\r\n\t\treturn m_soundAggregator;\r\n\t}\r\n\r\n\tvoid emitStartGame();\r\n\tvoid emitStopGame();\r\n\tvoid emitInitView();\r\n\tvoid emitInMenu( bool value );\r\n\r\n\tvoid emitPause( bool paused );\r\n\tvoid emitGameSpeed( GameSpeed speed );\r\n\r\n\tvoid sendResume();\r\n\tvoid sendLoadGameDone( bool value );\r\n\r\n\tGame* game();\r\nprivate:\r\n\tGameManager* gm = nullptr;\r\n\tQPointer<Game> g;\r\n\t\r\n\r\n\tAggregatorTileInfo* m_tiAggregator = nullptr;\r\n\tAggregatorStockpile* m_spAggregator = nullptr;\r\n\tAggregatorWorkshop* m_wsAggregator = nullptr;\r\n\tAggregatorAgri* m_acAggregator = nullptr;\r\n\tAggregatorRenderer* m_rAggregator = nullptr;\r\n\tAggregatorPopulation* m_popAggregator = nullptr;\r\n\tAggregatorCreatureInfo* m_creatureInfoAggregator = nullptr;\r\n\tAggregatorDebug* m_debugAggregator = nullptr;\r\n\tAggregatorNeighbors* m_neighborsAggregator = nullptr;\r\n\tAggregatorMilitary* m_militaryAggregator = nullptr;\r\n\tAggregatorSettings* m_settingsAggregator = nullptr;\r\n\tAggregatorInventory* m_inventoryAggregator = nullptr;\r\n\tAggregatorLoadGame* m_loadGameAggregator = nullptr;\r\n\tAggregatorSelection* m_selectionAggregator = nullptr;\r\n\tAggregatorSound* m_soundAggregator = nullptr;\r\n\r\npublic slots:\r\n\tvoid onExit();\r\n\tvoid onWindowSize( int w, int h );\r\n\r\n\tvoid onTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus );\r\n\tvoid onKingdomInfo( QString name, QString info1, QString info2, QString info3 );\r\n\tvoid onViewLevel( int level );\r\n\t\r\n\tvoid onHeartbeat( int value);\r\n\tvoid onHeartbeatResponse( int value);\r\n\r\n\tvoid onSetPause( bool paused );\r\n\tvoid onSetGameSpeed( GameSpeed speed );\r\n\r\n\tvoid onKeyPress( int key );\r\n\tvoid onTogglePause();\r\n\tvoid onPropagateEscape();\r\n\r\n\tvoid onBuild();\r\n\r\n\tvoid onTerrainCommand( unsigned int tileID, QString cmd );\r\n\tvoid onManageCommand( unsigned int tileID );\r\n\r\n\tvoid onSetRenderOptions( bool designations, bool jobs, bool walls, bool axles );\r\n\tvoid onUpdateRenderOptions();\r\n\r\n\tvoid onStartNewGame();\r\n\tvoid onContinueLastGame();\r\n\tvoid onLoadGame( QString folder );\r\n\tvoid onSaveGame();\r\n\tvoid onSetShowMainMenu( bool value );\r\n\tvoid onEndGame();\r\n\r\n\tvoid onSetSelectionAction( QString action );\r\n\tvoid onSetSelectionItem( QString item );\r\n\tvoid onSetSelectionMaterials( QStringList mats );\r\n\r\n\tvoid onCmdBuild( BuildItemType type, QString param, QString item, QStringList mats );\r\n\r\n\tvoid onAnswer( unsigned int id, bool answer );\r\n\tvoid onEvent( unsigned int id, QString title, QString msg, bool pause, bool yesno );\r\n\t\r\n\tvoid onPlayEffect( QVariantMap effect);\r\n\tvoid onCameraPosition( float x, float y, float z, int r, float scale );\r\n\r\nsignals:\r\n\tvoid signalExit();\r\n\tvoid signalWindowSize( int w, int h );\r\n\tvoid signalTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus );\r\n\tvoid signalKingdomInfo( QString name, QString info1, QString info2, QString info3 );\r\n\tvoid signalViewLevel( int level );\r\n\tvoid signalUpdatePause( bool paused );\r\n\tvoid signalUpdateGameSpeed( GameSpeed speed );\r\n\tvoid signalKeyEsc();\r\n\tvoid signalPropagateKeyEsc();\r\n\tvoid signalBuild();\r\n\tvoid signalUpdateRenderOptions( bool designation, bool jobs, bool walls, bool axles );\r\n\r\n\tvoid startGame();\r\n\tvoid stopGame();\r\n\tvoid signalInitView();\r\n\tvoid signalInMenu( bool value );\r\n\tvoid signalResume();\r\n\tvoid signalLoadGameDone( bool value );\r\n\r\n\tvoid signalEvent( unsigned int id, QString title, QString msg, bool pause, bool yesno );\r\n\t\r\n\tvoid signalHeartbeat( int value );\r\n\tvoid signalPlayEffect( QVariantMap effect );\r\n\t\r\n\tvoid signalCameraPosition( float x, float y, float z, int r, float scale );\r\n};\r\n"
  },
  {
    "path": "src/gui/keybindings.cpp",
    "content": "#include \"keybindings.h\"\r\n\r\n#include \"../base/io.h\"\r\n\r\n#include <QDebug>\r\n#include <QFile>\r\n#include <QDir>\r\n#include <QStandardPaths>\r\n#include <QJsonArray>\r\n#include <QJsonDocument>\r\n\r\nKeyBindings::KeyBindings(QObject *parent)\r\n\t: QObject(parent)\r\n{\r\n\tm_stringToCommand.insert( \"WorldScrollLeft\",     WorldScrollLeft );\r\n\tm_stringToCommand.insert( \"WorldScrollRight\",    WorldScrollRight );\r\n\tm_stringToCommand.insert( \"WorldScrollUp\",       WorldScrollUp );\r\n\tm_stringToCommand.insert( \"WorldScrollDown\",     WorldScrollDown );\r\n\tm_stringToCommand.insert( \"OpenBugReportWindow\", OpenBugReportWindow );\r\n\tm_stringToCommand.insert( \"OpenLogWindow\",       OpenLogWindow );\r\n\tm_stringToCommand.insert( \"OpenDebugWindow\",     OpenDebugWindow );\r\n\tm_stringToCommand.insert( \"PrintDebug\",          PrintDebug );\r\n\tm_stringToCommand.insert( \"ToggleDebugOverlay\",  ToggleDebugOverlay );\r\n\tm_stringToCommand.insert( \"ToggleDebugMode\",     ToggleDebugMode );\r\n\tm_stringToCommand.insert( \"ToggleFullScreen\",    ToggleFullScreen );\r\n\tm_stringToCommand.insert( \"OpenGnomeList\",       OpenGnomeList );\r\n\tm_stringToCommand.insert( \"ToggleWalls\",         ToggleWalls );\r\n\tm_stringToCommand.insert( \"ToggleOverlay\",       ToggleOverlay );\r\n\tm_stringToCommand.insert( \"ToggleAxles\",         ToggleAxles );\r\n\tm_stringToCommand.insert( \"ReloadShaders\",       ReloadShaders );\r\n\tm_stringToCommand.insert( \"ReloadCSS\",\t\t\t ReloadCSS );\r\n\tm_stringToCommand.insert( \"OpenLastActionWindow\",OpenLastActionWindow );\r\n\tm_stringToCommand.insert( \"TogglePause\",         TogglePause );\r\n\tm_stringToCommand.insert( \"RotateSelection\",     RotateSelection );\r\n\tm_stringToCommand.insert( \"RotateWorldCW\",       RotateWorldCW );\r\n\tm_stringToCommand.insert( \"RotateWorldCCW\",      RotateWorldCCW );\r\n\tm_stringToCommand.insert( \"ZMinus\",              ZMinus );\r\n\tm_stringToCommand.insert( \"ZPlus\",               ZPlus );\r\n\tm_stringToCommand.insert( \"ZoomIn\",              ZoomIn );\r\n\tm_stringToCommand.insert( \"ZoomOut\",             ZoomOut );\r\n\tm_stringToCommand.insert( \"MenuButtonKey1\",      MenuButtonKey1 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey2\",      MenuButtonKey2 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey3\",      MenuButtonKey3 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey4\",      MenuButtonKey4 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey5\",      MenuButtonKey5 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey6\",      MenuButtonKey6 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey7\",      MenuButtonKey7 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey8\",      MenuButtonKey8 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey9\",      MenuButtonKey9 );\r\n\tm_stringToCommand.insert( \"MenuButtonKey0\",      MenuButtonKey0 );\r\n\r\n\tm_stringToCommand.insert( \"Mine\",\t\t\t\t\t\t\t\tActionMine );\r\n\tm_stringToCommand.insert( \"DigHole\",                        \tActionDigHole );\r\n\tm_stringToCommand.insert( \"ExplorativeMine\",                \tActionExplorativeMine );\r\n\tm_stringToCommand.insert( \"RemoveRamp\",                     \tActionRemoveRamp );\r\n\tm_stringToCommand.insert( \"RemoveFloor\",                    \tActionRemoveFloor );\r\n\tm_stringToCommand.insert( \"RemovePlant\",                    \tActionRemovePlant );\r\n\tm_stringToCommand.insert( \"MineStairsUp\",                   \tActionMineStairsUp );\r\n\tm_stringToCommand.insert( \"DigStairsDown\",                  \tActionDigStairsDown );\r\n\tm_stringToCommand.insert( \"DigRampDown\",                    \tActionDigRampDown );\r\n\tm_stringToCommand.insert( \"CreateRoom\",                     \tActionCreateRoom );\r\n\tm_stringToCommand.insert( \"CreateStockpile\",                \tActionCreateStockpile );\r\n\tm_stringToCommand.insert( \"CreateGrove\",                    \tActionCreateGrove );\r\n\tm_stringToCommand.insert( \"CreateFarm\",                     \tActionCreateFarm );\r\n\tm_stringToCommand.insert( \"CreatePasture\",                  \tActionCreatePasture );\r\n\tm_stringToCommand.insert( \"CreateNoPass\",                   \tActionCreateNoPass );\r\n\tm_stringToCommand.insert( \"BuildWall\",                      \tActionBuildWall );\r\n\tm_stringToCommand.insert( \"ReplaceWall\",                    \tActionReplaceWall );\r\n\tm_stringToCommand.insert( \"BuildWallFloor\",                 \tActionBuildWallFloor );\r\n\tm_stringToCommand.insert( \"BuildFancyWall\",                 \tActionBuildFancyWall );\r\n\tm_stringToCommand.insert( \"BuildFloor\",                     \tActionBuildFloor );\r\n\tm_stringToCommand.insert( \"ReplaceFloor\",                   \tActionReplaceFloor );\r\n\tm_stringToCommand.insert( \"BuildFancyFloor\",                \tActionBuildFancyFloor );\r\n\tm_stringToCommand.insert( \"BuildScaffold\",                  \tActionBuildScaffold );\r\n\tm_stringToCommand.insert( \"BuildFence\",                     \tActionBuildFence );\r\n\tm_stringToCommand.insert( \"BuildWorkshop\",                  \tActionBuildWorkshop );\r\n\tm_stringToCommand.insert( \"BuildStairs\",                    \tActionBuildStairs );\r\n\tm_stringToCommand.insert( \"BuildRamp\",                      \tActionBuildRamp );\r\n\tm_stringToCommand.insert( \"BuildRampCorner\",                \tActionBuildRampCorner );\r\n\tm_stringToCommand.insert( \"CutClipping\",                    \tActionCutClipping );\r\n\tm_stringToCommand.insert( \"BuildItem\",                      \tActionBuildItem );\r\n\tm_stringToCommand.insert( \"PlantTree\",                      \tActionPlantTree );\r\n\tm_stringToCommand.insert( \"FellTree\",                       \tActionFellTree );\r\n\tm_stringToCommand.insert( \"Forage\",                         \tActionForage );\r\n\tm_stringToCommand.insert( \"HarvestTree\",                    \tActionHarvestTree );\r\n\tm_stringToCommand.insert( \"RemoveDesignation\",              \tActionRemoveDesignation );\r\n\tm_stringToCommand.insert( \"Deconstruct\",                    \tActionDeconstruct );\r\n\tm_stringToCommand.insert( \"CancelJob\",                      \tActionCancelJob );\r\n\tm_stringToCommand.insert( \"RaisePrio\",                      \tActionRaisePrio );\r\n\tm_stringToCommand.insert( \"LowerPrio\",                      \tActionLowerPrio );\r\n\tm_stringToCommand.insert( \"MagicNatureSpeedGrowth\",         \tActionMagicNatureSpeedGrowth );\r\n\tm_stringToCommand.insert( \"MagicGeomancyRevealOre\",         \tActionMagicGeomancyRevealOre );\r\n\r\n\tm_stringToCommand.insert( \"ToggleRenderCreatures\",         \t\tToggleRenderCreatures );\r\n\r\n\tm_stringToCommand.insert( \"QuickSave\",         \t\t\t\t\tQuickSave );\r\n\tm_stringToCommand.insert( \"QuickLoad\",         \t\t\t\t\tQuickLoad );\r\n\r\n}\r\n\r\nKeyBindings::~KeyBindings()\r\n{\r\n}\r\n\r\nvoid KeyBindings::update()\r\n{\r\n\tQString folder = IO::getDataFolder() + \"/settings/\";\r\n\tQJsonDocument jd;\r\n\tIO::loadFile( folder + \"keybindings.json\", jd );\r\n\tqDebug() << \"Load key bindings...\";\r\n\tauto groupList = jd.toVariant().toList();\r\n\t\r\n\tfor( auto groupElement : groupList )\r\n\t{\r\n\t\tauto eleMap = groupElement.toMap();\r\n\t\tfor( auto vKey : eleMap.value( \"Keys\" ).toList() )\r\n\t\t{\r\n\t\t\tauto kmap = vKey.toMap();\r\n\t\t\tQString cmd = kmap.value( \"Command\" ).toString();\r\n\t\t\tQVariantMap km1 = kmap.value( \"Key1\" ).toMap();\r\n\t\t\tQString keyCode = km1.value( \"Key\" ).toString() + km1.value( \"Ctrl\" ).toString() + km1.value( \"Alt\" ).toString() + km1.value( \"Shift\" ).toString();\r\n\t\t\tm_keyCodeToCmd.insert( keyCode, m_stringToCommand.value( cmd) );\r\n\t\t\tQVariantMap km2 = kmap.value( \"Key2\" ).toMap();\r\n\t\t\tkeyCode = km2.value( \"Key\" ).toString() + km2.value( \"Ctrl\" ).toString() + km2.value( \"Alt\" ).toString() + km2.value( \"Shift\" ).toString();\r\n\t\t\tm_keyCodeToCmd.insert( keyCode, m_stringToCommand.value( cmd) );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nUserKeyboardAction KeyBindings::getCommand( QKeyEvent* event )\r\n{\r\n\tbool ctrl = event->modifiers() & Qt::CTRL;\r\n\tbool alt = event->modifiers() & Qt::ALT;\r\n\tbool shift = event->modifiers() & Qt::SHIFT;\r\n\r\n\tQString keyCode = QKeySequence( event->key() ).toString();\r\n\tkeyCode += ctrl ? \"true\" : \"false\";\r\n\tkeyCode += alt ? \"true\" : \"false\";\r\n\tkeyCode += shift ? \"true\" : \"false\";\r\n\tif( m_keyCodeToCmd.contains( keyCode ) )\r\n\t{\r\n\t\treturn m_keyCodeToCmd.value( keyCode );\r\n\t}\r\n\treturn NoAction;\r\n}\r\n\r\nQString KeyBindings::getStringForCommand( UserKeyboardAction cmd )\r\n{\r\n\tfor( auto key : m_stringToCommand.keys() )\r\n\t{\r\n\t\tif( m_stringToCommand[key] == cmd )\r\n\t\t{\r\n\t\t\treturn key;\r\n\t\t}\r\n\t}\r\n\treturn \"\";\r\n}"
  },
  {
    "path": "src/gui/keybindings.h",
    "content": "#pragma once\r\n\r\n#include <QKeyEvent>\r\n#include <QObject>\r\n#include <QHash>\r\n\r\nenum UserKeyboardAction : unsigned int {\r\n\tNoAction,\r\n\tWorldScrollLeft,\r\n\tWorldScrollRight,\r\n\tWorldScrollUp,\r\n\tWorldScrollDown,\r\n\tRotateWorldCW,\r\n\tRotateWorldCCW,\r\n\tZMinus,\r\n\tZPlus,\r\n\tZoomIn,\r\n\tZoomOut,\r\n\r\n\t\r\n\tToggleFullScreen,\r\n\tOpenGnomeList,\r\n\tToggleWalls,\r\n\tToggleOverlay,\r\n\tOpenLastActionWindow,\r\n\tTogglePause,\r\n\tRotateSelection,\r\n\tToggleAxles,\r\n\t\r\n\tMenuButtonKey1,\r\n\tMenuButtonKey2,\r\n\tMenuButtonKey3,\r\n\tMenuButtonKey4,\r\n\tMenuButtonKey5,\r\n\tMenuButtonKey6,\r\n\tMenuButtonKey7,\r\n\tMenuButtonKey8,\r\n\tMenuButtonKey9,\r\n\tMenuButtonKey0,\r\n\t\r\n\tOpenBugReportWindow,\r\n\tOpenLogWindow,\r\n\tOpenDebugWindow,\r\n\tPrintDebug,\r\n\tToggleDebugOverlay,\r\n\tToggleDebugMode,\r\n\tReloadShaders,\r\n\tReloadCSS,\r\n\r\n\tQuickSave,\r\n\tQuickLoad,\r\n\r\n\tActionMine,\r\n\tActionDigHole,\r\n\tActionExplorativeMine,\r\n\tActionRemoveRamp,\r\n\tActionRemoveFloor,\r\n\tActionRemovePlant,\r\n\tActionMineStairsUp,\r\n\tActionDigStairsDown,\r\n\tActionDigRampDown,\r\n\tActionCreateRoom,\r\n\tActionCreateStockpile,\r\n\tActionCreateGrove,\r\n\tActionCreateFarm,\r\n\tActionCreatePasture,\r\n\tActionCreateNoPass,\r\n\tActionBuildWall,\r\n\tActionReplaceWall,\r\n\tActionBuildWallFloor,\r\n\tActionBuildFancyWall,\r\n\tActionBuildFloor,\r\n\tActionReplaceFloor,\r\n\tActionBuildFancyFloor,\r\n\tActionBuildScaffold,\r\n\tActionBuildFence,\r\n\tActionBuildWorkshop,\r\n\tActionBuildStairs,\r\n\tActionBuildRamp,\r\n\tActionBuildRampCorner,\r\n\tActionCutClipping,\r\n\tActionBuildItem,\r\n\tActionPlantTree,\r\n\tActionFellTree,\r\n\tActionForage,\r\n\tActionHarvestTree,\r\n\tActionRemoveDesignation,\r\n\tActionDeconstruct,\r\n\tActionCancelJob,\r\n\tActionRaisePrio,\r\n\tActionLowerPrio,\r\n\tActionMagicNatureSpeedGrowth,\r\n\tActionMagicGeomancyRevealOre,\r\n\r\n\tToggleRenderCreatures\r\n\t\r\n\r\n};\r\n\r\n\r\nclass KeyBindings : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tKeyBindings(QObject *parent = 0);\r\n\t~KeyBindings();\r\n\r\n\tvoid update();\r\n\tUserKeyboardAction getCommand( QKeyEvent* event );\r\n\r\n\tQString getStringForCommand( UserKeyboardAction cmd );\r\n\r\nprivate:\r\n\tQHash<QString, UserKeyboardAction>m_stringToCommand;\r\n\tQHash<QString, UserKeyboardAction>m_keyCodeToCmd;\r\n};\r\n"
  },
  {
    "path": "src/gui/license.h.in",
    "content": "#pragma once\n// DO NOT ADD YOUR LICENSE MANUALLY IN THIS FILE\n// READ THE DOCUMENTATION ON HOW TO CONFIGURE CMAKE\n\n// Noesis license information\n// A trial license for development purposes can be acquired free of charge at https://www.noesisengine.com/trial/\nstatic const char licenseName[] = \"@NOESIS_LICENSE_NAME@\";\nstatic const char licenseKey[]  = \"@NOESIS_LICENSE_KEY@\";\n\nstatic_assert( sizeof( licenseName ) > 1 && sizeof( licenseKey ) > 1, \"Please provide a working Noesis license or Noesis will stop working after a few minutes\" );\n"
  },
  {
    "path": "src/gui/mainwindow.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"mainwindow.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/io.h\"\r\n#include \"../gui/eventconnector.h\"\r\n#include \"../gui/aggregatorselection.h\"\r\n\r\n#include \"license.h\"\r\n#include \"mainwindowrenderer.h\"\r\n#include \"xaml/GameGui.xaml.h\"\r\n#include \"xaml/GameModel.h\"\r\n#include \"xaml/IngamePage.xaml.h\"\r\n#include \"xaml/LoadGameModel.h\"\r\n#include \"xaml/LoadGamePage.xaml.h\"\r\n#include \"xaml/Main.xaml.h\"\r\n#include \"xaml/MainMenu.xaml.h\"\r\n#include \"xaml/MainPage.xaml.h\"\r\n#include \"xaml/NewGameModel.h\"\r\n#include \"xaml/NewGamePage.xaml.h\"\r\n#include \"xaml/Population.xaml.h\"\r\n#include \"xaml/PopulationModel.h\"\r\n#include \"xaml/SettingsModel.h\"\r\n#include \"xaml/SettingsPage.xaml.h\"\r\n#include \"xaml/StockpileModel.h\"\r\n#include \"xaml/TileInfo.xaml.h\"\r\n#include \"xaml/TileInfoModel.h\"\r\n#include \"xaml/ViewModel.h\"\r\n#include \"xaml/WaitPage.xaml.h\"\r\n#include \"xaml/agriculture.xaml.h\"\r\n#include \"xaml/agriculturemodel.h\"\r\n#include \"xaml/creatureinfo.xaml.h\"\r\n#include \"xaml/creatureinfomodel.h\"\r\n#include \"xaml/debug.xaml.h\"\r\n#include \"xaml/debugmodel.h\"\r\n#include \"xaml/inventory.xaml.h\"\r\n#include \"xaml/inventorymodel.h\"\r\n#include \"xaml/selection.xaml.h\"\r\n#include \"xaml/selectionmodel.h\"\r\n\r\n\r\n#include \"xaml/military.xaml.h\"\r\n#include \"xaml/militarymodel.h\"\r\n#include \"xaml/neighbors.xaml.h\"\r\n#include \"xaml/neighborsmodel.h\"\r\n#include \"xaml/stockpilegui.xaml.h\"\r\n#include \"xaml/workshopgui.xaml.h\"\r\n#include \"xaml/workshopmodel.h\"\r\n\r\n#include \"xaml/converters.h\"\r\n\r\n#include <NsApp/Launcher.h>\r\n#include <NsApp/LocalFontProvider.h>\r\n#include <NsApp/LocalTextureProvider.h>\r\n#include <NsApp/LocalXamlProvider.h>\r\n#include <NsCore/EnumConverter.h>\r\n#include <NsCore/RegisterComponent.h>\r\n#include <NsGui/Grid.h>\r\n#include <NsGui/IRenderer.h>\r\n#include <NsGui/IntegrationAPI.h>\r\n#include <NsRender/GLFactory.h>\r\n\r\n#include <QDebug>\r\n#include <QKeyEvent>\r\n#include <QMouseEvent>\r\n#include <QTimer>\r\n\r\n#include <string>\r\n\r\nstatic MainWindow* instance;\r\n\r\nstatic QSet<QString> m_noesisMessages;\r\n\r\nMainWindow::MainWindow( QWidget* parent ) :\r\n\tQOpenGLWindow()\r\n{\r\n\tqDebug() << \"Create main window.\";\r\n\tconnect( Global::eventConnector, &EventConnector::signalExit, this, &MainWindow::onExit );\r\n\tconnect( this, &MainWindow::signalWindowSize, Global::eventConnector, &EventConnector::onWindowSize );\r\n\tconnect( this, &MainWindow::signalViewLevel, Global::eventConnector, &EventConnector::onViewLevel );\r\n\tconnect( this, &MainWindow::signalKeyPress, Global::eventConnector, &EventConnector::onKeyPress );\r\n\tconnect( this, &MainWindow::signalTogglePause, Global::eventConnector, &EventConnector::onTogglePause );\r\n\tconnect( this, &MainWindow::signalUpdateRenderOptions, Global::eventConnector, &EventConnector::onUpdateRenderOptions );\r\n\t\t\r\n\tconnect( this, &MainWindow::signalMouse, Global::eventConnector->aggregatorSelection(), &AggregatorSelection::onMouse, Qt::QueuedConnection );\r\n\tconnect( this, &MainWindow::signalLeftClick, Global::eventConnector->aggregatorSelection(), &AggregatorSelection::onLeftClick, Qt::QueuedConnection );\r\n\tconnect( this, &MainWindow::signalRightClick, Global::eventConnector->aggregatorSelection(), &AggregatorSelection::onRightClick, Qt::QueuedConnection );\r\n\tconnect( this, &MainWindow::signalRotateSelection, Global::eventConnector->aggregatorSelection(), &AggregatorSelection::onRotateSelection, Qt::QueuedConnection );\r\n\tconnect( this, &MainWindow::signalRenderParams, Global::eventConnector->aggregatorSelection(), &AggregatorSelection::onRenderParams, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorDebug(), &AggregatorDebug::signalSetWindowSize, this, &MainWindow::onSetWindowSize, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorSettings(), &AggregatorSettings::signalFullScreen, this, &MainWindow::onFullScreen, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector, &EventConnector::signalInitView, this, &MainWindow::onInitViewAfterLoad, Qt::QueuedConnection );\r\n\r\n\tinstance = this;\r\n}\r\n\r\nMainWindow::~MainWindow()\r\n{\r\n\tqDebug() << \"MainWindow destructor\";\r\n\r\n\tif( !m_isFullScreen )\r\n\t{\r\n\t\tGlobal::cfg->set( \"WindowWidth\", this->width() );\r\n\t\tGlobal::cfg->set( \"WindowHeight\", this->height() );\r\n\t\tGlobal::cfg->set( \"WindowPosX\", this->position().x() );\r\n\t\tGlobal::cfg->set( \"WindowPosY\", this->position().y() );\r\n\t}\r\n\t\r\n\tIO::saveConfig();\r\n\tinstance = nullptr;\r\n}\r\n\r\nMainWindow& MainWindow::getInstance()\r\n{\r\n\treturn *instance;\r\n}\r\n\r\nvoid MainWindow::onExit()\r\n{\r\n\tthis->close();\r\n}\r\n\r\nvoid MainWindow::toggleFullScreen()\r\n{\r\n\tQOpenGLWindow* w = this;\r\n\tm_isFullScreen = !m_isFullScreen;\r\n\tif ( m_isFullScreen )\r\n\t{\r\n\t\tw->showFullScreen();\r\n\t\tGlobal::cfg->set( \"fullscreen\", true );\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Reset from fullscreen:\r\n\t\tw->showNormal();\r\n\t\tGlobal::cfg->set( \"fullscreen\", false );\r\n\t}\r\n\tm_renderer->onRenderParamsChanged();\r\n\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n}\r\n\r\nvoid MainWindow::onFullScreen( bool value )\r\n{\r\n\tQOpenGLWindow* w = this;\r\n\tm_isFullScreen = value;\r\n\tGlobal::cfg->set( \"fullscreen\", value );\r\n\tif ( value )\r\n\t{\r\n\t\tw->showFullScreen();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// Reset from fullscreen:\r\n\t\tw->showNormal();\r\n\t}\r\n\tm_renderer->onRenderParamsChanged();\r\n\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n}\r\n\r\nvoid MainWindow::keyPressEvent( QKeyEvent* event )\r\n{\r\n\tint qtKey = event->key();\r\n\tauto noesisKey = Global::keyConvert( (Qt::Key)qtKey );\r\n\t//qDebug() << \"keyPressEvent\" << event->key() << \" \" << event->text() << noesisKey;\r\n\r\n\tbool ret = false;\r\n\t\r\n\tif( qtKey != 32 )\r\n\t{\r\n\t\tret = m_view->KeyDown( noesisKey );\r\n\t}\r\n\r\n\tif ( event->key() > 31 && event->key() < 256 )\r\n\t{\r\n\t\tif ( event->text().size() == 1 )\r\n\t\t{\r\n\t\t\tQChar c = event->text().at( 0 );\r\n\t\t\tret |= m_view->Char( c.unicode() );\r\n\t\t}\r\n\t}\r\n\t\r\n\tif ( ret )\r\n\t{\r\n\t\tidleRenderTick();\r\n\t}\r\n\r\n\tif ( !ret )\r\n\t{\r\n\t\tswitch ( event->key() )\r\n\t\t{\r\n\t\t\tcase Qt::Key_H:\r\n\t\t\t\tGlobal::wallsLowered = !Global::wallsLowered;\r\n\t\t\t\temit signalUpdateRenderOptions();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_K:\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_O:\r\n\t\t\t\tif ( event->modifiers() & Qt::ControlModifier )\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::debugMode = !Global::debugMode;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::showDesignations = !Global::showDesignations;\r\n\t\t\t\t\temit signalUpdateRenderOptions();\r\n\t\t\t\t}\r\n\t\t\t\tm_renderer->onRenderParamsChanged();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_F:\r\n\t\t\t\t//toggleFullScreen();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_R:\r\n\t\t\t\tif ( event->modifiers() & Qt::ControlModifier )\r\n\t\t\t\t{\r\n\t\t\t\t\tGlobal::debugOpenGL = !Global::debugOpenGL;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\temit signalRotateSelection();\r\n\t\t\t\t\tredraw();\r\n\t\t\t\t}\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_Comma:\r\n\t\t\t\tm_renderer->rotate( 1 );\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_Period:\r\n\t\t\t\tm_renderer->rotate( -1 );\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_Escape:\r\n\t\t\t\temit signalKeyPress( event->key() );\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_Space:\r\n\t\t\t\temit signalTogglePause();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_W:\r\n\t\t\t\tkeyboardMove();\r\n\t\t\t\tm_keyboardMove += KeyboardMove::Up;\r\n\t\t\t\tredraw();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_S:\r\n\t\t\t\tkeyboardMove();\r\n\t\t\t\tm_keyboardMove += KeyboardMove::Down;\r\n\t\t\t\tredraw();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_A:\r\n\t\t\t\tkeyboardMove();\r\n\t\t\t\tm_keyboardMove += KeyboardMove::Left;\r\n\t\t\t\tredraw();\r\n\t\t\t\tbreak;\r\n\t\t\tcase Qt::Key_D:\r\n\t\t\t\tkeyboardMove();\r\n\t\t\t\tm_keyboardMove += KeyboardMove::Right;\r\n\t\t\t\tredraw();\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\t\temit signalMouse( m_mouseX, m_mouseY, event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );\r\n\t}\r\n}\r\n\r\nvoid MainWindow::keyReleaseEvent( QKeyEvent* event )\r\n{\r\n\tauto noesisKey = Global::keyConvert( (Qt::Key)event->key() );\r\n\t//qDebug() << \"keyReleaseEvent\" << event->key() << \" \" << event->text() << noesisKey;\r\n\tif ( m_view->KeyUp( noesisKey ) )\r\n\t{\r\n\t\tidleRenderTick();\r\n\t}\r\n\r\n\tswitch ( event->key() )\r\n\t{\r\n\t\tcase Qt::Key_W:\r\n\t\t\tkeyboardMove();\r\n\t\t\tm_keyboardMove -= KeyboardMove::Up;\r\n\t\t\tredraw();\r\n\t\t\tbreak;\r\n\t\tcase Qt::Key_S:\r\n\t\t\tkeyboardMove();\r\n\t\t\tm_keyboardMove -= KeyboardMove::Down;\r\n\t\t\tredraw();\r\n\t\t\tbreak;\r\n\t\tcase Qt::Key_A:\r\n\t\t\tkeyboardMove();\r\n\t\t\tm_keyboardMove -= KeyboardMove::Left;\r\n\t\t\tredraw();\r\n\t\t\tbreak;\r\n\t\tcase Qt::Key_D:\r\n\t\t\tkeyboardMove();\r\n\t\t\tm_keyboardMove -= KeyboardMove::Right;\r\n\t\t\tredraw();\r\n\t\t\tbreak;\r\n\t}\r\n\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\temit signalMouse( m_mouseX, m_mouseY, event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );\r\n}\r\n\r\nbool MainWindow::isOverGui( int x, int y )\r\n{\r\n\tauto root     = Noesis::VisualTreeHelper::GetRoot( m_view->GetContent() );\r\n\tauto mousePos = Noesis::Point( x, y );\r\n\tauto hit      = Noesis::VisualTreeHelper::HitTest( root, mousePos );\r\n\r\n\treturn hit.visualHit;\r\n}\r\n\r\nvoid MainWindow::keyboardMove()\r\n{\r\n\tint x = 0;\r\n\tint y = 0;\r\n\tif( (bool)( m_keyboardMove & KeyboardMove::Up ) ) y -= 1;\r\n\tif( (bool)( m_keyboardMove & KeyboardMove::Down ) ) y += 1;\r\n\tif( (bool)( m_keyboardMove & KeyboardMove::Left ) ) x -= 1;\r\n\tif( (bool)( m_keyboardMove & KeyboardMove::Right ) ) x += 1;\r\n\r\n\t// Elapsed time in second\r\n\tconst float elapsedTime = m_keyboardMovementTimer.nsecsElapsed() * 0.000000001f;\r\n\tm_keyboardMovementTimer.restart();\r\n\r\n\tif( m_renderer && (x || y) )\r\n\t{\r\n\t\tconst float keyboardMoveSpeed = (Global::cfg->get( \"keyboardMoveSpeed\" ).toFloat() + 50.f) * 4.f;\r\n\r\n\t\tfloat moveX = -x * keyboardMoveSpeed * elapsedTime;\r\n\t\tfloat moveY = -y * keyboardMoveSpeed * elapsedTime;\r\n\r\n\t\tif (x && y)\r\n\t\t{\r\n\t\t\tmoveX /= sqrt( 2 );\r\n\t\t\tmoveY /= sqrt( 2 );\r\n\t\t}\r\n\r\n\t\tm_renderer->move( moveX, moveY );\r\n\t\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\t}\r\n}\r\n\r\nvoid MainWindow::mouseMoveEvent( QMouseEvent* event )\r\n{\r\n\tauto gp = this->mapFromGlobal( event->globalPos() );\r\n\tif ( m_view )\r\n\t{\r\n\t\t// Mouse movement needs to be handled by both Qt and Noesis, to correctly handle ongoing mouse gestures\r\n\t\tif ( m_view->MouseMove( gp.x(), gp.y() ) )\r\n\t\t{\r\n\t\t\tidleRenderTick();\r\n\t\t}\r\n\r\n\t\tif ( event->buttons() & Qt::LeftButton && m_leftDown )\r\n\t\t{\r\n\t\t\tif ( ( abs( gp.x() - m_clickX ) > 5 || abs( gp.y() - m_clickY ) > 5 ) && !m_isMove )\r\n\t\t\t{\r\n\t\t\t\tm_isMove = true;\r\n\t\t\t\tm_moveX  = m_clickX;\r\n\t\t\t\tm_moveY  = m_clickY;\r\n\t\t\t}\r\n\r\n\t\t\tif ( m_isMove )\r\n\t\t\t{\r\n\t\t\t\tm_renderer->move( gp.x() - m_moveX, gp.y() - m_moveY );\r\n\r\n\t\t\t\tm_moveX = gp.x();\r\n\t\t\t\tm_moveY = gp.y();\r\n\t\t\t}\r\n\t\t\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\t//qDebug() << \"huhu\";\r\n\t\t}\r\n\t}\r\n\r\n\tm_mouseX  = gp.x();\r\n\tm_mouseY  = gp.y();\r\n\r\n\r\n\temit signalMouse( m_mouseX, m_mouseY, event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );\r\n\r\n\tredraw();\r\n}\r\n\r\nvoid MainWindow::onInitViewAfterLoad()\r\n{\r\n\tm_renderer->setScale( 1.0 );\r\n\tm_moveX = GameState::moveX;\r\n\tm_moveY = GameState::moveY;\r\n\tm_renderer->move( m_moveX, m_moveY );\r\n\t\r\n\tm_renderer->setScale( GameState::scale );\r\n\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n}\r\n\r\nvoid MainWindow::mousePressEvent( QMouseEvent* event )\r\n{\r\n\t//qDebug() << \"mousePressEvent\";\r\n\tauto gp = this->mapFromGlobal( event->globalPos() );\r\n\tif ( event->button() & Qt::LeftButton )\r\n\t{\r\n\t\tif ( m_view )\r\n\t\t{\r\n\t\t\tif ( isOverGui( gp.x(), gp.y() ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_view->MouseButtonDown( gp.x(), gp.y(), Noesis::MouseButton::MouseButton_Left ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tidleRenderTick();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_clickX   = gp.x();\r\n\t\t\t\tm_clickY   = gp.y();\r\n\t\t\t\tm_isMove   = false;\r\n\t\t\t\tm_leftDown = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if ( event->button() & Qt::RightButton )\r\n\t{\r\n\t\tif ( m_view )\r\n\t\t{\r\n\t\t\tif ( isOverGui( gp.x(), gp.y() ) )\r\n\t\t\t{\r\n\t\t\t\tif ( m_view->MouseButtonDown( gp.x(), gp.y(), Noesis::MouseButton::MouseButton_Right ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tidleRenderTick();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_rightDown = true;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MainWindow::mouseReleaseEvent( QMouseEvent* event )\r\n{\r\n\t//qDebug() << \"mouseReleaseEvent\";\r\n\tif ( event->button() & Qt::LeftButton )\r\n\t{\r\n\t\tif ( m_view )\r\n\t\t{\r\n\t\t\tauto gp = this->mapFromGlobal( event->globalPos() );\r\n\t\t\tif ( isOverGui( gp.x(), gp.y() ) || !m_leftDown )\r\n\t\t\t{\r\n\t\t\t\tif ( m_view->MouseButtonUp( gp.x(), gp.y(), Noesis::MouseButton::MouseButton_Left ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tidleRenderTick();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( !m_isMove && m_leftDown )\r\n\t\t\t\t{\r\n\t\t\t\t\temit signalMouse( m_mouseX, m_mouseY, event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );\r\n\t\t\t\t\temit signalLeftClick( event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );\r\n\t\t\t\t\tredraw();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tm_isMove   = false;\r\n\t\t\tm_leftDown = false;\r\n\t\t}\r\n\t}\r\n\telse if ( event->button() & Qt::RightButton )\r\n\t{\r\n\t\tif ( m_view )\r\n\t\t{\r\n\t\t\tauto gp = this->mapFromGlobal( event->globalPos() );\r\n\t\t\tif ( isOverGui( gp.x(), gp.y() ) || !m_rightDown )\r\n\t\t\t{\r\n\t\t\t\tif ( m_view->MouseButtonUp( gp.x(), gp.y(), Noesis::MouseButton::MouseButton_Right ) )\r\n\t\t\t\t{\r\n\t\t\t\t\tidleRenderTick();\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\temit signalMouse( m_mouseX, m_mouseY, event->modifiers() & Qt::ShiftModifier, event->modifiers() & Qt::ControlModifier );\r\n\t\t\t\temit signalRightClick();\r\n\t\t\t\tredraw();\r\n\t\t\t\tm_rightDown = false;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MainWindow::wheelEvent( QWheelEvent* event )\r\n{\r\n\tQWheelEvent* wEvent = event; //dynamic_cast<QWheelEvent*>( event );\r\n\tif ( m_view )\r\n\t{\r\n\t\tauto gp = this->mapFromGlobal( event->globalPos() );\r\n\t\tif ( isOverGui( gp.x(), gp.y() ) )\r\n\t\t{\r\n\t\t\tif ( m_view->MouseWheel( gp.x(), gp.y(), wEvent->delta() ) )\r\n\t\t\t{\r\n\t\t\t\tidleRenderTick();\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tif ( (bool)( wEvent->modifiers() & Qt::ControlModifier ) ^ Global::cfg->get( \"toggleMouseWheel\" ).toBool() ) \r\n\t\t\t{\r\n\t\t\t\t// Scale the view / do the zoom\r\n\t\t\t\tauto delta = wEvent->delta();\r\n\t\t\t\tm_renderer->scale( pow( 1.002, delta ) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tif ( wEvent->delta() > 0 )\r\n\t\t\t\t{\r\n\t\t\t\t\tkeyboardZPlus( event->modifiers() & Qt::ShiftModifier );\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tkeyboardZMinus( event->modifiers() & Qt::ShiftModifier );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\t}\r\n}\r\n\r\nvoid MainWindow::focusInEvent( QFocusEvent* e )\r\n{\r\n\tif ( m_view )\r\n\t{\r\n\t\tm_view->Activate();\r\n\t\tidleRenderTick();\r\n\t}\r\n}\r\n\r\nvoid MainWindow::focusOutEvent( QFocusEvent* e )\r\n{\r\n\tif ( m_view )\r\n\t{\r\n\t\tm_view->Deactivate();\r\n\t\tidleRenderTick();\r\n\t}\r\n}\r\n\r\nvoid MainWindow::keyboardZPlus( bool shift, bool ctrl )\r\n{\r\n\tint dimZ      = Global::dimZ - 1;\r\n\tGameState::viewLevel += 1;\r\n\tGameState::viewLevel = qMax( 0, qMin( dimZ, GameState::viewLevel ) );\r\n\r\n\tm_renderer->onRenderParamsChanged();\r\n\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\temit signalViewLevel( GameState::viewLevel );\r\n\r\n\temit signalMouse( m_mouseX, m_mouseY, shift, ctrl );\r\n\tredraw();\r\n}\r\n\r\nvoid MainWindow::keyboardZMinus( bool shift, bool ctrl )\r\n{\r\n\tint dimZ      = Global::dimZ - 1;\r\n\tGameState::viewLevel -= 1;\r\n\tGameState::viewLevel = qMax( 0, qMin( dimZ, GameState::viewLevel ) );\r\n\r\n\tm_renderer->onRenderParamsChanged();\r\n\temit signalViewLevel( GameState::viewLevel );\r\n\temit signalRenderParams( width(), height(), m_renderer->moveX(), m_renderer->moveY(), m_renderer->scale(), m_renderer->rotation() );\r\n\temit signalMouse( m_mouseX, m_mouseY, shift, ctrl );\r\n\tredraw();\r\n}\r\n\r\nvoid MainWindow::noesisInit()\r\n{\r\n\tqDebug() << \"noesisInit()\";\r\n\tNoesis::LogHandler logHandler = []( const char*, uint32_t, uint32_t level, const char*, const char* message ) {\r\n\t\t// [TRACE] [DEBUG] [INFO] [WARNING] [ERROR]\r\n\t\tconst char* prefixes[] = { \"T\", \"D\", \"I\", \"W\", \"E\" };\r\n\t\t//printf(\"[NOESIS/%s] %s\\n\", prefixes[level], message);\r\n\t\tif ( m_noesisMessages.contains( message ) )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tm_noesisMessages.insert( message );\r\n\r\n\t\tqDebug() << \"[NOESIS]\" << prefixes[level] << message;\r\n\t};\r\n\r\n\tNoesis::ErrorHandler errorHandler = []( const char* file, uint32_t line, const char* message, bool fatal ) {\r\n\t\tqDebug() << \"[NOESIS]\" << message << \" in \" << file << \":\" << line;\r\n\t\tif ( fatal )\r\n\t\t{\r\n\t\t\tabort();\r\n\t\t}\r\n\t};\r\n\r\n\tNoesis::GUI::SetLogHandler( logHandler );\r\n\tNoesis::GUI::SetErrorHandler( errorHandler );\r\n\tNoesis::GUI::DisableInspector();\r\n\r\n\t// Noesis initialization. This must be the first step before using any NoesisGUI functionality\r\n\tNoesis::GUI::Init( licenseName, licenseKey );\r\n\r\n\tinstallResourceProviders();\r\n\r\n\tregisterComponents();\r\n\r\n\tNoesis::Ptr<Noesis::FrameworkElement> xaml = Noesis::GUI::LoadXaml<Noesis::FrameworkElement>( \"Main.xaml\" );\r\n\r\n\t// View creation to render and interact with the user interface\r\n\t// We transfer the ownership to a global pointer instead of a Ptr<> because there is no way\r\n\t// in GLUT to do shutdown and we don't want the Ptr<> to be released at global time\r\n\tm_view = Noesis::GUI::CreateView( xaml ).GiveOwnership();\r\n\r\n\t//m_view->SetIsPPAAEnabled( true );\r\n\r\n\t// Renderer initialization with an OpenGL device\r\n\tm_view->GetRenderer()->Init( NoesisApp::GLFactory::CreateDevice( false ) );\r\n\r\n\tm_view->SetSize( this->width(), this->height() );\r\n\r\n\temit signalWindowSize( this->width(), this->height() );\r\n}\r\n\r\nbool MainWindow::noesisUpdate()\r\n{\r\n\t// Update view (layout, animations, ...)\r\n\tstatic std::chrono::system_clock::time_point appStart = std::chrono::system_clock::now();\r\n\r\n\tauto timeDiff = std::chrono::duration_cast<std::chrono::duration<double>>( std::chrono::system_clock::now() - appStart );\r\n\r\n\t// See if anything needs to be animated\r\n\tif ( m_view->Update( timeDiff.count() ) )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid MainWindow::idleRenderTick()\r\n{\r\n\t// Check for ongoing keyboard movement\r\n\tkeyboardMove();\r\n\r\n\t// Check if redraw is required\r\n\tif ( noesisUpdate() && !m_pendingUpdate )\r\n\t{\r\n\t\t// Trigger rendering\r\n\t\tm_pendingUpdate = true;\r\n\t\tupdate();\r\n\t}\r\n\telse\r\n\t{\r\n\t\t// check again later\r\n\t\tm_timer->start( 20 );\r\n\t}\r\n}\r\n\r\nvoid MainWindow::paintGL()\r\n{\r\n\t// Apply latest position\r\n\tkeyboardMove();\r\n\r\n\t// Get the GPU busy\r\n\tm_renderer->paintWorld();\r\n\r\n\t// Trigger noesis updates again, to avoid \"stuttering UI\"\r\n\tnoesisUpdate();\r\n\r\n\t// Offscreen rendering phase populates textures needed by the on-screen rendering\r\n\t// If necessary, actually update\r\n\tm_view->GetRenderer()->UpdateRenderTree();\r\n\r\n\t// If you are going to render here with your own engine you need to restore the GPU state\r\n\t// because noesis changes it. In this case only framebuffer and viewport need to be restored\r\n\tif ( m_view->GetRenderer()->RenderOffscreen() )\r\n\t{\r\n\t\t// Restore state managed by QOpenGLWindow\r\n\t\tmakeCurrent();\r\n\t\tcontext()->functions()->glViewport( 0, 0, this->width() * devicePixelRatioF(), this->height() * devicePixelRatioF() );\r\n\t}\r\n\r\n\t// Rendering is done in the active framebuffer\r\n\tm_view->GetRenderer()->Render();\r\n\r\n\tm_timer->start( 0 );\r\n\tm_pendingUpdate = false;\r\n}\r\n\r\nvoid MainWindow::resizeGL( int w, int h )\r\n{\r\n\tQOpenGLWindow::resizeGL( w, h );\r\n\r\n\tif( !m_isFullScreen )\r\n\t{\r\n\t\tGlobal::cfg->set( \"WindowWidth\", w );\r\n\t\tGlobal::cfg->set( \"WindowHeight\", h );\r\n\t}\r\n\r\n\tif ( m_view )\r\n\t{\r\n\t\tm_view->SetSize( this->width(), this->height() );\r\n\t}\r\n\tm_renderer->resize( this->width(), this->height() );\r\n\r\n\tcontext()->functions()->glViewport( 0, 0, this->width() * devicePixelRatioF(), this->height() * devicePixelRatioF() );\r\n\r\n\temit signalWindowSize( this->width(), this->height() );\r\n\r\n\tupdate();\r\n}\r\n\r\nvoid MainWindow::onSetWindowSize( int width, int height )\r\n{\r\n\tthis->resize( width, height );\r\n}\r\n\r\nvoid MainWindow::redraw()\r\n{\r\n\tif ( !m_pendingUpdate )\r\n\t{\r\n\t\t// Trigger rendering\r\n\t\tm_pendingUpdate = true;\r\n\t\tupdate();\r\n\t}\r\n}\r\n\r\nvoid MainWindow::initializeGL()\r\n{\r\n\tQOpenGLWindow::initializeGL();\r\n\r\n\tm_renderer = new MainWindowRenderer( this );\r\n\tm_renderer->initializeGL();\r\n\r\n\tnoesisInit();\r\n\tm_timer = new QTimer( this );\r\n\tconnect( m_timer, &QTimer::timeout, this, &MainWindow::idleRenderTick );\r\n\r\n\tupdate();\r\n}\r\n\r\nMainWindowRenderer* MainWindow::renderer()\r\n{\r\n\treturn m_renderer;\r\n}\r\n\r\nvoid MainWindow::installResourceProviders()\r\n{\r\n\tconst std::string contentPath = Global::cfg->get( \"dataPath\" ).toString().toStdString() + \"/xaml/\";\r\n\tNoesis::GUI::SetXamlProvider( Noesis::MakePtr<NoesisApp::LocalXamlProvider>( contentPath.c_str() ) );\r\n\tNoesis::GUI::SetTextureProvider( Noesis::MakePtr<NoesisApp::LocalTextureProvider>( contentPath.c_str() ) );\r\n\tNoesis::GUI::SetFontProvider( Noesis::MakePtr<NoesisApp::LocalFontProvider>( contentPath.c_str() ) );\r\n}\r\n\r\nvoid MainWindow::registerComponents()\r\n{\r\n\tNoesisApp::Launcher::RegisterAppComponents();\r\n\r\n\tNoesis::RegisterComponent<IngnomiaGUI::Main>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::ViewModel>();\r\n\r\n\tNoesis::RegisterComponent<IngnomiaGUI::MainMenu>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::MainPage>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::SettingsPage>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::SettingsModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::LoadGamePage>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::LoadGameModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::NewGamePage>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::NewGameModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::WaitPage>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::IngamePage>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::GameModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::TileInfo>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::TileInfoModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::StockpileGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::StockpileModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::WorkshopGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::WorkshopModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::Agriculture>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::AgricultureModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::PopulationWindow>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::PopulationModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::CreatureInfo>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::CreatureInfoModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::DebugGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::DebugModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::NeighborsGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::NeighborsModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::MilitaryGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::MilitaryModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::InventoryGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::InventoryModel>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::SelectionGui>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::SelectionModel>();\r\n\r\n\tNoesis::RegisterComponent<Noesis::EnumConverter<IngnomiaGUI::State>>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::ColorToBrushConverter>();\r\n\tNoesis::RegisterComponent<IngnomiaGUI::ColorToBrushConverterDark>();\r\n\r\n\tNoesis::RegisterComponent<IngnomiaGUI::GameGui>();\r\n}\r\n"
  },
  {
    "path": "src/gui/mainwindow.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../base/position.h\"\r\n#include \"../base/tile.h\"\r\n\r\n#include <NsGui/IView.h>\r\n\r\n#include <QElapsedTimer>\r\n#include <QOpenGLWindow>\r\n#include <QTimer>\r\n\r\nenum class KeyboardMove : unsigned char\r\n{\r\n\tNone  = 0,\r\n\tUp    = 0x01,\r\n\tDown  = 0x02,\r\n\tLeft  = 0x04,\r\n\tRight = 0x08\r\n};\r\n\r\ninline KeyboardMove operator+( KeyboardMove a, KeyboardMove b )\r\n{\r\n\treturn static_cast<KeyboardMove>( static_cast<unsigned char>( a ) | static_cast<unsigned char>( b ) );\r\n}\r\n\r\ninline KeyboardMove operator&( KeyboardMove a, KeyboardMove b )\r\n{\r\n\treturn static_cast<KeyboardMove>( static_cast<unsigned char>( a ) & static_cast<unsigned char>( b ) );\r\n}\r\n\r\ninline KeyboardMove operator-( KeyboardMove a )\r\n{\r\n\treturn static_cast<KeyboardMove>( ~static_cast<unsigned char>( a ) );\r\n}\r\n\r\ninline KeyboardMove& operator+=( KeyboardMove& a, KeyboardMove b )\r\n{\r\n\treturn a = a + b;\r\n}\r\n\r\ninline KeyboardMove& operator-=( KeyboardMove& a, KeyboardMove b )\r\n{\r\n\treturn a = a & -b;\r\n}\r\n\r\nstruct Position;\r\nclass QOpenGLTexture;\r\nclass MainWindowRenderer;\r\n\r\nclass MainWindow : public QOpenGLWindow\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tMainWindow( QWidget* parent = Q_NULLPTR );\r\n\t~MainWindow();\r\n\tstatic MainWindow& getInstance();\r\n\r\n\tbool noesisUpdate();\r\n\r\n\tMainWindowRenderer* renderer();\r\n\r\nprotected:\r\n\tvoid paintGL() override;\r\n\tvoid resizeGL( int w, int h ) override;\r\n\tvoid initializeGL() override;\r\n\r\n\tvoid keyPressEvent( QKeyEvent* event ) override;\r\n\tvoid keyReleaseEvent( QKeyEvent* event ) override;\r\n\tvoid mouseMoveEvent( QMouseEvent* event ) override;\r\n\tvoid mousePressEvent( QMouseEvent* event ) override;\r\n\tvoid mouseReleaseEvent( QMouseEvent* event ) override;\r\n\tvoid wheelEvent( QWheelEvent* event ) override;\r\n\tvoid focusInEvent( QFocusEvent* e ) override;\r\n\tvoid focusOutEvent( QFocusEvent* e ) override;\r\n\r\nprivate:\r\n\tvoid noesisInit();\r\n\r\n\tvoid keyboardZPlus( bool shift = false, bool ctrl = false );\r\n\tvoid keyboardZMinus( bool shift = false, bool ctrl = false );\r\n\tbool isOverGui( int x, int y );\r\n\r\n\tvoid installResourceProviders();\r\n\tvoid registerComponents();\r\n\r\n\tvoid toggleFullScreen();\r\n\tbool m_isFullScreen = false;\r\n\r\n\tvoid onExit();\r\n\r\n\tQTimer* m_timer = nullptr;\r\n\tQElapsedTimer m_keyboardMovementTimer;\r\n\r\n\tNoesis::IView* m_view          = nullptr;\r\n\tMainWindowRenderer* m_renderer = nullptr;\r\n\r\n\t// Global position of last mouse click\r\n\tint m_clickX = 0;\r\n\tint m_clickY = 0;\r\n\t// Local position of last mouse click\r\n\tint m_mouseX = 0;\r\n\tint m_mouseY = 0;\r\n\t// Global position of last mouse event during drag\r\n\tint m_moveX = 0;\r\n\tint m_moveY = 0;\r\n\r\n\tbool m_leftDown  = false;\r\n\tbool m_rightDown = false;\r\n\tbool m_isMove    = false;\r\n\r\n\tbool m_pendingUpdate = false;\r\n\r\n\tKeyboardMove m_keyboardMove = KeyboardMove::None;\r\n\r\npublic slots:\r\n\tvoid redraw();\r\n\tvoid idleRenderTick();\r\n\tvoid onFullScreen( bool value );\r\n\tvoid keyboardMove();\r\n\r\n\tvoid onSetWindowSize( int width, int height );\r\n\r\n\tvoid onInitViewAfterLoad();\r\n\r\nsignals:\r\n\tvoid signalWindowSize( int w, int h );\r\n\tvoid signalViewLevel( int level );\r\n\t\r\n\r\n\tvoid signalKeyPress( int key );\r\n\tvoid signalUpdateRenderOptions();\r\n\tvoid signalTogglePause();\r\n\r\n\tvoid signalRenderParams( int width, int height, int moveX, int moveY, float scale, int rotation );\r\n\tvoid signalRotateSelection();\r\n\tvoid signalMouse( int mouseX, int mouseY, bool shift, bool ctrl );\r\n\tvoid signalLeftClick( bool shift, bool ctrl );\r\n\tvoid signalRightClick();\r\n};\r\n"
  },
  {
    "path": "src/gui/mainwindowrenderer.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"mainwindowrenderer.h\"\r\n\r\n#include \"../game/game.h\" //TODO only temporary\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n#include \"../base/gamestate.h\"\r\n#include \"../base/global.h\"\r\n#include \"../base/util.h\"\r\n#include \"../base/vptr.h\"\r\n#include \"../game/gamemanager.h\"\r\n#include \"../game/plant.h\"\r\n#include \"../game/world.h\"\r\n#include \"../gfx/sprite.h\"\r\n#include \"../gfx/spritefactory.h\"\r\n#include \"eventconnector.h\"\r\n#include \"mainwindow.h\"\r\n#include \"aggregatorselection.h\"\r\n\r\n#include <QCoreApplication>\r\n#include <QDebug>\r\n#include <QFile>\r\n#include <QImage>\r\n#include <QMessageBox>\r\n#include <QOpenGLShaderProgram>\r\n#include <QOpenGLTexture>\r\n#include <QTimer>\r\n\r\nnamespace\r\n{\r\nclass DebugScope\r\n{\r\npublic:\r\n\tDebugScope() = delete;\r\n\tDebugScope( const char* c )\r\n\t{\r\n\t\tstatic GLuint counter    = 0;\r\n\t\tQOpenGLExtraFunctions* f = QOpenGLContext::currentContext()->extraFunctions();\r\n\t\tf->glPushDebugGroup( GL_DEBUG_SOURCE_APPLICATION, counter++, static_cast<GLsizei>( strlen( c ) ), c );\r\n\t}\r\n\t~DebugScope()\r\n\t{\r\n\t\tQOpenGLExtraFunctions* f = QOpenGLContext::currentContext()->extraFunctions();\r\n\t\tf->glPopDebugGroup();\r\n\t}\r\n};\r\n} // namespace\r\n\r\nMainWindowRenderer::MainWindowRenderer( MainWindow* parent ) :\r\n\tQObject( parent ),\r\n\tm_parent( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::signalWorldParametersChanged, this, &MainWindowRenderer::cleanupWorld );\r\n\r\n\tconnect( Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::signalTileUpdates, this, &MainWindowRenderer::onTileUpdates );\r\n\tconnect( Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::signalAxleData, this, &MainWindowRenderer::onAxelData );\r\n\tconnect( Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::signalThoughtBubbles, this, &MainWindowRenderer::onThoughtBubbles );\r\n\tconnect( Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::signalCenterCamera, this, &MainWindowRenderer::onCenterCameraPosition );\r\n\tconnect( Global::eventConnector, &EventConnector::signalInMenu, this, &MainWindowRenderer::onSetInMenu );\r\n\r\n\tconnect( Global::eventConnector->aggregatorSelection(), &AggregatorSelection::signalUpdateSelection, this, &MainWindowRenderer::onUpdateSelection, Qt::QueuedConnection );\r\n\r\n\t// Full polling of initial state on load\r\n\tconnect( this, &MainWindowRenderer::fullDataRequired, Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::onAllTileInfo );\r\n\tconnect( this, &MainWindowRenderer::fullDataRequired, Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::onThoughtBubbleUpdate );\r\n\tconnect( this, &MainWindowRenderer::fullDataRequired, Global::eventConnector->aggregatorRenderer(), &AggregatorRenderer::onAxleDataUpdate );\r\n\r\n\tconnect( this, &MainWindowRenderer::signalCameraPosition, Global::eventConnector, &EventConnector::onCameraPosition );\r\n\r\n\tqDebug() << \"initialize GL ...\";\r\n\tconnect( m_parent->context(), &QOpenGLContext::aboutToBeDestroyed, this, &MainWindowRenderer::cleanup );\r\n\tconnect( this, &MainWindowRenderer::redrawRequired, m_parent, &MainWindow::redraw );\r\n\r\n\tif ( !initializeOpenGLFunctions() )\r\n\t{\r\n\t\tqDebug() << \"failed to initialize OpenGL - make sure your graphics card and driver support OpenGL 4.3\";\r\n\t\tqCritical() << \"failed to initialize OpenGL functions core 4.3 - exiting\";\r\n\t\tQMessageBox msgBox;\r\n\t\tmsgBox.setText( \"Failed to initialize OpenGL - make sure your graphics card and driver support OpenGL 4.3\" );\r\n\t\tmsgBox.exec();\r\n\t\texit( 0 );\r\n\t}\r\n\r\n\tqDebug() << \"[OpenGL]\" << reinterpret_cast<char const*>( glGetString( GL_VENDOR ) );\r\n\tqDebug() << \"[OpenGL]\" << reinterpret_cast<char const*>( glGetString( GL_VERSION ) );\r\n\tqDebug() << \"[OpenGL]\" << reinterpret_cast<char const*>( glGetString( GL_RENDERER ) );\r\n\r\n\tqDebug() << m_parent->context()->format();\r\n\r\n\tQOpenGLExtraFunctions* f = QOpenGLContext::currentContext()->extraFunctions();\r\n\tGLDEBUGPROC logHandler   = []( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam ) -> void\r\n\t{\r\n\t\tstatic const std::unordered_map<GLenum, const char*> debugTypes = {\r\n\t\t\t{ GL_DEBUG_TYPE_ERROR, \"Error\" },\r\n\t\t\t{ GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, \"DeprecatedBehavior\" },\r\n\t\t\t{ GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, \"UndefinedBehavior\" },\r\n\t\t\t{ GL_DEBUG_TYPE_PORTABILITY, \"Portability\" },\r\n\t\t\t{ GL_DEBUG_TYPE_PERFORMANCE, \"Performance\" },\r\n\t\t\t{ GL_DEBUG_TYPE_MARKER, \"Marker\" },\r\n\t\t\t{ GL_DEBUG_TYPE_OTHER, \"Other\" },\r\n\t\t\t{ GL_DEBUG_TYPE_PUSH_GROUP, \"Push\" },\r\n\t\t\t{ GL_DEBUG_TYPE_POP_GROUP, \"Pop\" }\r\n\t\t};\r\n\t\tstatic const std::unordered_map<GLenum, const char*> severities = {\r\n\t\t\t{ GL_DEBUG_SEVERITY_LOW, \"low\" },\r\n\t\t\t{ GL_DEBUG_SEVERITY_MEDIUM, \"medium\" },\r\n\t\t\t{ GL_DEBUG_SEVERITY_HIGH, \"high\" },\r\n\t\t\t{ GL_DEBUG_SEVERITY_NOTIFICATION, \"notify\" },\r\n\t\t};\r\n\t\tif ( severity == GL_DEBUG_SEVERITY_NOTIFICATION && !Global::debugOpenGL )\r\n\t\t\treturn;\r\n\t\t// Only want to handle these from dedicated graphic debugger\r\n\t\tif ( type == GL_DEBUG_TYPE_PUSH_GROUP || type == GL_DEBUG_TYPE_POP_GROUP )\r\n\t\t\treturn;\r\n\t\tqDebug() << \"[OpenGL]\" << debugTypes.at( type ) << \" \" << severities.at(severity) << \":\" << message;\r\n\t};\r\n\tglEnable( GL_DEBUG_OUTPUT );\r\n\tf->glDebugMessageCallback( logHandler, nullptr );\r\n}\r\nMainWindowRenderer ::~MainWindowRenderer()\r\n{\r\n}\r\n\r\nvoid MainWindowRenderer::initializeGL()\r\n{\r\n\tfloat vertices[] = {\r\n\t\t// Wall layer\r\n\t\t0.f, .8f, 1.f, // top left\r\n\t\t0.f, .2f, 1.f, // bottom left\r\n\t\t1.f, .8f, 1.f, // top right\r\n\t\t1.f, .2f, 1.f, // bottom right\r\n\r\n\t\t// floor layer\r\n\t\t0.f, .5f, 0.f, // top left\r\n\t\t0.f, .2f, 0.f, // bottom left\r\n\t\t1.f, .5f, 0.f, // top right\r\n\t\t1.f, .2f, 0.f, // bottom right\r\n\t};\r\n\r\n\tconstexpr GLushort indices[] = {\r\n\t\t0, 1, 3, // Wall 1\r\n\t\t2, 0, 3, // Wall 2\r\n\t\t4, 5, 7, // Floor 1\r\n\t\t6, 4, 7, // Floor 2\r\n\t\t// Wall again for BTF rendering\r\n\t\t0, 1, 3, // Wall 1\r\n\t\t2, 0, 3, // Wall 2\r\n\t};\r\n\r\n\tif ( !initShaders() )\r\n\t{\r\n\t\t//qCritical() << \"failed to init shaders - exiting\";\r\n\t}\r\n\r\n\tm_vao.create();\r\n\tQOpenGLVertexArrayObject::Binder vaoBinder( &m_vao );\r\n\r\n\tglGenBuffers( 1, &m_vbo );\r\n\tglBindBuffer( GL_ARRAY_BUFFER, m_vbo );\r\n\tglBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );\r\n\r\n\tglVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof( float ), (void*)0 );\r\n\tglEnableVertexAttribArray( 0 );\r\n\r\n\tglGenBuffers( 1, &m_vibo );\r\n\tglBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_vibo );\r\n\tglBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW );\r\n\r\n\tupdateRenderParams();\r\n\r\n\tqDebug() << \"initialize GL - done\";\r\n}\r\n\r\nvoid MainWindowRenderer::reloadShaders()\r\n{\r\n\tm_reloadShaders = true;\r\n}\r\n\r\nvoid MainWindowRenderer::cleanup()\r\n{\r\n\tm_parent->makeCurrent();\r\n\tm_worldShader.reset();\r\n\tm_worldUpdateShader.reset();\r\n\tm_thoughtBubbleShader.reset();\r\n\tm_selectionShader.reset();\r\n\tm_axleShader.reset();\r\n\r\n\tglDeleteBuffers( 1, &m_vbo );\r\n\tglDeleteBuffers( 1, &m_vibo );\r\n\r\n\tm_parent->doneCurrent();\r\n\r\n\tm_reloadShaders = true;\r\n}\r\n\r\nvoid MainWindowRenderer::cleanupWorld()\r\n{\r\n\tm_parent->makeCurrent();\r\n\tglDeleteTextures( 32, m_textures );\r\n\tmemset( m_textures, 0, sizeof( m_textures ) );\r\n\tglDeleteBuffers( 1, &m_tileBo );\r\n\tm_tileBo = 0;\r\n\tglDeleteBuffers( 1, &m_tileUpdateBo );\r\n\tm_tileUpdateBo     = 0;\r\n\tm_texesInitialized = false;\r\n\r\n\tm_parent->doneCurrent();\r\n\r\n\tm_pendingUpdates.clear();\r\n\tm_selectionData.clear();\r\n\tm_thoughBubbles = ThoughtBubbleInfo();\r\n\tm_axleData      = AxleDataInfo();\r\n}\r\n\r\nvoid MainWindowRenderer::onTileUpdates( const TileDataUpdateInfo& updates )\r\n{\r\n\tm_pendingUpdates.push_back( updates.updates );\r\n\temit redrawRequired();\r\n}\r\n\r\nvoid MainWindowRenderer::onThoughtBubbles( const ThoughtBubbleInfo& bubbles )\r\n{\r\n\tm_thoughBubbles = bubbles;\r\n\temit redrawRequired();\r\n}\r\n\r\nvoid MainWindowRenderer::onAxelData( const AxleDataInfo& data )\r\n{\r\n\tm_axleData = data;\r\n\temit redrawRequired();\r\n}\r\n\r\nQString MainWindowRenderer::copyShaderToString( QString name )\r\n{\r\n\tQFile file( Global::cfg->get( \"dataPath\" ).toString() + \"/shaders/\" + name + \".glsl\" );\r\n\tfile.open( QIODevice::ReadOnly );\r\n\tQTextStream in( &file );\r\n\tQString code( \"\" );\r\n\twhile ( !in.atEnd() )\r\n\t{\r\n\t\tcode += in.readLine();\r\n\t\tcode += \"\\n\";\r\n\t}\r\n\r\n\treturn code;\r\n}\r\n\r\nQOpenGLShaderProgram* MainWindowRenderer::initShader( QString name )\r\n{\r\n\tQString vs = copyShaderToString( name + \"_v\" );\r\n\tQString fs = copyShaderToString( name + \"_f\" );\r\n\r\n\tQScopedPointer<QOpenGLShaderProgram> shader(new QOpenGLShaderProgram);\r\n\r\n\tbool ok = true;\r\n\tok &= shader->addShaderFromSourceCode( QOpenGLShader::Vertex, vs );\r\n\tok &= shader->addShaderFromSourceCode( QOpenGLShader::Fragment, fs );\r\n\tif ( !ok )\r\n\t{\r\n\t\tqCritical() << \"failed to add shader source code\" << name;\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tok &= shader->link();\r\n\r\n\tif ( !ok )\r\n\t{\r\n\t\tqCritical() << \"failed to link shader\" << name;\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tok &= shader->bind();\r\n\tif ( !ok )\r\n\t{\r\n\t\tqCritical() << \"failed to bind shader\" << name;\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tshader->release();\r\n\r\n\treturn shader.take();\r\n}\r\n\r\nQOpenGLShaderProgram* MainWindowRenderer::initComputeShader( QString name )\r\n{\r\n\tQString cs = copyShaderToString( name + \"_c\" );\r\n\r\n\tQScopedPointer<QOpenGLShaderProgram> shader( new QOpenGLShaderProgram );\r\n\r\n\tbool ok = true;\r\n\tok &= shader->addShaderFromSourceCode( QOpenGLShader::Compute, cs );\r\n\tif ( !ok )\r\n\t{\r\n\t\tqCritical() << \"failed to add shader source code\";\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tok &= shader->link();\r\n\r\n\tif ( !ok )\r\n\t{\r\n\t\tqCritical() << \"failed to link shader\";\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tok &= shader->bind();\r\n\tif ( !ok )\r\n\t{\r\n\t\tqCritical() << \"failed to bind shader\";\r\n\t\treturn nullptr;\r\n\t}\r\n\r\n\tshader->release();\r\n\r\n\treturn shader.take();\r\n}\r\n\r\nbool MainWindowRenderer::initShaders()\r\n{\r\n\tm_worldShader.reset(initShader( \"world\" ));\r\n\tm_worldUpdateShader.reset(initComputeShader( \"worldupdate\" ));\r\n\tm_thoughtBubbleShader.reset(initShader( \"thoughtbubble\" ));\r\n\tm_selectionShader.reset(initShader( \"selection\" ));\r\n\tm_axleShader.reset(initShader( \"axle\" ));\r\n\r\n\tif ( !m_worldShader || !m_worldUpdateShader || !m_thoughtBubbleShader || !m_selectionShader || !m_axleShader )\r\n\t{\r\n\t\t// Can't proceed, and need to know what happened!\r\n\t\tabort();\r\n\t\treturn false;\r\n\t}\r\n\r\n\tm_reloadShaders = false;\r\n\r\n\treturn true;\r\n}\r\n\r\nvoid MainWindowRenderer::createArrayTexture( int unit, int depth )\r\n{\r\n\t//GLint max_layers;\r\n\t//glGetIntegerv ( GL_MAX_ARRAY_TEXTURE_LAYERS, &max_layers );\r\n\r\n\tglActiveTexture( GL_TEXTURE0 + unit );\r\n\tglGenTextures( 1, &m_textures[unit] );\r\n\tglBindTexture( GL_TEXTURE_2D_ARRAY, m_textures[unit] );\r\n\tglTexStorage3D(\r\n\t\tGL_TEXTURE_2D_ARRAY,\r\n\t\t1,             // No mipmaps\r\n\t\tGL_RGBA8,      // Internal format\r\n\t\t32, 64,        // width,height\r\n\t\tdepth          // Number of layers\r\n\t);\r\n\tglTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST );\r\n\tglTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST );\r\n\tglTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0 );\r\n\tglTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );\r\n\tglTexParameteri( GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );\r\n}\r\n\r\nvoid MainWindowRenderer::uploadArrayTexture( int unit, int depth, const uint8_t* data )\r\n{\r\n\tglActiveTexture( GL_TEXTURE0 + unit );\r\n\tglTexSubImage3D(\r\n\t\tGL_TEXTURE_2D_ARRAY,\r\n\t\t0,                // Mipmap number\r\n\t\t0, 0, 0,          // xoffset, yoffset, zoffset\r\n\t\t32, 64, depth,    // width, height, depth\r\n\t\tGL_RGBA,          // format\r\n\t\tGL_UNSIGNED_BYTE, // type\r\n\t\tdata\r\n\t);\r\n}\r\n\r\nvoid MainWindowRenderer::initTextures()\r\n{\r\n\tGLint max_layers;\r\n\tglGetIntegerv( GL_MAX_ARRAY_TEXTURE_LAYERS, &max_layers );\r\n\r\n\tqDebug() << \"max array size: \" << max_layers;\r\n\tqDebug() << \"used \" << Global::eventConnector->game()->sf()->size() << \" sprites\";\r\n\r\n\tint maxArrayTextures = Global::cfg->get( \"MaxArrayTextures\" ).toInt();\r\n\r\n\tfor ( int i = 0; i < 32; ++i )\r\n\t{\r\n\t\tcreateArrayTexture( i, maxArrayTextures );\r\n\t}\r\n\r\n\tm_texesInitialized = true;\r\n}\r\n\r\nvoid MainWindowRenderer::initWorld()\r\n{\r\n\tQElapsedTimer timer;\r\n\ttimer.start();\r\n\r\n\tglGenBuffers( 1, &m_tileBo );\r\n\tglBindBuffer( GL_SHADER_STORAGE_BUFFER, m_tileBo );\r\n\tglBufferData( GL_SHADER_STORAGE_BUFFER, TD_SIZE * sizeof( unsigned int ) * Global::eventConnector->game()->w()->world().size(), nullptr, GL_DYNAMIC_DRAW );\r\n\tconst uint8_t zero = 0;\r\n\tglClearBufferData( GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, &zero );\r\n\tglBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 ); // unbind\r\n\r\n\tglBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, m_tileBo );\r\n\r\n\tglGenBuffers( 1, &m_tileUpdateBo );\r\n\r\n\tglBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, m_tileBo );\r\n\tglBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, m_tileUpdateBo );\r\n\r\n\tm_texesInitialized = true;\r\n\r\n\tm_rotation = 0;\r\n\r\n\temit fullDataRequired();\r\n}\r\n\r\nvoid MainWindowRenderer::updateRenderParams()\r\n{\r\n\tm_renderSize = qMin( Global::dimX, (int)( ( sqrt( m_width * m_width + m_height * m_height ) / 12 ) / m_scale ) );\r\n\r\n\tm_renderDepth = Global::cfg->get( \"renderDepth\" ).toInt();\r\n\r\n\tm_viewLevel = GameState::viewLevel;\r\n\r\n\tm_volume.min = { 0, 0, qMin( qMax( m_viewLevel - m_renderDepth, 0 ), Global::dimZ - 1 ) };\r\n\tm_volume.max = { Global::dimX - 1, Global::dimY - 1, qMin( m_viewLevel, Global::dimZ - 1 ) };\r\n\r\n\tm_lightMin = Global::cfg->get( \"lightMin\" ).toFloat();\r\n\tif ( m_lightMin < 0.01 )\r\n\t\tm_lightMin = 0.3f;\r\n\r\n\tm_debug   = Global::debugMode;\r\n\r\n\tm_projectionMatrix.setToIdentity();\r\n\tm_projectionMatrix.ortho( -m_width / 2, m_width / 2, -m_height / 2, m_height / 2, -( m_volume.max.x + m_volume.max.y + m_volume.max.z + 1 ), -m_volume.min.z );\r\n\tm_projectionMatrix.scale( m_scale, m_scale );\r\n\tm_projectionMatrix.translate( m_moveX, -m_moveY );\r\n\r\n\t/*\r\n\tQString msg = \"Move: \" + QString::number( m_moveX ) + \", \" + QString::number( m_moveY ) + \" z-Level: \" + QString::number( m_viewLevel ); \r\n\tqDebug() << msg;\r\n\t//emit sendOverlayMessage( 5, msg );\r\n\tmsg = \"Window size: \" + QString::number( m_width ) + \"x\" + QString::number( m_height ) + \" Scale \" + QString::number( m_scale ) + \" Rotation \" + QString::number( m_rotation );\r\n\tqDebug() << msg;\r\n\t//emit sendOverlayMessage( 4, msg );\r\n\t*/\r\n}\r\n\r\nvoid MainWindowRenderer::paintWorld()\r\n{\r\n\tDebugScope s( \"paint world\" );\r\n\tQElapsedTimer timer;\r\n\t//timer.start();\r\n\t{\r\n\t\tDebugScope s( \"clear\" );\r\n\t\tglEnable( GL_BLEND );\r\n\t\tglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );\r\n\t\tglEnable( GL_DEPTH_TEST );\r\n\t\tglDepthFunc( GL_LEQUAL );\r\n\t\tglDisable( GL_STENCIL_TEST );\r\n\t\tglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );\r\n\t\tglDisable( GL_SCISSOR_TEST );\r\n\r\n\t\tglDepthMask( true );\r\n\t\tglStencilMask( 0xFFFFFFFF );\r\n\t\tglClearStencil( 0 );\r\n\t\tglClearDepth( 1 );\r\n\t\tglClearColor( 0.0, 0.0, 0.0, 1.0 );\r\n\t\tglColorMask( true, true, true, true );\r\n\t\t//glClearDepth( 1 );\r\n\t\tglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );\r\n\r\n\t\tglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );\r\n\t}\r\n\r\n\tif ( m_inMenu )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_reloadShaders )\r\n\t{\r\n\t\tDebugScope s( \"init shaders\" );\r\n\t\tif ( !initShaders() )\r\n\t\t{\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n\r\n\tif ( !m_texesInitialized )\r\n\t{\r\n\t\tDebugScope s( \"init textures\" );\r\n\t\tinitWorld();\r\n\t\tinitTextures();\r\n\t\tupdateRenderParams();\r\n\t}\r\n\tupdateWorld();\r\n\r\n\t// Rebind correct textures to texture units\r\n\tfor ( auto unit = 0; unit < 32; ++unit )\r\n\t{\r\n\t\tglActiveTexture( GL_TEXTURE0 + unit );\r\n\t\tglBindTexture( GL_TEXTURE_2D_ARRAY, m_textures[unit] );\r\n\t}\r\n\r\n\ttimer.start();\r\n\tupdateTextures();\r\n\r\n\tglMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT );\r\n\r\n\tQString msg = \"render time: \" + QString::number( timer.elapsed() ) + \" ms\";\r\n\t//emit sendOverlayMessage( 1, msg );\r\n\r\n\t{\r\n\t\tglEnable( GL_BLEND );\r\n\t\tglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );\r\n\t\tglEnable( GL_DEPTH_TEST );\r\n\t\tglDepthFunc( GL_LEQUAL );\r\n\t\tglDisable( GL_STENCIL_TEST );\r\n\r\n\t\tglDepthMask( true );\r\n\t\tglStencilMask( 0xFFFFFFFF );\r\n\t\tglClearStencil( 0 );\r\n\t\tglClearDepth( 1 );\r\n\t\tglClearColor( 0.0, 0.0, 0.0, 1.0 );\r\n\t\tglColorMask( true, true, true, true );\r\n\t\t//glClearDepth( 1 );\r\n\t\tglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );\r\n\r\n\t\tQOpenGLVertexArrayObject::Binder vaoBinder( &m_vao );\r\n\r\n\t\tpaintTiles();\r\n\r\n\t\tpaintSelection();\r\n\r\n\t\tpaintThoughtBubbles();\r\n\r\n\t\tif ( Global::showAxles )\r\n\t\t{\r\n\t\t\tpaintAxles();\r\n\t\t}\r\n\t}\r\n\r\n\t//glFinish();\r\n\r\n\tbool pause = Global::cfg->get( \"Pause\" ).toBool();\r\n\r\n\tif ( pause != m_pause )\r\n\t{\r\n\t\tm_pause = pause;\r\n\t}\r\n}\r\n\r\nvoid MainWindowRenderer::onRenderParamsChanged()\r\n{\r\n\tupdateRenderParams();\r\n\temit redrawRequired();\r\n\temit signalCameraPosition(m_moveX, m_moveY, m_viewLevel, m_rotation, m_scale);\r\n\t\r\n}\r\n\r\nvoid MainWindowRenderer::setCommonUniforms( QOpenGLShaderProgram* shader )\r\n{\r\n\tauto indexTotal = shader->uniformLocation( \"uWorldSize\" );\r\n\tif ( indexTotal >= 0 )\r\n\t{\r\n\t\tglUniform3ui( indexTotal, Global::dimX, Global::dimY, Global::dimZ );\r\n\t}\r\n\tauto indexMin = shader->uniformLocation( \"uRenderMin\" );\r\n\tif ( indexMin >= 0 )\r\n\t{\r\n\t\tglUniform3ui( indexMin, m_volume.min.x, m_volume.min.y, m_volume.min.z );\r\n\t}\r\n\tauto indexMax = shader->uniformLocation( \"uRenderMax\" );\r\n\tif ( indexMax >= 0 )\r\n\t{\r\n\t\tglUniform3ui( indexMax, m_volume.max.x, m_volume.max.y, m_volume.max.z );\r\n\t}\r\n\tshader->setUniformValue( \"uTransform\", m_projectionMatrix );\r\n\tshader->setUniformValue( \"uWorldRotation\", (GLuint)m_rotation );\r\n\tshader->setUniformValue( \"uTickNumber\", (GLuint)GameState::tick );\r\n}\r\n\r\nvoid MainWindowRenderer::paintTiles()\r\n{\r\n\tDebugScope s( \"paint tiles\" );\r\n\r\n\tm_worldShader->bind();\r\n\tsetCommonUniforms( m_worldShader.get() );\r\n\r\n\tfor ( int i = 0; i < m_texesUsed; ++i )\r\n\t{\r\n\t\tauto texNum = \"uTexture[\" + QString::number( i ) + \"]\";\r\n\t\tm_worldShader->setUniformValue( texNum.toStdString().c_str(), i );\r\n\t}\r\n\r\n\t//glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );\r\n\tm_worldShader->setUniformValue( \"uOverlay\", Global::showDesignations );\r\n\tm_worldShader->setUniformValue( \"uShowJobs\", Global::showJobs );\r\n\tm_worldShader->setUniformValue( \"uDebug\", m_debug );\r\n\tm_worldShader->setUniformValue( \"uWallsLowered\", Global::wallsLowered );\r\n\r\n\tm_worldShader->setUniformValue( \"uUndiscoveredTex\", Global::undiscoveredUID * 4 );\r\n\tm_worldShader->setUniformValue( \"uWaterTex\", Global::waterSpriteUID * 4 );\r\n\r\n\tif ( GameState::daylight )\r\n\t{\r\n\t\tm_daylight = qMin( 1.0, m_daylight + 0.025 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_daylight = qMax( 0.0, m_daylight - 0.025 );\r\n\t}\r\n\tm_worldShader->setUniformValue( \"uDaylight\", m_daylight );\r\n\tm_worldShader->setUniformValue( \"uLightMin\", m_lightMin );\r\n\t//m_worldShader->setUniformValue( \"uDaylight\", 1.0f );\r\n\r\n\tauto volume   = m_volume.size();\r\n\tGLsizei tiles = volume.x * volume.y * volume.z;\r\n\r\n\t// First pass is pure front-to-back of opaque blocks, alpha doesn't even work\r\n\tglDisable( GL_BLEND );\r\n\tglDepthMask( true );\r\n\r\n\tm_worldShader->setUniformValue( \"uPaintFrontToBack\", true );\r\n\tglDrawElementsInstanced( GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, 0, tiles );\r\n\r\n\t//!TODO Transparency pass is too early, all the stuff rendered later is still missing\r\n\t// Second pass includes transparency\r\n\tm_worldShader->setUniformValue( \"uPaintFrontToBack\", false );\r\n\tglEnable( GL_BLEND );\r\n\tglDrawElementsInstanced( GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, (void*)( sizeof( GLushort ) * 6 ), tiles );\r\n\r\n\t// All done with depth writes, everything beyond is layered\r\n\tglDepthMask( false );\r\n\r\n\tm_worldShader->release();\r\n}\r\n\r\nvoid MainWindowRenderer::paintSelection()\r\n{\r\n\t// TODO this is a workaround until some transparency solution is implemented\r\n\tif( m_selectionNoDepthTest )\r\n\t{\r\n\t\tglDisable( GL_DEPTH_TEST );\r\n\t}\r\n\tDebugScope s( \"paint selection\" );\r\n\tm_selectionShader->bind();\r\n\tsetCommonUniforms( m_selectionShader.get() );\r\n\r\n\tfor ( int i = 0; i < m_texesUsed; ++i )\r\n\t{\r\n\t\tauto texNum = \"uTexture[\" + QString::number( i ) + \"]\";\r\n\t\tm_selectionShader->setUniformValue( texNum.toStdString().c_str(), i );\r\n\t}\r\n\r\n\tfor ( const auto& sd : m_selectionData )\r\n\t{\r\n\t\tGLint tile = m_axleShader->uniformLocation( \"tile\" );\r\n\t\tglUniform3ui( tile, sd.pos.x, sd.pos.y, sd.pos.z );\r\n\t\tm_selectionShader->setUniformValue( \"uSpriteID\", sd.spriteID );\r\n\t\tm_selectionShader->setUniformValue( \"uRotation\", sd.localRot );\r\n\t\tm_selectionShader->setUniformValue( \"uValid\", sd.valid );\r\n\r\n\t\tglDrawArraysInstancedBaseInstance( GL_TRIANGLE_STRIP, 0, 4, 1, 0 );\r\n\t}\r\n\r\n\tm_selectionShader->release();\r\n\tif( m_selectionNoDepthTest )\r\n\t{\r\n\t\tglEnable( GL_DEPTH_TEST );\r\n\t}\r\n}\r\n\r\nvoid MainWindowRenderer::paintThoughtBubbles()\r\n{\r\n\tDebugScope s( \"paint thoughts\" );\r\n\r\n\tm_thoughtBubbleShader->bind();\r\n\tsetCommonUniforms( m_thoughtBubbleShader.get() );\r\n\r\n\tm_thoughtBubbleShader->setUniformValue( \"uTexture0\", 0 );\r\n\r\n\tfor ( const auto& thoughtBubble : m_thoughBubbles.thoughtBubbles )\r\n\t{\r\n\t\tif ( thoughtBubble.pos.z <= m_viewLevel )\r\n\t\t{\r\n\t\t\tGLint tile = m_axleShader->uniformLocation( \"tile\" );\r\n\t\t\tglUniform3ui( tile, thoughtBubble.pos.x, thoughtBubble.pos.y, thoughtBubble.pos.z );\r\n\t\t\tm_thoughtBubbleShader->setUniformValue( \"uType\", thoughtBubble.sprite );\r\n\t\t\tglDrawArraysInstancedBaseInstance( GL_TRIANGLE_STRIP, 0, 4, 1, 0 );\r\n\t\t}\r\n\t}\r\n\r\n\tm_thoughtBubbleShader->release();\r\n}\r\n\r\nvoid MainWindowRenderer::paintAxles()\r\n{\r\n\tDebugScope s( \"paint axles\" );\r\n\r\n\tm_axleShader->bind();\r\n\tsetCommonUniforms( m_axleShader.get() );\r\n\tm_axleShader->setUniformValue( \"uTickNumber\", (unsigned int)GameState::tick );\r\n\r\n\tfor ( int i = 0; i < m_texesUsed; ++i )\r\n\t{\r\n\t\tauto texNum = \"uTexture[\" + QString::number( i ) + \"]\";\r\n\t\tm_axleShader->setUniformValue( texNum.toStdString().c_str(), i );\r\n\t}\r\n\r\n\tfor ( const auto& ad : m_axleData.data )\r\n\t{\r\n\t\tif ( !ad.isVertical && ad.pos.z <= m_viewLevel )\r\n\t\t{\r\n\t\t\tGLint tile = m_axleShader->uniformLocation( \"tile\" );\r\n\t\t\tglUniform3ui( tile, ad.pos.x, ad.pos.y, ad.pos.z );\r\n\t\t\tm_axleShader->setUniformValue( \"uSpriteID\", ad.spriteID );\r\n\t\t\tm_axleShader->setUniformValue( \"uRotation\", ad.localRot );\r\n\t\t\tm_axleShader->setUniformValue( \"uAnim\", ad.anim );\r\n\r\n\t\t\tglDrawArraysInstancedBaseInstance( GL_TRIANGLE_STRIP, 0, 4, 1, 0 );\r\n\t\t}\r\n\t}\r\n\r\n\tm_axleShader->release();\r\n}\r\n\r\nvoid MainWindowRenderer::resize( int w, int h )\r\n{\r\n\tm_width  = w;\r\n\tm_height = h;\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::rotate( int direction )\r\n{\r\n\tdirection  = qBound( -1, direction, 1 );\r\n\tm_rotation = ( 4 + m_rotation + direction ) % 4;\r\n\t\r\n\tif( direction == 1 )\r\n\t{\r\n\t\tupdatePositionAfterCWRotation( m_moveX, m_moveY );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tupdatePositionAfterCWRotation( m_moveX, m_moveY );\r\n\t\tupdatePositionAfterCWRotation( m_moveX, m_moveY );\r\n\t\tupdatePositionAfterCWRotation( m_moveX, m_moveY );\r\n\t}\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::move( float x, float y )\r\n{\r\n\tif ( !Global::dimX )\r\n\t\treturn;\r\n\r\n\tm_moveX += x / m_scale;\r\n\tm_moveY += y / m_scale;\r\n\r\n\tconst auto centerY = -Global::dimX * 8.f;\r\n\tconst auto centerX = 0;\r\n\r\n\tfloat oldX, oldY;\r\n\tdo\r\n\t{\r\n\t\toldX   = m_moveX;\r\n\t\toldY   = m_moveY;\r\n\t\tconst auto rangeY = Global::dimX * 8.f - abs( m_moveX - centerX ) / 2.f;\r\n\t\tconst auto rangeX = Global::dimX * 16.f - abs( m_moveY - centerY ) * 2.f;\r\n\t\tm_moveX           = qBound( centerX - rangeX, m_moveX, centerX + rangeX );\r\n\t\tm_moveY           = qBound( centerY - rangeY, m_moveY, centerY + rangeY );\r\n\t} while ( oldX != m_moveX || oldY != m_moveY );\r\n\r\n\tGameState::moveX = m_moveX;\r\n\tGameState::moveY = m_moveY;\r\n\t\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::scale( float factor )\r\n{\r\n\tm_scale *= factor;\r\n\tm_scale = qBound( 0.25f, m_scale, 15.f );\r\n\tGameState::scale = m_scale;\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::setScale( float scale )\r\n{\r\n\tm_scale = qBound( 0.25f, scale, 15.f );\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::setViewLevel( int level )\r\n{\r\n\tm_viewLevel = level;\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::updateWorld()\r\n{\r\n\tif ( !m_pendingUpdates.empty() )\r\n\t{\r\n\t\tDebugScope s( \"update world\" );\r\n\t\tfor ( const auto& update : m_pendingUpdates )\r\n\t\t{\r\n\t\t\tuploadTileData( update );\r\n\t\t}\r\n\t\tm_pendingUpdates.clear();\r\n\t}\r\n}\r\n\r\nvoid MainWindowRenderer::uploadTileData( const QVector<TileDataUpdate>& tileData )\r\n{\r\n\tglBindBuffer( GL_SHADER_STORAGE_BUFFER, m_tileUpdateBo );\r\n\tglBufferData( GL_SHADER_STORAGE_BUFFER, sizeof( TileDataUpdate ) * tileData.size(), tileData.data(), GL_STREAM_DRAW );\r\n\tglBindBuffer( GL_SHADER_STORAGE_BUFFER, 0 );\r\n\r\n\tm_worldUpdateShader->bind();\r\n\tm_worldUpdateShader->setUniformValue( \"uUpdateSize\", (GLint)tileData.size() );\r\n\tglDispatchCompute( ( tileData.size() + 63 ) / 64, 1, 1 );\r\n\tm_worldUpdateShader->release();\r\n}\r\n\r\nvoid MainWindowRenderer::updateTextures()\r\n{\r\n\tif ( Global::eventConnector->game()->sf()->textureAdded() || Global::eventConnector->game()->sf()->creatureTextureAdded() )\r\n\t{\r\n\t\tDebugScope s( \"update textures\" );\r\n\r\n\t\tm_texesUsed = Global::eventConnector->game()->sf()->texesUsed();\r\n\r\n\t\tint maxArrayTextures = Global::cfg->get( \"MaxArrayTextures\" ).toInt();\r\n\r\n\t\tfor ( int i = 0; i < m_texesUsed; ++i )\r\n\t\t{\r\n\t\t\tuploadArrayTexture( i, maxArrayTextures, Global::eventConnector->game()->sf()->pixelData( i ).cbegin() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid MainWindowRenderer::onUpdateSelection( const QMap<unsigned int, SelectionData>& data, bool noDepthTest )\r\n{\r\n\tm_selectionData.clear();\r\n\tfor( const auto& key : data.keys() )\r\n\t{\r\n\t\tm_selectionData.insert( key, data[key] );\r\n\t}\r\n\tm_selectionNoDepthTest = noDepthTest;\r\n}\r\n\r\nvoid MainWindowRenderer::onCenterCameraPosition( const Position& target )\r\n{\r\n\tm_moveX     = 16 * (-target.x + target.y);\r\n\tm_moveY     = 8 * ( -target.x - target.y );\r\n\tm_viewLevel = target.z;\r\n\tonRenderParamsChanged();\r\n}\r\n\r\nvoid MainWindowRenderer::updatePositionAfterCWRotation( float& x, float& y )\r\n{\r\n\tconstexpr int tileHeight = 8; //tiles are assumed to be 8 pixels high (and twice as wide)\r\n\tint tmp = x;\r\n\tx = -2 * ( Global::dimX * tileHeight + y );\r\n\ty = -( Global::dimY - 2 ) * tileHeight + tmp/2;\r\n}\r\n\r\nvoid MainWindowRenderer::onSetInMenu( bool value )\r\n{\r\n\tm_inMenu = value;\r\n}"
  },
  {
    "path": "src/gui/mainwindowrenderer.h",
    "content": "/*\t\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as\n    published by the Free Software Foundation, either version 3 of the\n    License, or (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n#pragma once\n\n#include \"aggregatorrenderer.h\"\n\n#include <NsGui/IView.h>\n\n#include <QElapsedTimer>\n#include <QMatrix4x4>\n#include <QOpenGLBuffer>\n#include <QOpenGLExtraFunctions>\n#include <QOpenGLFunctions>\n#include <QOpenGLShaderProgram>\n#include <QOpenGLVertexArrayObject>\n#include <QOpenGLWindow>\n\n#include <QOpenGLFunctions_4_3_Core>\n\nstruct Position;\nclass QOpenGLTexture;\nclass MainWindow;\n\nclass MainWindowRenderer : public QObject, protected QOpenGLFunctions_4_3_Core\n{\n\tQ_OBJECT\n\npublic:\n\tMainWindowRenderer( MainWindow* parent = Q_NULLPTR );\n\t~MainWindowRenderer();\n\n\tint rotation() { return m_rotation; }\n\tfloat scale() { return m_scale; }\n\tint moveX() { return m_moveX; }\n\tint moveY() { return m_moveY; }\n\nprotected:\n\tQOpenGLVertexArrayObject m_vao;\n\tQScopedPointer<QOpenGLShaderProgram> m_worldShader;\n\tQScopedPointer<QOpenGLShaderProgram> m_worldUpdateShader;\n\tQScopedPointer<QOpenGLShaderProgram> m_thoughtBubbleShader;\n\tQScopedPointer<QOpenGLShaderProgram> m_selectionShader;\n\tQScopedPointer<QOpenGLShaderProgram> m_axleShader;\n\n\tGLuint m_textures[32] = { 0 };\n\tGLuint m_tileBo       = 0;\n\tGLuint m_tileUpdateBo = 0;\n\tGLuint m_vbo          = 0;\n\tGLuint m_vibo         = 0;\n\n\tQString m_selectedAction = \"\";\n\nprivate:\n\tQString copyShaderToString( QString name );\n\tQOpenGLShaderProgram* initShader( QString name );\n\tQOpenGLShaderProgram* initComputeShader( QString name );\n\tbool initShaders();\n\n\tvoid initTextures();\n\tvoid initWorld();\n\n\tvoid paintTiles();\n\tvoid setCommonUniforms( QOpenGLShaderProgram* shader );\n\tvoid paintSelection();\n\tvoid paintThoughtBubbles();\n\tvoid paintAxles();\n\tvoid updateWorld();\n\tvoid uploadTileData( const QVector<TileDataUpdate>& tileData );\n\tvoid updateTextures();\n\tvoid updateRenderParams();\n\n\tvoid updatePositionAfterCWRotation( float& x, float& y );\n\n\tvoid createArrayTexture( int unit, int depth );\n\tvoid uploadArrayTexture( int unit, int depth, const uint8_t* data );\n\tint m_texesUsed         = 0;\n\tbool m_texesInitialized = false;\n\n\tMainWindow* m_parent;\n\n\tQMatrix4x4 m_projectionMatrix;\n\n\tint m_width  = 0;\n\tint m_height = 0;\n\n\tbool m_rendering = false;\n\tbool m_inMenu    = true;\n\n\tfloat m_moveX       = 0;\n\tfloat m_moveY       = 0;\n\tfloat m_scale       = 1.0;\n\tint m_rotation      = 0;\n\tint m_renderSize    = 100;\n\tint m_viewLevel     = 100;\n\tint m_renderDepth   = 10;\n\tbool m_debug        = false;\n\n\tstruct RenderVolume\n\t{\n\t\tPosition min;\n\t\tPosition max;\n\t\tinline Position size() const\n\t\t{\n\t\t\t// Min and max are inclusive\n\t\t\treturn max - min + Position( 1, 1, 1 );\n\t\t}\n\t};\n\tRenderVolume m_volume;\n\n\tbool m_paintCreatures = true;\n\n\tfloat m_daylight = 1.0;\n\n\tint m_countRenders = 0;\n\n\tbool m_pause     = false;\n\tfloat m_lightMin = 0.3f;\n\n\tbool m_reloadShaders = false;\n\n\tQMap<unsigned int, SelectionData> m_selectionData;\n\tbool m_selectionNoDepthTest = false;\n\n\tThoughtBubbleInfo m_thoughBubbles;\n\tAxleDataInfo m_axleData;\n\tQVector<QVector<TileDataUpdate>> m_pendingUpdates;\n\npublic slots:\n\tvoid initializeGL();\n\tvoid reloadShaders();\n\tvoid resize( int w, int h );\n\tvoid rotate( int direction );\n\tvoid move( float x, float y );\n\tvoid scale( float factor );\n\tvoid setScale( float scale );\n\tvoid setViewLevel( int level );\n\tvoid cleanup();\n\tvoid cleanupWorld();\n\n\tvoid onTileUpdates( const TileDataUpdateInfo& updates );\n\tvoid onThoughtBubbles( const ThoughtBubbleInfo& bubbles );\n\tvoid onAxelData( const AxleDataInfo& data );\n\n\tvoid paintWorld();\n\tvoid onRenderParamsChanged();\n\n\tvoid onSetInMenu( bool value );\n\n\tvoid onUpdateSelection( const QMap<unsigned int, SelectionData>& data, bool noDepthTest );\n\n\tvoid onCenterCameraPosition( const Position& target );\n\nsignals:\n\tvoid redrawRequired();\n\tvoid fullDataRequired();\n\tvoid signalCameraPosition(float x, float y, float z, int r, float scale );\n};\n"
  },
  {
    "path": "src/gui/openalwrapper.cpp",
    "content": "#include \"openalwrapper.h\"\n\n#include <al.h>\n#include <alc.h>\n#include <alext.h>\n#include <cstring>\n#include <fstream>\n#include <iostream>\n#include <sstream>\n#include <vector>\n\nusing namespace AL;\n\n#define _DEBUG\n\n#ifdef _DEBUG\n#define validate() Object::checkContextActive()\n#else\n#define validate() void()\n#endif\n\nstruct Device::Functions\n{\n\t/* Thread local context functions */\n\tPFNALCSETTHREADCONTEXTPROC alcSetThreadContext;\n\tPFNALCGETTHREADCONTEXTPROC alcGetThreadContext;\n\n\t/* Filter object functions */\n\tLPALGENFILTERS alGenFilters;\n\tLPALDELETEFILTERS alDeleteFilters;\n\tLPALISFILTER alIsFilter;\n\tLPALFILTERI alFilteri;\n\tLPALFILTERIV alFilteriv;\n\tLPALFILTERF alFilterf;\n\tLPALFILTERFV alFilterfv;\n\tLPALGETFILTERI alGetFilteri;\n\tLPALGETFILTERIV alGetFilteriv;\n\tLPALGETFILTERF alGetFilterf;\n\tLPALGETFILTERFV alGetFilterfv;\n\n\t/* Effect object functions */\n\tLPALGENEFFECTS alGenEffects;\n\tLPALDELETEEFFECTS alDeleteEffects;\n\tLPALISEFFECT alIsEffect;\n\tLPALEFFECTI alEffecti;\n\tLPALEFFECTIV alEffectiv;\n\tLPALEFFECTF alEffectf;\n\tLPALEFFECTFV alEffectfv;\n\tLPALGETEFFECTI alGetEffecti;\n\tLPALGETEFFECTIV alGetEffectiv;\n\tLPALGETEFFECTF alGetEffectf;\n\tLPALGETEFFECTFV alGetEffectfv;\n\n\t/* Auxiliary Effect Slot object functions */\n\tLPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;\n\tLPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;\n\tLPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;\n\tLPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;\n\tLPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;\n\tLPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;\n\tLPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;\n\tLPALGETAUXILIARYEFFECTSLOTI alGetAuxiliaryEffectSloti;\n\tLPALGETAUXILIARYEFFECTSLOTIV alGetAuxiliaryEffectSlotiv;\n\tLPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;\n\tLPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;\n\n\tFunctions( const Device& device )\n\t{\n\t\t/* Define a macro to help load the function pointers. */\n#define LOAD_PROC( x ) ( ( x ) = (decltype( x ))alcGetProcAddress( device.device(), #x ) )\n\t\tLOAD_PROC( alcSetThreadContext );\n\t\tLOAD_PROC( alcGetThreadContext );\n\n\t\tLOAD_PROC( alGenFilters );\n\t\tLOAD_PROC( alDeleteFilters );\n\t\tLOAD_PROC( alIsFilter );\n\t\tLOAD_PROC( alFilteri );\n\t\tLOAD_PROC( alFilteriv );\n\t\tLOAD_PROC( alFilterf );\n\t\tLOAD_PROC( alFilterfv );\n\t\tLOAD_PROC( alGetFilteri );\n\t\tLOAD_PROC( alGetFilteriv );\n\t\tLOAD_PROC( alGetFilterf );\n\t\tLOAD_PROC( alGetFilterfv );\n\n\t\tLOAD_PROC( alGenEffects );\n\t\tLOAD_PROC( alDeleteEffects );\n\t\tLOAD_PROC( alIsEffect );\n\t\tLOAD_PROC( alEffecti );\n\t\tLOAD_PROC( alEffectiv );\n\t\tLOAD_PROC( alEffectf );\n\t\tLOAD_PROC( alEffectfv );\n\t\tLOAD_PROC( alGetEffecti );\n\t\tLOAD_PROC( alGetEffectiv );\n\t\tLOAD_PROC( alGetEffectf );\n\t\tLOAD_PROC( alGetEffectfv );\n\n\t\tLOAD_PROC( alGenAuxiliaryEffectSlots );\n\t\tLOAD_PROC( alDeleteAuxiliaryEffectSlots );\n\t\tLOAD_PROC( alIsAuxiliaryEffectSlot );\n\t\tLOAD_PROC( alAuxiliaryEffectSloti );\n\t\tLOAD_PROC( alAuxiliaryEffectSlotiv );\n\t\tLOAD_PROC( alAuxiliaryEffectSlotf );\n\t\tLOAD_PROC( alAuxiliaryEffectSlotfv );\n\t\tLOAD_PROC( alGetAuxiliaryEffectSloti );\n\t\tLOAD_PROC( alGetAuxiliaryEffectSlotiv );\n\t\tLOAD_PROC( alGetAuxiliaryEffectSlotf );\n\t\tLOAD_PROC( alGetAuxiliaryEffectSlotfv );\n#undef LOAD_PROC\n\t}\n};\n\nstatic std::uint32_t read_uint32( const char* buffer )\n{\n\tuint32_t tmp = 0;\n\tstd::memcpy( &tmp, buffer, 4 );\n\treturn tmp;\n}\n\nstatic std::uint32_t read_uint16( const char* buffer )\n{\n\tuint32_t tmp = 0;\n\tstd::memcpy( &tmp, buffer, 2 );\n\treturn tmp;\n}\n\nstatic void load_wav_file_header( std::ifstream& file, std::uint8_t& channels, std::uint32_t& sampleRate, std::uint8_t& bitsPerSample, ALsizei& size )\n{\n\tchar buffer[4];\n\tif ( !file.is_open() )\n\t\tthrow std::logic_error( \"File not open\" );\n\n\t// the RIFF\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read RIFF\" );\n\t}\n\tif ( std::strncmp( buffer, \"RIFF\", 4 ) != 0 )\n\t{\n\t\tthrow std::logic_error( \"ERROR: file is not a valid WAVE file (header doesn't begin with RIFF)\" );\n\t}\n\n\t// the size of the file\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read size of file\" );\n\t}\n\n\t// the WAVE\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read WAVE\" );\n\t}\n\tif ( std::strncmp( buffer, \"WAVE\", 4 ) != 0 )\n\t{\n\t\tthrow std::logic_error( \"ERROR: file is not a valid WAVE file (header doesn't contain WAVE)\" );\n\t}\n\n\t// \"fmt/0\"\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read fmt/0\" );\n\t}\n\n\t// this is always 16, the size of the fmt data chunk\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read the 16\" );\n\t}\n\n\t// PCM should be 1?\n\tif ( !file.read( buffer, 2 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read PCM\" );\n\t}\n\n\t// the number of channels\n\tif ( !file.read( buffer, 2 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read number of channels\" );\n\t}\n\tchannels = read_uint16( buffer );\n\n\t// sample rate\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read sample rate\" );\n\t}\n\tsampleRate = read_uint32( buffer );\n\n\t// (sampleRate * bitsPerSample * channels) / 8\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read (sampleRate * bitsPerSample * channels) / 8\" );\n\t}\n\n\t// ?? dafaq\n\tif ( !file.read( buffer, 2 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read dafaq\" );\n\t}\n\n\t// bitsPerSample\n\tif ( !file.read( buffer, 2 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read bits per sample\" );\n\t}\n\tbitsPerSample = read_uint16( buffer );\n\n\t// data chunk header \"data\"\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read data chunk header\" );\n\t}\n\tif ( std::memcmp( buffer, \"data\", 4 ) != 0 )\n\t{\n\t\tthrow std::logic_error( \"ERROR: file is not a valid WAVE file (doesn't have 'data' tag)\" );\n\t}\n\n\t// size of data\n\tif ( !file.read( buffer, 4 ) )\n\t{\n\t\tthrow std::logic_error( \"ERROR: could not read data size\" );\n\t}\n\tsize = read_uint32( buffer );\n\n\t/* cannot be at the end of file */\n\tif ( file.eof() )\n\t{\n\t\tthrow std::logic_error( \"ERROR: reached EOF on the file\" );\n\t}\n\tif ( file.fail() )\n\t{\n\t\tthrow std::logic_error( \"ERROR: fail state set on the file\" );\n\t}\n}\n\nstatic std::vector<char> load_wav( const std::string& filename, std::uint8_t& channels, std::uint32_t& sampleRate, std::uint8_t& bitsPerSample )\n{\n\tstd::ifstream in( filename, std::ios::binary );\n\tif ( !in.is_open() )\n\t{\n\t\tthrow std::logic_error( \"ERROR: Could not open \\\"\" + filename + \"\\\"\" );\n\t}\n\tALsizei size;\n\tload_wav_file_header( in, channels, sampleRate, bitsPerSample, size );\n\n\tstd::vector<char> data;\n\tdata.resize( size );\n\tin.read( data.data(), data.size() );\n\n\treturn data;\n}\n\nstatic void check_al_errors()\n{\n\tALenum error = alGetError();\n\tif ( error != AL_NO_ERROR )\n\t{\n\t\tstd::stringstream ss;\n\t\tswitch ( error )\n\t\t{\n\t\t\tcase AL_INVALID_NAME:\n\t\t\t\tss << \"AL_INVALID_NAME: a bad name (ID) was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase AL_INVALID_ENUM:\n\t\t\t\tss << \"AL_INVALID_ENUM: an invalid enum value was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase AL_INVALID_VALUE:\n\t\t\t\tss << \"AL_INVALID_VALUE: an invalid value was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase AL_INVALID_OPERATION:\n\t\t\t\tss << \"AL_INVALID_OPERATION: the requested operation is not valid\";\n\t\t\t\tbreak;\n\t\t\tcase AL_OUT_OF_MEMORY:\n\t\t\t\tss << \"AL_OUT_OF_MEMORY: the requested operation resulted in OpenAL running out of memory\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tss << \"UNKNOWN AL ERROR: \" << error;\n\t\t}\n\t\tthrow std::invalid_argument( ss.str() );\n\t}\n}\n\ntemplate <typename alFunction, typename... Params>\nauto alCall( alFunction function, Params... params )\n\t-> typename std::enable_if_t<std::is_same_v<void, decltype( function( params... ) )>, void>\n{\n\tfunction( std::forward<Params>( params )... );\n\tcheck_al_errors();\n}\n\ntemplate <typename alFunction, typename... Params>\nauto alCall( alFunction function, Params... params )\n\t-> typename std::enable_if_t<!std::is_same_v<void, decltype( function( params... ) )>, decltype( function( params... ) )>\n{\n\tauto ret = function( std::forward<Params>( params )... );\n\tcheck_al_errors();\n\treturn ret;\n}\n\nstatic void check_alc_errors( ALCdevice* device )\n{\n\tALCenum error = alcGetError( device );\n\tif ( error != ALC_NO_ERROR )\n\t{\n\t\tstd::stringstream ss;\n\t\tswitch ( error )\n\t\t{\n\t\t\tcase ALC_INVALID_VALUE:\n\t\t\t\tss << \"ALC_INVALID_VALUE: an invalid value was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase ALC_INVALID_DEVICE:\n\t\t\t\tss << \"ALC_INVALID_DEVICE: a bad device was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase ALC_INVALID_CONTEXT:\n\t\t\t\tss << \"ALC_INVALID_CONTEXT: a bad context was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase ALC_INVALID_ENUM:\n\t\t\t\tss << \"ALC_INVALID_ENUM: an unknown enum value was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tcase ALC_OUT_OF_MEMORY:\n\t\t\t\tss << \"ALC_OUT_OF_MEMORY: an unknown enum value was passed to an OpenAL function\";\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tss << \"UNKNOWN ALC ERROR: \" << error;\n\t\t}\n\t\tthrow std::invalid_argument( ss.str() );\n\t}\n}\n\ntemplate <typename alcFunction, typename... Params>\nauto alcCall( alcFunction function, ALCdevice* device, Params... params )\n\t-> typename std::enable_if_t<std::is_same_v<void, decltype( function( params... ) )>, void>\n{\n\tfunction( std::forward<Params>( params )... );\n\tcheck_alc_errors( device );\n}\n\ntemplate <typename alcFunction, typename... Params>\nauto alcCall( alcFunction function, ALCdevice* device, Params... params )\n\t-> typename std::enable_if_t<!std::is_same_v<void, decltype( function( params... ) )>, decltype( function( params... ) )>\n{\n\tauto returnValue = function( std::forward<Params>( params )... );\n\tcheck_alc_errors( device );\n\treturn returnValue;\n}\n\nDevice::Device() :\n\tm_openALDevice( alcOpenDevice( nullptr ) )\n{\n\tif ( !m_openALDevice )\n\t\tthrow std::logic_error( \"Could not open device\" );\n\tm_functions = std::make_unique<Functions>( *this );\n}\n\nDevice::~Device()\n{\n\tALCboolean closed = alcCall( alcCloseDevice, m_openALDevice, m_openALDevice );\n}\n\nContext::Context( const std::shared_ptr<Device>& device ) :\n\tm_device( device ),\n\tm_openACLContext( alcCall( alcCreateContext, m_device->device(), m_device->device(), nullptr ) )\n{\n\tif ( !m_openACLContext )\n\t{\n\t\tthrow std::logic_error( \"Could not create context\" );\n\t}\n\tm_hasEFX         = alcCall( alcIsExtensionPresent, m_device->device(), m_device->device(), ALC_EXT_EFX_NAME );\n\tm_hasThreadLocal = alcCall( alcIsExtensionPresent, m_device->device(), m_device->device(), \"ALC_EXT_thread_local_context\" );\n}\n\nContext::~Context()\n{\n\talcCall( alcDestroyContext, m_device->device(), m_openACLContext );\n}\n\nContext::Lock::Lock( const std::shared_ptr<Context>& context ) :\n\tm_context( context )\n{\n#ifdef _DEBUG\n\tauto activeContext = m_context->hasThreadLocal() ? m_context->device()->fn()->alcGetThreadContext() : alcGetCurrentContext();\n\tif ( activeContext )\n\t{\n\t\tthrow std::logic_error( \"Another OpenAL context is already active\" );\n\t}\n#endif // _DEBUG\n\tif ( m_context->hasThreadLocal() )\n\t{\n\t\tALCboolean contextMadeCurrent = alcCall( m_context->device()->fn()->alcSetThreadContext, m_context->device()->device(), m_context->context() );\n\t\tif ( !contextMadeCurrent )\n\t\t{\n\t\t\tthrow std::logic_error( \"Failed to activate OpenAL context\" );\n\t\t}\n\t}\n\telse\n\t{\n\t\tALCboolean contextMadeCurrent = alcCall( alcMakeContextCurrent, m_context->device()->device(), m_context->context() );\n\t\tif ( !contextMadeCurrent )\n\t\t{\n\t\t\tthrow std::logic_error( \"Failed to activate OpenAL context\" );\n\t\t}\n\t}\n}\n\nContext::Lock::~Lock()\n{\n\tif ( m_context->hasThreadLocal() )\n\t{\n\t\talcCall( m_context->device()->fn()->alcSetThreadContext, m_context->device()->device(), nullptr );\n\t}\n\telse\n\t{\n\t\talcCall( alcMakeContextCurrent, m_context->device()->device(), nullptr );\n\t}\n}\n\nBuffer::Buffer( const std::shared_ptr<Context>& context, const std::string& fileName ) :\n\tObject( context )\n{\n\tvalidate();\n\talCall( alGenBuffers, 1, &m_buffer );\n\tstd::uint8_t channels;\n\tstd::uint32_t sampleRate;\n\tstd::uint8_t bitsPerSample;\n\tauto soundData = load_wav( fileName, channels, sampleRate, bitsPerSample );\n\tALenum format;\n\tif ( channels == 1 && bitsPerSample == 8 )\n\t\tformat = AL_FORMAT_MONO8;\n\telse if ( channels == 1 && bitsPerSample == 16 )\n\t\tformat = AL_FORMAT_MONO16;\n\telse if ( channels == 2 && bitsPerSample == 8 )\n\t\tformat = AL_FORMAT_STEREO8;\n\telse if ( channels == 2 && bitsPerSample == 16 )\n\t\tformat = AL_FORMAT_STEREO16;\n\telse\n\t{\n\t\tstd::stringstream ss;\n\t\tss << \"Unrecognised wave format: \" << channels << \" channels, \" << bitsPerSample << \" bps\";\n\t\tthrow std::invalid_argument( ss.str() );\n\t}\n\talCall( alBufferData, m_buffer, format, soundData.data(), static_cast<ALsizei>( soundData.size() ), sampleRate );\n}\n\nBuffer::~Buffer()\n{\n\tvalidate();\n\talCall( alDeleteBuffers, 1, &m_buffer );\n}\n\nSource::Source( const std::shared_ptr<Context>& context, std::shared_ptr<Buffer> buffer ) :\n\tObject( context ),\n\tm_buffer( buffer )\n{\n\tvalidate();\n\talCall( alGenSources, 1, &m_source );\n\n\talCall( alSourcef, m_source, AL_PITCH, 1.0f );\n\talCall( alSourcef, m_source, AL_GAIN, 1.0f );\n\talCall( alSource3f, m_source, AL_POSITION, 0, 0, 0 );\n\talCall( alSource3f, m_source, AL_VELOCITY, 0, 0, 0 );\n\talCall( alSourcei, m_source, AL_LOOPING, AL_FALSE );\n\talCall( alSourcei, m_source, AL_BUFFER, m_buffer->buffer() );\n}\n\nSource::~Source()\n{\n\tvalidate();\n\talCall( alDeleteSources, 1, &m_source );\n}\n\nvoid Source::setRelativeToListener( bool relative )\n{\n\tvalidate();\n\talCall( alSourcei, m_source, AL_SOURCE_RELATIVE, relative ? AL_TRUE : AL_FALSE );\n}\n\nvoid Source::setVolume( float volume )\n{\n\tvalidate();\n\talCall( alSourcef, m_source, AL_GAIN, volume );\n}\n\nvoid Source::setPosition( float x, float y, float z )\n{\n\tvalidate();\n\talCall( alSource3f, m_source, AL_POSITION, x, y, z );\n}\n\nvoid Source::setPitch( float pitch )\n{\n\tvalidate();\n\talCall( alSourcef, m_source, AL_PITCH, pitch );\n}\n\nvoid AL::Source::rewind()\n{\n\tvalidate();\n\talCall( alSourceRewind, m_source );\n}\n\nvoid Source::play()\n{\n\tvalidate();\n\talCall( alSourcePlay, m_source );\n}\n\nvoid Source::stop()\n{\n\tvalidate();\n\talCall( alSourceStop, m_source );\n}\n\nvoid Source::setDryPathFilter( const std::shared_ptr<Filter>& filter )\n{\n\tvalidate();\n\talCall( alSourcei, m_source, AL_DIRECT_FILTER, filter ? filter->filter() : AL_FILTER_NULL );\n\tm_dryPath = filter;\n}\n\nvoid Source::setWetPathEffect( ALuint slot, const std::shared_ptr<EffectSlot>& auxSlot, const std::shared_ptr<Filter>& filter )\n{\n\tvalidate();\n\talCall( alSource3i, m_source, AL_AUXILIARY_SEND_FILTER, auxSlot ? auxSlot->slot() : AL_EFFECTSLOT_NULL, slot, filter ? filter->filter() : AL_FILTER_NULL );\n\tif ( auxSlot || filter )\n\t{\n\t\tm_wetPath[slot] = std::make_pair( auxSlot, filter );\n\t}\n\telse\n\t{\n\t\tm_wetPath.erase( slot );\n\t}\n}\n\nSource::PlayState Source::getPlayState() const\n{\n\tvalidate();\n\tALint state = AL_PLAYING;\n\talCall( alGetSourcei, m_source, AL_SOURCE_STATE, &state );\n\tswitch ( state )\n\t{\n\t\tcase AL_INITIAL:\n\t\t\treturn INITIAL;\n\t\tcase AL_PLAYING:\n\t\t\treturn PLAYING;\n\t\tcase AL_PAUSED:\n\t\t\treturn PAUSED;\n\t\tcase AL_STOPPED:\n\t\t\treturn STOPPED;\n\t\tdefault:\n\t\t\tthrow std::logic_error( \"Unknown playstate \" + std::to_string( state ) );\n\t}\n}\n\nEffect::Effect( const std::shared_ptr<Context>& context ) :\n\tObject( context )\n{\n\tvalidate();\n\tif ( !Object::context()->hasEFX() )\n\t{\n\t\tthrow std::invalid_argument( \"No EFX support\" );\n\t}\n\talCall( fn()->alGenEffects, 1, &m_effect );\n}\n\nEffect::~Effect()\n{\n\tvalidate();\n\talCall( fn()->alDeleteEffects, 1, &m_effect );\n}\n\nFilter::Filter( const std::shared_ptr<Context>& context ) :\n\tObject( context )\n{\n\tvalidate();\n\talCall( fn()->alGenFilters, 1, &m_filter );\n\talCall( fn()->alFilteri, m_filter, AL_FILTER_TYPE, AL_FILTER_NULL );\n}\n\nFilter::~Filter()\n{\n\tvalidate();\n\talCall( fn()->alDeleteFilters, 1, &m_filter );\n}\n\nvoid Filter::setGain( float lfGain, float midGain, float hfGain )\n{\n\tvalidate();\n\tif ( lfGain == 1.0f && midGain == 1.0f && hfGain == 1.0f )\n\t{\n\t\tfn()->alFilteri( m_filter, AL_FILTER_TYPE, AL_FILTER_NULL );\n\t}\n\telse if ( lfGain != midGain && midGain != hfGain )\n\t{\n\t\talCall( fn()->alFilteri, filter(), AL_FILTER_TYPE, AL_FILTER_BANDPASS );\n\t\talCall( fn()->alFilterf, filter(), AL_BANDPASS_GAINLF, lfGain );\n\t\talCall( fn()->alFilterf, filter(), AL_BANDPASS_GAIN, midGain );\n\t\talCall( fn()->alFilterf, filter(), AL_BANDPASS_GAINHF, hfGain );\n\t}\n\telse if ( midGain != hfGain )\n\t{\n\t\talCall( fn()->alFilteri, filter(), AL_FILTER_TYPE, AL_FILTER_LOWPASS );\n\t\talCall( fn()->alFilterf, filter(), AL_LOWPASS_GAIN, midGain );\n\t\talCall( fn()->alFilterf, filter(), AL_LOWPASS_GAINHF, hfGain );\n\t}\n\telse\n\t{\n\t\talCall( fn()->alFilteri, filter(), AL_FILTER_TYPE, AL_FILTER_HIGHPASS );\n\t\talCall( fn()->alFilterf, filter(), AL_HIGHPASS_GAINLF, lfGain );\n\t\talCall( fn()->alFilterf, filter(), AL_HIGHPASS_GAIN, midGain );\n\t}\n}\n\nEffectSlot::EffectSlot( const std::shared_ptr<Context>& context, const std::shared_ptr<Effect>& effect ) :\n\tObject( context ),\n\tm_effect( effect )\n{\n\tvalidate();\n\talCall( fn()->alGenAuxiliaryEffectSlots, 1, &m_slot );\n\talCall( fn()->alAuxiliaryEffectSloti, m_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, AL_TRUE );\n\talCall( fn()->alAuxiliaryEffectSloti, m_slot, AL_EFFECTSLOT_EFFECT, effect->effect() );\n}\n\nEffectSlot::~EffectSlot()\n{\n\tvalidate();\n\talCall( fn()->alDeleteAuxiliaryEffectSlots, 1, &m_slot );\n}\n\nReverbEffect::ReverbEffect( const std::shared_ptr<Context>& context ) :\n\tEffect( context ),\n\tm_hasEAX( alCall( alGetEnumValue, \"AL_EFFECT_EAXREVERB\" ) != 0 )\n{\n\tvalidate();\n\tif ( m_hasEAX )\n\t{\n\t\talCall( fn()->alEffecti, effect(), AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB );\n\t}\n\telse\n\t{\n\t\talCall( fn()->alEffecti, effect(), AL_EFFECT_TYPE, AL_EFFECT_REVERB );\n\t}\n}\n\nReverbEffect::~ReverbEffect() = default;\n\nvoid ReverbEffect::setPreset( const EFXEAXREVERBPROPERTIES& preset )\n{\n\tvalidate();\n\tif ( m_hasEAX )\n\t{\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_DENSITY, preset.flDensity );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_DIFFUSION, preset.flDiffusion );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_GAIN, preset.flGain );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_GAINHF, preset.flGainHF );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_GAINLF, preset.flGainLF );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_DECAY_TIME, preset.flDecayTime );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_DECAY_HFRATIO, preset.flDecayHFRatio );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_DECAY_LFRATIO, preset.flDecayLFRatio );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_REFLECTIONS_GAIN, preset.flReflectionsGain );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_REFLECTIONS_DELAY, preset.flReflectionsDelay );\n\t\talCall( fn()->alEffectfv, effect(), AL_EAXREVERB_REFLECTIONS_PAN, preset.flReflectionsPan );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_LATE_REVERB_GAIN, preset.flLateReverbGain );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_LATE_REVERB_DELAY, preset.flLateReverbDelay );\n\t\talCall( fn()->alEffectfv, effect(), AL_EAXREVERB_LATE_REVERB_PAN, preset.flLateReverbPan );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_ECHO_TIME, preset.flEchoTime );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_ECHO_DEPTH, preset.flEchoDepth );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_MODULATION_TIME, preset.flModulationTime );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_MODULATION_DEPTH, preset.flModulationDepth );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_AIR_ABSORPTION_GAINHF, preset.flAirAbsorptionGainHF );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_HFREFERENCE, preset.flHFReference );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_LFREFERENCE, preset.flLFReference );\n\t\talCall( fn()->alEffectf, effect(), AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, preset.flRoomRolloffFactor );\n\t\talCall( fn()->alEffecti, effect(), AL_EAXREVERB_DECAY_HFLIMIT, preset.iDecayHFLimit );\n\t}\n\telse\n\t{\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_DENSITY, preset.flDensity );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_DIFFUSION, preset.flDiffusion );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_GAIN, preset.flGain );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_GAINHF, preset.flGainHF );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_DECAY_TIME, preset.flDecayTime );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_DECAY_HFRATIO, preset.flDecayHFRatio );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_REFLECTIONS_GAIN, preset.flReflectionsGain );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_REFLECTIONS_DELAY, preset.flReflectionsDelay );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_LATE_REVERB_GAIN, preset.flLateReverbGain );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_LATE_REVERB_DELAY, preset.flLateReverbDelay );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_AIR_ABSORPTION_GAINHF, preset.flAirAbsorptionGainHF );\n\t\talCall( fn()->alEffectf, effect(), AL_REVERB_ROOM_ROLLOFF_FACTOR, preset.flRoomRolloffFactor );\n\t\talCall( fn()->alEffecti, effect(), AL_REVERB_DECAY_HFLIMIT, preset.iDecayHFLimit );\n\t}\n}\n\nObject::Object( const std::shared_ptr<Context>& context ) :\n\tm_context( context )\n{\n\tif ( !m_context )\n\t\tthrow std::invalid_argument( \"Missing OpenAL context\" );\n}\n\nObject::~Object() = default;\n\nvoid Object::checkContextActive() const\n{\n\tauto activeContext = m_context->hasThreadLocal() ? fn()->alcGetThreadContext() : alcGetCurrentContext();\n\tif ( activeContext != m_context->context() )\n\t{\n\t\tthrow std::logic_error( \"Another OpenAL context is active\" );\n\t}\n}\n\nListener::Listener( const std::shared_ptr<Context>& context ) :\n\tObject( context )\n{\n}\n\nListener::~Listener() = default;\n\nvoid Listener::setOrientation( const float forward[3], const float up[3] )\n{\n\tALfloat orientation[6] = {\n\t\tforward[0],\n\t\tforward[1],\n\t\tforward[2],\n\t\tup[0],\n\t\tup[1],\n\t\tup[2],\n\t};\n\talCall( alListenerfv, AL_ORIENTATION, orientation );\n}\n\nvoid Listener::setPosition( const float position[3] )\n{\n\talCall( alListenerfv, AL_POSITION, position );\n}\n\nvoid AL::Listener::setVolume( float volume )\n{\n\talCall( alListenerf, AL_GAIN, volume );\n}\n"
  },
  {
    "path": "src/gui/openalwrapper.h",
    "content": "#pragma once\n\n#include <memory>\n#include <cstdint>\n#include <alc.h>\n#include <efx-presets.h>\n\nnamespace AL\n{\nclass Device\n{\npublic:\n\tstruct Functions;\n\n\tDevice();\n\t~Device();\n\tDevice( Device&& ) = delete;\n\tDevice( const Device& ) = delete;\n\n\tALCdevice* device() const\n\t{\n\t\treturn m_openALDevice;\n\t}\n\n\tconst Functions* fn() const\n\t{\n\t\treturn m_functions.get();\n\t}\n\nprivate:\n\tALCdevice* const m_openALDevice = nullptr;\n\tstd::unique_ptr<Functions> m_functions;\n};\n\nclass Context\n{\npublic:\n\tContext( const std::shared_ptr<Device>& device );\n\t~Context();\n\tContext( Context&& ) = delete;\n\tContext( const Context& ) = delete;\n\n\tstd::shared_ptr<const Device> device() const\n\t{\n\t\treturn std::const_pointer_cast<const Device>( m_device );\n\t}\n\n\tALCcontext* context() const\n\t{\n\t\treturn m_openACLContext;\n\t}\n\n\tbool hasEFX() const\n\t{\n\t\treturn m_hasEFX;\n\t}\n\tbool hasThreadLocal() const\n\t{\n\t\treturn m_hasThreadLocal;\n\t}\n\n\tclass Lock\n\t{\n\tpublic:\n\t\tLock( const std::shared_ptr<Context>& context );\n\t\t~Lock();\n\n\tprivate:\n\t\tstd::shared_ptr<Context> m_context;\n\t};\n\nprivate:\n\tstd::shared_ptr<Device> m_device;\n\tALCcontext* m_openACLContext = nullptr;\n\tbool m_hasEFX                = false;\n\tbool m_hasThreadLocal        = false;\n};\n\nclass Object\n{\npublic:\n\tObject( const std::shared_ptr<Context>& context );\n\t~Object();\n\tObject()                  = delete;\n\tObject( Object&& )      = delete;\n\tObject( const Object& ) = delete;\n\tstd::shared_ptr<const Context> context() const\n\t{\n\t\treturn std::const_pointer_cast<const Context>( m_context );\n\t}\n\n\tconst Device::Functions* fn() const\n\t{\n\t\treturn m_context->device()->fn();\n\t}\n\nprotected:\n\tvoid checkContextActive() const;\n\nprivate:\n\tstd::shared_ptr<Context> m_context;\n};\n\nclass Listener : public Object\n{\npublic:\n\tListener( const std::shared_ptr<Context>& context );\n\t~Listener();\n\tvoid setOrientation( const float forward[3], const float up[3] );\n\tvoid setPosition( const float position[3] );\n\tvoid setVolume( float volume );\n};\n\nclass Buffer : public Object\n{\npublic:\n\tBuffer( const std::shared_ptr<Context>& context, const std::string& fileName );\n\t~Buffer();\n\tuint32_t buffer() const\n\t{\n\t\treturn m_buffer;\n\t}\n\nprivate:\n\tuint32_t m_buffer = 0;\n};\n\nclass Effect : public Object\n{\npublic:\n\tEffect( const std::shared_ptr<Context>& context );\n\t~Effect();\n\tuint32_t effect() const\n\t{\n\t\treturn m_effect;\n\t}\n\nprivate:\n\tuint32_t m_effect = 0;\n};\n\nclass ReverbEffect : public Effect\n{\npublic:\n\tReverbEffect( const std::shared_ptr<Context>& context );\n\t~ReverbEffect();\n\tvoid setPreset( const EFXEAXREVERBPROPERTIES& preset );\n\nprivate:\n\tconst bool m_hasEAX;\n};\n\nclass EffectSlot : public Object\n{\npublic:\n\tEffectSlot( const std::shared_ptr<Context>& context, const std::shared_ptr<Effect>& effect );\n\t~EffectSlot();\n\tuint32_t slot() const\n\t{\n\t\treturn m_slot;\n\t}\n\nprivate:\n\tstd::shared_ptr<Effect> m_effect;\n\tuint32_t m_slot = 0;\n};\n\nclass Filter : public Object\n{\npublic:\n\tFilter( const std::shared_ptr<Context>& context );\n\t~Filter();\n\tvoid setGain( float lfGain, float midGain, float hfGain );\n\tuint32_t filter() const\n\t{\n\t\treturn m_filter;\n\t}\n\nprivate:\n\tuint32_t m_filter = 0;\n};\n\nclass Source : public Object\n{\npublic:\n\tSource( const std::shared_ptr<Context>& context, std::shared_ptr<Buffer> buffer );\n\t~Source();\n\n\tenum PlayState\n\t{\n\t\tINITIAL = 0,\n\t\tPLAYING,\n\t\tPAUSED,\n\t\tSTOPPED\n\t};\n\n\tvoid setRelativeToListener( bool relative );\n\tvoid setVolume( float volume );\n\tvoid setPosition( float x, float y, float z );\n\tvoid setPitch( float pitch );\n\tvoid rewind();\n\tvoid play();\n\tvoid stop();\n\tvoid setDryPathFilter( const std::shared_ptr<Filter>& filter );\n\tvoid setWetPathEffect( uint32_t slot, const std::shared_ptr<EffectSlot>& effectSlot, const std::shared_ptr<Filter>& filter );\n\tPlayState getPlayState() const;\n\nprivate:\n\tstd::shared_ptr<Buffer> m_buffer;\n\tstd::shared_ptr<Filter> m_dryPath;\n\tstd::unordered_map<uint32_t, std::pair<std::shared_ptr<EffectSlot>, std::shared_ptr<Filter>>> m_wetPath;\n\tuint32_t m_source = 0;\n};\n} // namespace AL\n"
  },
  {
    "path": "src/gui/strings.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"strings.h\"\r\n\r\n#include \"../base/config.h\"\r\n#include \"../base/db.h\"\r\n\r\n#include <QApplication>\r\n#include <QDebug>\r\n#include <QJsonDocument>\r\n#include <QVariantMap>\r\n\r\nQMap<QString, QString> Strings::m_table = QMap<QString, QString>();\r\nQString Strings::m_language             = \"\";\r\n\r\nStrings::Strings()\r\n{\r\n}\r\n\r\nStrings::~Strings()\r\n{\r\n}\r\n\r\nbool Strings::init()\r\n{\r\n\tm_language = Global::cfg->get( \"language\" ).toString();\r\n\tm_table.clear();\r\n\t//for( auto row : DB::selectRows( \"Translation_\" + m_language ) )\r\n\tfor ( auto row : DB::selectRows( \"Translation\" ) )\r\n\t{\r\n\t\tm_table.insert( row.value( \"ID\" ).toString(), row.value( \"Text\" ).toString() );\r\n\t}\r\n\r\n\treturn true;\r\n}\r\n\r\nQString Strings::s( QString key )\r\n{\r\n\tif ( m_table.contains( key ) )\r\n\t{\r\n\t\treturn m_table[key];\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"Error: \" + key;\r\n\t\t//return m_table[\"$ERROR_TranslationKeyUnknown\"].toString();\r\n\t}\r\n}\r\n\r\nvoid Strings::insertString( QString key, QString string )\r\n{\r\n\tm_table.insert( key, string );\r\n}\r\n\r\nQString Strings::randomKingdomName()\r\n{\r\n\tauto ruleList = DB::selectRows( \"Namerules_Rule\", \"Faction\" );\r\n\r\n\tsrand( std::chrono::system_clock::now().time_since_epoch().count() );\r\n\tauto rule = ruleList.at( rand() % ruleList.size() ).value( \"Part\" ).toString().split( \"|\" );\r\n\tQString name;\r\n\tfor ( auto part : rule )\r\n\t{\r\n\t\tname += replaceNamePart( part );\r\n\t\tname += \" \";\r\n\t}\r\n\tname.remove( name.size() - 1, 1 );\r\n\treturn name;\r\n}\r\n\r\nQString Strings::replaceNamePart( QString part )\r\n{\r\n\tQSet<QString> noReplaceables = { \"The\", \"of\", \"Land\", \"Kingdom\" };\r\n\tif ( noReplaceables.contains( part ) )\r\n\t{\r\n\t\treturn part;\r\n\t}\r\n\tQStringList pl = part.split( \"_\" );\r\n\tQString out;\r\n\r\n\tswitch ( pl.size() )\r\n\t{\r\n\t\tcase 1: // only \"Adjective\" so far\r\n\t\t\tout = replaceNamePart2( pl.at( 0 ) );\r\n\t\t\tbreak;\r\n\t\tcase 2:\r\n\t\t\tout = replaceNamePart2( pl.at( 0 ), pl.at( 1 ) );\r\n\t\t\tbreak;\r\n\t\tcase 3: // comppounds\r\n\t\t{\r\n\t\t\tif ( pl.at( 0 ) == \"Compound\" )\r\n\t\t\t{\r\n\t\t\t\tout = replaceNamePart2( pl.at( 1 ), pl.at( 2 ) );\r\n\t\t\t\tout += replaceNamePart2( pl.at( 1 ), pl.at( 2 ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\tout.replace( 0, 1, out[0].toUpper() );\r\n\treturn out;\r\n}\r\n\r\nQString Strings::replaceNamePart2( QString part )\r\n{\r\n\tQString tableName = \"Words_\" + part;\r\n\tint ra            = rand() % DB::numRows( tableName );\r\n\treturn DB::select( \"Word\", tableName, ra ).toString();\r\n}\r\n\r\nQString Strings::replaceNamePart2( QString part, QString part2 )\r\n{\r\n\tif ( part2 == \"Singular\" )\r\n\t{\r\n\t\tpart2 = \"Word\";\r\n\t}\r\n\tQString tableName = \"Words_\" + part;\r\n\tint ra            = rand() % DB::numRows( tableName );\r\n\treturn DB::select( part2, tableName, ra ).toString();\r\n}\r\n\r\nQString Strings::numberWord( int number )\r\n{\r\n\tif ( number >= 0 )\r\n\t{\r\n\t\tif ( number < 20 )\r\n\t\t{\r\n\t\t\tauto result = DB::select2( \"Word\", \"Words_Numbers\", \"Number\", number );\r\n\t\t\tif ( result.size() > 0 )\r\n\t\t\t{\r\n\t\t\t\treturn result.first().toString();\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn QString::number( number );\r\n\t}\r\n\treturn \"no number\";\r\n}"
  },
  {
    "path": "src/gui/strings.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <QMap>\r\n\r\nclass Strings\r\n{\r\nprivate:\r\n\t// Private Constructor\r\n\tStrings();\r\n\t// Stop the compiler generating methods of copy the object\r\n\tStrings( Strings const& copy );            // Not Implemented\r\n\tStrings& operator=( Strings const& copy ); // Not Implemented\r\n\r\n\tstatic QMap<QString, QString> m_table;\r\n\tstatic QString m_language;\r\n\r\n\tQMap<int, QString> m_numberWords;\r\n\r\n\tstatic QString replaceNamePart( QString part );\r\n\tstatic QString replaceNamePart2( QString part );\r\n\tstatic QString replaceNamePart2( QString part, QString part2 );\r\n\r\npublic:\r\n\t~Strings();\r\n\r\n\tstatic Strings& getInstance()\r\n\t{\r\n\t\t// The only instance\r\n\t\t// Guaranteed to be lazy initialized\r\n\t\t// Guaranteed that it will be destroyed correctly\r\n\t\tstatic Strings instance;\r\n\t\treturn instance;\r\n\t}\r\n\r\n\tstatic Strings& gi()\r\n\t{\r\n\t\t// The only instance\r\n\t\t// Guaranteed to be lazy initialized\r\n\t\t// Guaranteed that it will be destroyed correctly\r\n\t\tstatic Strings instance;\r\n\t\treturn instance;\r\n\t}\r\n\r\n\tbool init();\r\n\r\n\tstatic QString s( QString key );\r\n\r\n\tstatic void insertString( QString key, QString string );\r\n\r\n\tQString numberWord( int number );\r\n\tQString randomKingdomName();\r\n};\r\n\r\ntypedef Strings S;"
  },
  {
    "path": "src/gui/xaml/GameGui.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"GameGui.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nGameGui::GameGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &GameGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid GameGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"GameGui.xaml\" );\r\n}\r\n\r\nbool GameGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid GameGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::GameGui, \"IngnomiaGUI.GameGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/GameGui.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __GAMEGUI_H__\r\n#define __GAMEGUI_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GameGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tGameGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( GameGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/GameModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"GameModel.h\"\r\n#include \"ProxyGameView.h\"\r\n\r\n#include \"../strings.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n#include <QImage>\r\n#include <QPixmap>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n#pragma region DataItems\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nCommandButton::CommandButton( QString name, QString sid )\r\n{\r\n\t_name = name.toStdString().c_str();\r\n\t_sid  = sid.toStdString().c_str();\r\n}\r\n\r\nconst char* CommandButton::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst char* CommandButton::GetID() const\r\n{\r\n\treturn _sid.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nBuildButton::BuildButton( QString name, QString sid, QString image )\r\n{\r\n\t_name  = name.toStdString().c_str();\r\n\t_sid   = sid.toStdString().c_str();\r\n\t_image = image.toStdString().c_str();\r\n}\r\n\r\nconst char* BuildButton::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst char* BuildButton::GetID() const\r\n{\r\n\treturn _sid.Str();\r\n}\r\n\r\nconst char* BuildButton::GetImage() const\r\n{\r\n\treturn _image.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nBuildItem::BuildItem( const GuiBuildItem& gbi, ProxyGameView* proxy )\r\n{\r\n\tm_name = gbi.name.toStdString().c_str();\r\n\tm_sid  = gbi.id;\r\n\tm_type = gbi.biType;\r\n\tm_proxy = proxy;\r\n\r\n\tm_cmdBuild.SetExecuteFunc( MakeDelegate( this, &BuildItem::onCmdBuild ) );\r\n\r\n\tm_requiredItems = *new Noesis::ObservableCollection<NRequiredItem>();\r\n\tm_bitmapSource = BitmapImage::Create( gbi.iconWidth, gbi.iconHeight, 96, 96, gbi.buffer.data(), gbi.iconWidth * 4, BitmapSource::Format::Format_RGBA8 );\r\n\r\n\tfor( auto ri : gbi.requiredItems )\r\n\t{\r\n\t\tauto item = MakePtr<NRequiredItem>( ri.itemID, ri.amount, ri.availableMats );\r\n\t\tm_requiredItems->Add( item );\r\n\t}\r\n}\r\n\r\nconst char* BuildItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nQString BuildItem::sid() const\r\n{\r\n\treturn m_sid;\r\n}\r\n\r\nNoesis::ObservableCollection<NRequiredItem>* BuildItem::requiredItems() const\r\n{\r\n\treturn m_requiredItems;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* BuildItem::GetCmdBuild() const\r\n{\r\n\treturn &m_cmdBuild;\r\n}\r\n\r\nconst char* BuildItem::GetShowReplaceButton() const\r\n{\r\n\tif( m_type == BuildItemType::Terrain )\r\n\t{\r\n\t\tif( m_sid.endsWith( \"Wall\" ) || m_sid.endsWith( \"Floor\" ) || m_sid.startsWith( \"FancyFloor\" ) ||  m_sid.startsWith( \"FancyWall\" ) )\r\n\t\t{\r\n\t\t\treturn \"Visible\";\r\n\t\t}\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* BuildItem::GetShowFillHoleButton() const\r\n{\r\n\tif( m_type == BuildItemType::Terrain )\r\n\t{\r\n\t\tif( m_sid.endsWith( \"Wall\" ) || m_sid.startsWith( \"FancyWall\" ) )\r\n\t\t{\r\n\t\t\treturn \"Visible\";\r\n\t\t}\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst ImageSource* BuildItem::getBitmapSource() const\r\n{\r\n\treturn m_bitmapSource;\r\n}\r\n\r\nvoid BuildItem::onCmdBuild( BaseComponent* param )\r\n{\r\n\tQStringList mats;\r\n\tfor ( int i = 0; i < m_requiredItems->Count(); ++i )\r\n\t{\r\n\t\tauto item = m_requiredItems->Get( i );\r\n\t\tauto mat  = item->GetSelectedMaterial();\r\n\t\tmats.append( mat->sid() );\r\n\t}\r\n\tQString qParam;\r\n\tif( param )\r\n\t{\r\n\t\tqParam = param->ToString().Str();\r\n\t}\r\n\r\n\tm_proxy->requestCmdBuild( m_type, qParam, m_sid, mats );\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNRequiredItem::NRequiredItem( QString sid, int amount, const QList<QPair<QString, int>>& mats )\r\n{\r\n\t_name   = S::s( \"$ItemName_\" + sid ).toStdString().c_str();\r\n\t_sid    = sid;\r\n\t_amount = QString::number( amount ).toStdString().c_str();\r\n\r\n\t_availableMaterials = *new Noesis::ObservableCollection<AvailableMaterial>();\r\n\r\n\tfor( auto mat : mats )\r\n\t{\r\n\t\t_availableMaterials->Add( MakePtr<AvailableMaterial>( mat.first, mat.second, _sid ) );\r\n\t}\r\n\r\n\tSetSelectedMaterial( _availableMaterials->Get( 0 ) );\r\n}\r\n\r\nNRequiredItem::NRequiredItem( QString sid, int amount )\r\n{\r\n\t_name   = S::s( \"$ItemName_\" + sid ).toStdString().c_str();\r\n\t_sid    = sid;\r\n\t_amount = QString::number( amount ).toStdString().c_str();\r\n\t_availableMaterials = *new Noesis::ObservableCollection<AvailableMaterial>();\r\n}\r\n\r\nconst char* NRequiredItem::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst QString NRequiredItem::sid()\r\n{\r\n\treturn _sid;\r\n}\r\n\r\nconst char* NRequiredItem::amount() const\r\n{\r\n\treturn _amount.Str();\r\n}\r\n\r\nNoesis::ObservableCollection<AvailableMaterial>* NRequiredItem::availableMaterials() const\r\n{\r\n\treturn _availableMaterials;\r\n}\r\n\r\nvoid NRequiredItem::SetSelectedMaterial( AvailableMaterial* mat )\r\n{\r\n\tif ( _selectedMaterial != mat )\r\n\t{\r\n\t\t_selectedMaterial = mat;\r\n\t\tOnPropertyChanged( \"SelectedMaterial\" );\r\n\t}\r\n}\r\n\r\nAvailableMaterial* NRequiredItem::GetSelectedMaterial() const\r\n{\r\n\treturn _selectedMaterial;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAvailableMaterial::AvailableMaterial( QString sid, int amount, QString item )\r\n{\r\n\t_name   = ( S::s( \"$MaterialName_\" + sid ) + \" \" + S::s( \"$ItemName_\" + item ) ).toStdString().c_str();\r\n\t_sid    = sid.toStdString().c_str();\r\n\t_amount = QString::number( amount ).toStdString().c_str();\r\n}\r\n\r\nconst char* AvailableMaterial::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst char* AvailableMaterial::sid() const\r\n{\r\n\treturn _sid.Str();\r\n}\r\n\r\nconst char* AvailableMaterial::amount() const\r\n{\r\n\treturn _amount.Str();\r\n}\r\n#pragma endregion Buttons\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nGameModel::GameModel()\r\n{\r\n\t_cmdButtonCommand.SetExecuteFunc( MakeDelegate( this, &GameModel::OnCmdButtonCommand ) );\r\n\t_cmdCategory.SetExecuteFunc( MakeDelegate( this, &GameModel::OnCmdCategory ) );\r\n\r\n\t_cmdLeftCommandButton.SetExecuteFunc( MakeDelegate( this, &GameModel::CmdLeftCommandButton ) );\r\n\t_cmdRightCommandButton.SetExecuteFunc( MakeDelegate( this, &GameModel::CmdRightCommandButton ) );\r\n\t_cmdSimple.SetExecuteFunc( MakeDelegate( this, &GameModel::OnCmdSimple ) );\r\n\r\n\tm_closeWindowCmd.SetExecuteFunc( MakeDelegate( this, &GameModel::onCloseWindowCmd ) );\r\n\tm_openGnomeDetailsCmd.SetExecuteFunc( MakeDelegate( this, &GameModel::onOpenGnomeDetailsCmd ) );\r\n\r\n\tm_messageButtonCmd.SetExecuteFunc( MakeDelegate( this, &GameModel::onMessageButtonCmd ) );\r\n\r\n\tm_messageHeader = \"Message header\";\r\n\tm_messageText = \"Message text Message text Message text Message text Message text Message text Message text Message text Message text Message text Message text Message text Message text\";\r\n\r\n\tm_proxy = new ProxyGameView;\r\n\tm_proxy->setParent( this );\r\n\r\n\t\r\n\r\n\t_commandButtons = *new ObservableCollection<CommandButton>();\r\n\t_buildButtons   = *new ObservableCollection<BuildButton>();\r\n\t_buildItems     = *new ObservableCollection<BuildItem>();\r\n\tm_watchList\t\t= *new Noesis::ObservableCollection<GameItem>();\r\n\r\n\tm_year  = \"*Year*\";\r\n\tm_day   = \"*Day*\";\r\n\tm_time  = \"*Time*\";\r\n\tm_level = \"*Level*\";\r\n\r\n\tm_kingdomName = \"*Kingdom Name*\";\r\n\r\n\tsetShowTileInfo( 0 );\r\n}\r\n\r\nvoid GameModel::updateKingdomInfo( QString name, QString info1, QString info2, QString info3 )\r\n{\r\n\tm_kingdomName = name.toStdString().c_str();\r\n\tm_kingdomInfo1 = info1.toStdString().c_str();\r\n\tm_kingdomInfo2 = info2.toStdString().c_str();\r\n\tm_kingdomInfo3 = info3.toStdString().c_str();\r\n\tOnPropertyChanged( \"KingdomName\" );\r\n\tOnPropertyChanged( \"KingdomInfo1\" );\r\n\tOnPropertyChanged( \"KingdomInfo2\" );\r\n\tOnPropertyChanged( \"KingdomInfo3\" );\r\n}\r\n\r\nvoid GameModel::setTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus )\r\n{\r\n\t{\r\n\t\tconst auto tmp = ( \"Year \" + QString::number( year ) ).toStdString();\r\n\t\tif ( tmp.compare( m_year.Str() ) != 0 )\r\n\t\t{\r\n\t\t\tm_year = tmp.c_str();\r\n\t\t\tOnPropertyChanged( \"Year\" );\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tQString dayString;\r\n\r\n\t\tswitch ( day )\r\n\t\t{\r\n\t\t\tcase 1:\r\n\t\t\t\tdayString = \"1st day of \";\r\n\t\t\t\tbreak;\r\n\t\t\tcase 2:\r\n\t\t\t\tdayString = \"2nd day of \";\r\n\t\t\t\tbreak;\r\n\t\t\tcase 3:\r\n\t\t\t\tdayString = \"3rd day of \";\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tdayString = QString::number( day ) + \"th day of \";\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tconst auto tmp = ( dayString + season ).toStdString();\r\n\t\tif ( tmp.compare( m_year.Str() ) != 0 )\r\n\t\t{\r\n\t\t\tm_day = tmp.c_str();\r\n\t\t\tOnPropertyChanged( \"Day\" );\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tm_time = ( QString( \"%1\" ).arg( hour, 2, 10, QChar( '0' ) ) + \":\" + QString( \"%1\" ).arg( minute, 2, 10, QChar( '0' ) ) ).toStdString().c_str();\r\n\t\tOnPropertyChanged( \"Time\" );\r\n\t}\r\n\r\n\t{\r\n\t\tconst auto tmp = sunStatus.toStdString();\r\n\t\tif ( tmp.compare( m_sun.Str() ) != 0 )\r\n\t\t{\r\n\t\t\tm_sun = tmp.c_str();\r\n\t\t\tOnPropertyChanged( \"Sun\" );\r\n\t\t}\r\n\t}\r\n\r\n\t{\r\n\t\tQString path = \"Images/clock/\";\r\n\t\tif ( season == \"Spring\" )\r\n\t\t\tpath += \"s\";\r\n\t\telse if ( season == \"Summer\" )\r\n\t\t\tpath += \"u\";\r\n\t\telse if ( season == \"Autumn\" )\r\n\t\t\tpath += \"v\";\r\n\t\telse\r\n\t\t\tpath += \"w\";\r\n\r\n\t\thour /= 2;\r\n\t\tpath += QStringLiteral( \"%1\" ).arg( hour, 2, 10, QLatin1Char( '0' ) );\r\n\t\tpath += \".png\";\r\n\r\n\t\tconst auto tmp = path.toStdString();\r\n\t\tif ( tmp.compare( m_timeImagePath.Str() ) != 0 )\r\n\t\t{\r\n\t\t\tm_timeImagePath = tmp.c_str();\r\n\t\t\tOnPropertyChanged( \"TimeImagePath\" );\r\n\t\t}\r\n\t}\r\n\r\n}\r\n\r\nvoid GameModel::setViewLevel( int level )\r\n{\r\n\tm_level = ( \"Level: \" + QString::number( level ) ).toStdString().c_str();\r\n\tOnPropertyChanged( \"Level\" );\r\n}\r\n\r\nvoid GameModel::updatePause( bool paused )\r\n{\r\n\tsetPaused( paused );\r\n}\r\n\r\nvoid GameModel::updateGameSpeed( GameSpeed speed )\r\n{\r\n\tsetGameSpeed( speed );\r\n}\r\n\r\nvoid GameModel::updateRenderOptions( bool designation, bool jobs, bool walls, bool axles )\r\n{\r\n\tsetRenderDesignations( designation );\r\n\tsetRenderJobs( jobs );\r\n\tsetRenderWalls( walls );\r\n\tsetRenderAxles( axles );\r\n}\r\n\r\nvoid GameModel::onBuild()\r\n{\r\n\t//m_selectedButtons = ButtonSelection::None;\r\n\tm_buildSelection = BuildSelection::None;\r\n\t//OnPropertyChanged( \"ShowCommandButtons\" );\r\n\tOnPropertyChanged( \"ShowCategoryButtons\" );\r\n}\r\n\r\nvoid GameModel::onShowTileInfo( unsigned int tileID )\r\n{\r\n\tif ( m_shownInfo == ShownInfo::None || m_shownInfo == ShownInfo::TileInfo )\r\n\t{\r\n\t\tsetShowTileInfo( tileID );\r\n\t}\r\n}\r\n\r\nvoid GameModel::onShowStockpileInfo( unsigned int stockpileID )\r\n{\r\n\tsetShowStockpile( stockpileID );\r\n}\r\n\r\nvoid GameModel::onShowWorkshopInfo( unsigned int workshopID )\r\n{\r\n\tsetShowWorkshop( workshopID );\r\n}\r\n\r\nvoid GameModel::onShowAgriculture( unsigned id )\r\n{\r\n\tsetShowAgriculture( id );\r\n}\r\n\r\nconst char* GameModel::getYear() const\r\n{\r\n\treturn m_year.Str();\r\n}\r\n\r\nconst char* GameModel::getDay() const\r\n{\r\n\treturn m_day.Str();\r\n}\r\n\r\nconst char* GameModel::getTime() const\r\n{\r\n\treturn m_time.Str();\r\n}\r\n\r\nconst char* GameModel::getLevel() const\r\n{\r\n\treturn m_level.Str();\r\n}\r\n\r\nconst char* GameModel::getSun() const\r\n{\r\n\treturn m_sun.Str();\r\n}\r\n\t\r\nconst char* GameModel::getKingdomName() const\r\n{\r\n\treturn m_kingdomName.Str();\r\n}\r\n\r\nconst char* GameModel::getKingdomInfo1() const\r\n{\r\n\treturn m_kingdomInfo1.Str();\r\n}\r\n\r\nconst char* GameModel::getKingdomInfo2() const\r\n{\r\n\treturn m_kingdomInfo2.Str();\r\n}\r\n\r\nconst char* GameModel::getKingdomInfo3() const\r\n{\r\n\treturn m_kingdomInfo3.Str();\r\n}\r\n\r\nconst char* GameModel::getTimeImagePath() const\r\n{\r\n\treturn m_timeImagePath.Str();\r\n}\r\n\r\nconst char* GameModel::showCommandButtons() const\r\n{\r\n\tif ( m_selectedButtons != ButtonSelection::None )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* GameModel::showCategoryButtons() const\r\n{\r\n\tif ( m_buildSelection != BuildSelection::None )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* GameModel::getShowTileInfo() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::TileInfo && m_tileInfoID != 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowTileInfo( unsigned int tileID )\r\n{\r\n\tif ( m_shownInfo != ShownInfo::TileInfo || m_tileInfoID != tileID )\r\n\t{\r\n\t\tif ( tileID == 0 )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::None );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::TileInfo );\r\n\t\t\tm_prevTileInfoID = tileID;\r\n\t\t}\r\n\t\tm_tileInfoID = tileID;\r\n\t\tOnPropertyChanged( \"ShowTileInfo\" );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowStockpile() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Stockpile && m_stockpileID != 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowStockpile( unsigned int stockpileID )\r\n{\r\n\tif ( m_shownInfo != ShownInfo::Stockpile || m_stockpileID != stockpileID )\r\n\t{\r\n\t\tif ( stockpileID == 0 )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::None );\r\n\t\t\tm_proxy->closeStockpileWindow();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsetShowTileInfo( 0 );\r\n\t\t\tsetShownInfo( ShownInfo::Stockpile );\r\n\t\t}\r\n\t\tm_stockpileID = stockpileID;\r\n\t\tOnPropertyChanged( \"ShowStockpile\" );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowAgriculture() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Agriculture && m_agricultureID != 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowAgriculture( unsigned int id )\r\n{\r\n\tif ( m_shownInfo != ShownInfo::Agriculture || m_agricultureID != id )\r\n\t{\r\n\t\tif ( id == 0 )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::None );\r\n\t\t\tm_proxy->closeAgricultureWindow();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsetShowTileInfo( 0 );\r\n\t\t\tsetShownInfo( ShownInfo::Agriculture );\r\n\t\t}\r\n\t\tm_agricultureID = id;\r\n\t\tOnPropertyChanged( \"ShowAgriculture\" );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowWorkshop() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Workshop && m_workshopID != 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowWorkshop( unsigned int workshopID )\r\n{\r\n\tif ( m_shownInfo != ShownInfo::Workshop || m_workshopID != workshopID )\r\n\t{\r\n\t\tif ( workshopID == 0 )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::None );\r\n\t\t\tm_proxy->closeWorkshopWindow();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tsetShowTileInfo( 0 );\r\n\t\t\tsetShownInfo( ShownInfo::Workshop );\r\n\t\t}\r\n\t\tm_workshopID = workshopID;\r\n\t\tOnPropertyChanged( \"ShowWorkshop\" );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowPopulation() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Population )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nvoid GameModel::setShowPopulation( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tif( m_shownInfo != ShownInfo::Population )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::Population );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetShownInfo( ShownInfo::None );\r\n\t}\r\n}\r\n\r\n\t\r\nconst char* GameModel::getShowDebug() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Debug )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowDebug( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tif( m_shownInfo != ShownInfo::Debug )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::Debug );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetShownInfo( ShownInfo::None );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowNeighbors() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Neighbors )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowNeighbors( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tif( m_shownInfo != ShownInfo::Neighbors )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::Neighbors );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetShownInfo( ShownInfo::None );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowMilitary() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Military )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowMilitary( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tif( m_shownInfo != ShownInfo::Military )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::Military );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetShownInfo( ShownInfo::None );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowInventory() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::Inventory )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShowInventory( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tif( m_shownInfo != ShownInfo::Inventory )\r\n\t\t{\r\n\t\t\tsetShownInfo( ShownInfo::Inventory );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tsetShownInfo( ShownInfo::None );\r\n\t}\r\n}\r\n\r\n\r\n\r\nvoid GameModel::setGameSpeed( GameSpeed value )\r\n{\r\n\tif( m_showMessageWindow )\r\n\t{\r\n\t\tm_proxy->setPaused( true );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif ( m_gameSpeed != value )\r\n\t\t{\r\n\t\t\tm_proxy->setGameSpeed( value );\r\n\t\t}\r\n\t\tm_proxy->setPaused( false );\r\n\t}\r\n\tm_gameSpeed = value;\r\n\r\n\tOnPropertyChanged( \"Paused\" );\r\n\tOnPropertyChanged( \"NormalSpeed\" );\r\n\tOnPropertyChanged( \"FastSpeed\" );\r\n}\r\n\r\nbool GameModel::getPaused() const\r\n{\r\n\treturn m_paused;\r\n}\r\n\r\nvoid GameModel::setPaused( bool value )\r\n{\r\n\tif( m_showMessageWindow && !value )\r\n\t{\r\n\t\treturn;\r\n\t}\r\n\tm_paused = value;\r\n\tm_proxy->setPaused( value );\r\n\tOnPropertyChanged( \"Paused\" );\r\n\tOnPropertyChanged( \"NormalSpeed\" );\r\n\tOnPropertyChanged( \"FastSpeed\" );\r\n}\r\n\r\nbool GameModel::getNormalSpeed() const\r\n{\r\n\treturn ( m_gameSpeed == GameSpeed::Normal && !m_paused );\r\n}\r\n\r\nvoid GameModel::setNormalSpeed( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tsetGameSpeed( GameSpeed::Normal );\r\n\t}\r\n}\r\n\r\nbool GameModel::getFastSpeed() const\r\n{\r\n\treturn ( m_gameSpeed == GameSpeed::Fast && !m_paused );\r\n}\r\n\r\nvoid GameModel::setFastSpeed( bool value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tsetGameSpeed( GameSpeed::Fast );\r\n\t}\r\n}\r\n\r\nbool GameModel::getRenderDesignations() const\r\n{\r\n\treturn m_renderDesignations;\r\n}\r\nvoid GameModel::setRenderDesignations( bool value )\r\n{\r\n\tif( m_renderDesignations != value )\r\n\t{\r\n\t\tm_renderDesignations = value;\r\n\t\tm_proxy->setRenderOptions( m_renderDesignations, m_renderJobs, m_wallsLowered, m_renderAxles );\r\n\t\tOnPropertyChanged( \"RenderDesignations\" );\r\n\t}\r\n}\r\nbool GameModel::getRenderJobs() const\r\n{\r\n\treturn m_renderJobs;\r\n}\r\nvoid GameModel::setRenderJobs( bool value )\r\n{\r\n\tif( m_renderJobs != value )\r\n\t{\r\n\t\tm_renderJobs = value;\r\n\t\tm_proxy->setRenderOptions( m_renderDesignations, m_renderJobs, m_wallsLowered, m_renderAxles );\r\n\t\tOnPropertyChanged( \"RenderJobs\" );\r\n\t}\r\n}\r\nbool GameModel::getRenderWalls() const\r\n{\r\n\treturn m_wallsLowered;\r\n}\r\nvoid GameModel::setRenderWalls( bool value )\r\n{\r\n\tif( m_wallsLowered != value )\r\n\t{\r\n\t\tm_wallsLowered = value;\r\n\t\tm_proxy->setRenderOptions( m_renderDesignations, m_renderJobs, m_wallsLowered, m_renderAxles );\r\n\t\tOnPropertyChanged( \"RenderWalls\" );\r\n\t}\r\n}\r\nbool GameModel::getRenderAxles() const\r\n{\r\n\treturn m_renderAxles;\r\n}\r\nvoid GameModel::setRenderAxles( bool value )\r\n{\r\n\tif( m_renderAxles != value )\r\n\t{\r\n\t\tm_renderAxles = value;\r\n\t\tm_proxy->setRenderOptions( m_renderDesignations, m_renderJobs, m_wallsLowered, m_renderAxles );\r\n\t\tOnPropertyChanged( \"RenderWalls\" );\r\n\t}\r\n}\r\n\r\nvoid GameModel::OnCmdCategory( BaseComponent* param )\r\n{\r\n\tsetCategory( param->ToString().Str() );\r\n}\r\n\r\nvoid GameModel::setCategory( const char* cats )\r\n{\r\n\tQString cat( cats );\r\n\tm_proxy->requestBuildItems( m_buildSelection, cat );\r\n}\r\n\r\nvoid GameModel::updateBuildItems( const QList<GuiBuildItem>& items )\r\n{\r\n\t_buildItems->Clear();\r\n\r\n\tfor( const auto& item : items )\r\n\t{\r\n\t\t_buildItems->Add( MakePtr<BuildItem>( item, m_proxy ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"BuildItems\" );\r\n}\r\n\r\nvoid GameModel::OnCmdButtonCommand( BaseComponent* param )\r\n{\r\n\tQString cmd( param->ToString().Str() );\r\n\r\n\tswitch ( m_selectedButtons )\r\n\t{\r\n\t\tcase ButtonSelection::Build:\r\n\t\t\tif ( cmd == \"Deconstruct\" )\r\n\t\t\t{\r\n\t\t\t\tm_buildSelection = BuildSelection::None;\r\n\t\t\t\tOnPropertyChanged( \"BuildButtons\" );\r\n\t\t\t\tOnPropertyChanged( \"ShowCategoryButtons\" );\r\n\t\t\t\tOnCmdSimple( param );\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::Mine:\r\n\t\tcase ButtonSelection::Agriculture:\r\n\t\tcase ButtonSelection::Designation:\r\n\t\tcase ButtonSelection::Job:\r\n\t\tcase ButtonSelection::Magic:\r\n\t\t\tOnCmdSimple( param );\r\n\t\t\treturn;\r\n\t\tcase ButtonSelection::None:\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tBuildSelection bs = BuildSelection::None;\r\n\tif ( cmd == \"Workshop\" )\r\n\t\tbs = BuildSelection::Workshop;\r\n\telse if ( cmd == \"Wall\" )\r\n\t\tbs = BuildSelection::Wall;\r\n\telse if ( cmd == \"Floor\" )\r\n\t\tbs = BuildSelection::Floor;\r\n\telse if ( cmd == \"Stairs\" )\r\n\t\tbs = BuildSelection::Stairs;\r\n\telse if ( cmd == \"Containers\" )\r\n\t\tbs = BuildSelection::Containers;\r\n\telse if ( cmd == \"Ramp\" )\r\n\t\tbs = BuildSelection::Ramps;\r\n\telse if ( cmd == \"Fence\" )\r\n\t\tbs = BuildSelection::Fence;\r\n\telse if ( cmd == \"Furniture\" )\r\n\t\tbs = BuildSelection::Furniture;\r\n\telse if ( cmd == \"Utility\" )\r\n\t\tbs = BuildSelection::Utility;\r\n\r\n\tif ( bs == m_buildSelection )\r\n\t{\r\n\t\tm_buildSelection = BuildSelection::None;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_buildSelection = bs;\r\n\t}\r\n\r\n\t_buildButtons->Clear();\r\n\r\n\tswitch ( m_buildSelection )\r\n\t{\r\n\t\tcase BuildSelection::Wall:\r\n\t\tcase BuildSelection::Floor:\r\n\t\tcase BuildSelection::Stairs:\r\n\t\tcase BuildSelection::Ramps:\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Wood\", \"Wood\", \"buttons/wood.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Soil\", \"Soil\", \"buttons/build-all.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Stone\", \"Stone\", \"buttons/stone.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Metal\", \"Metal\", \"buttons/metal.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Other\", \"Other\", \"buttons/build-all.png\" ) );\r\n\t\t\tsetCategory( \"Wood\" );\r\n\t\t\tbreak;\r\n\t\tcase BuildSelection::Fence:\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Wood\", \"Wood\", \"buttons/wood.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Stone\", \"Stone\", \"buttons/stone.png\" ) );\r\n\t\t\tsetCategory( \"Wood\" );\r\n\t\t\tbreak;\r\n\r\n\t\tcase BuildSelection::Workshop:\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Wood\", \"Wood\", \"buttons/woodwork.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Stone\", \"Stone\", \"buttons/stonework.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Metal\", \"Metal\", \"buttons/metalwork.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Food\", \"Food\", \"buttons/food.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Crafts\", \"Craft\", \"buttons/crafts.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Mechanics\", \"Mechanics\", \"buttons/mechanics.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Misc\", \"Misc\", \"buttons/crafts.png\" ) );\r\n\t\t\tsetCategory( \"Wood\" );\r\n\t\t\tbreak;\r\n\t\tcase BuildSelection::Containers:\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"All\", \"Containers\", \"buttons/stockpile.png\" ) );\r\n\t\t\tsetCategory( \"Containers\" );\r\n\t\t\tbreak;\r\n\t\tcase BuildSelection::Furniture:\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Chairs\", \"Chairs\", \"buttons/chair.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Tables\", \"Tables\", \"buttons/table.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Beds\", \"Beds\", \"buttons/bed.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Cabinets\", \"Cabinets\", \"buttons/cabinet.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Misc\", \"Misc\", \"buttons/woodwork.png\" ) );\r\n\t\t\tsetCategory( \"Chairs\" );\r\n\t\t\tbreak;\r\n\t\tcase BuildSelection::Utility:\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Doors\", \"Doors\", \"buttons/door.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Lights\", \"Lights\", \"buttons/light.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Farm\", \"Farm\", \"buttons/farm.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Mechanism\", \"Mechanism\", \"buttons/mechanism.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Hydraulics\", \"Hydraulics\", \"buttons/hydro.png\" ) );\r\n\t\t\t_buildButtons->Add( MakePtr<BuildButton>( \"Other\", \"Other\", \"buttons/woodwork.png\" ) );\r\n\t\t\tsetCategory( \"Doors\" );\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tOnPropertyChanged( \"BuildButtons\" );\r\n\tOnPropertyChanged( \"ShowCategoryButtons\" );\r\n}\r\n\r\nNoesis::ObservableCollection<CommandButton>* GameModel::GetCommandButtons() const\r\n{\r\n\treturn _commandButtons;\r\n}\r\n\r\nNoesis::ObservableCollection<BuildButton>* GameModel::GetBuildButtons() const\r\n{\r\n\treturn _buildButtons;\r\n}\r\n\r\nNoesis::ObservableCollection<BuildItem>* GameModel::GetBuildItems() const\r\n{\r\n\treturn _buildItems;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* GameModel::GetCmdButtonCommand() const\r\n{\r\n\treturn &_cmdButtonCommand;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* GameModel::GetCmdCategory() const\r\n{\r\n\treturn &_cmdCategory;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* GameModel::GetSimpleCommand() const\r\n{\r\n\treturn &_cmdSimple;\r\n}\r\n\r\nvoid GameModel::OnCmdBack( BaseComponent* param )\r\n{\r\n\tif ( m_shownInfo != ShownInfo::None && m_shownInfo != ShownInfo::TileInfo )\r\n\t{\r\n\t\tsetShowStockpile( 0 );\r\n\t\tsetShowWorkshop( 0 );\r\n\t\tsetShowAgriculture( 0 );\r\n\t\tsetShowTileInfo( m_prevTileInfoID );\r\n\t\tsetShowPopulation( false );\r\n\t\treturn;\r\n\t}\r\n\telse if ( m_shownInfo == ShownInfo::TileInfo )\r\n\t{\r\n\t\tsetShowStockpile( 0 );\r\n\t\tsetShowWorkshop( 0 );\r\n\t\tsetShowAgriculture( 0 );\r\n\t\tsetShowTileInfo( 0 );\r\n\t\treturn;\r\n\t}\r\n\r\n\tif ( m_buildSelection != BuildSelection::None )\r\n\t{\r\n\t\tm_buildSelection = BuildSelection::None;\r\n\t\tOnPropertyChanged( \"ShowCategoryButtons\" );\r\n\t\treturn;\r\n\t}\r\n\tif ( m_selectedButtons != ButtonSelection::None )\r\n\t{\r\n\t\tm_selectedButtons = ButtonSelection::None;\r\n\t\tOnPropertyChanged( \"ShowCommandButtons\" );\r\n\t\treturn;\r\n\t}\r\n\r\n\tm_proxy->propagateEscape();\r\n}\r\n\r\nvoid GameModel::CmdRightCommandButton( BaseComponent* param )\r\n{\r\n\tQString cmd( param->ToString().Str() );\r\n\t\r\n\tif ( cmd == \"Population\" )\r\n\t{\r\n\t\tsetShowPopulation( true );\r\n\t\tm_proxy->requestPopulationUpdate();\r\n\t}\r\n\telse if ( cmd == \"Kingdom\" )\r\n\t{\r\n\t}\r\n\telse if ( cmd == \"Military\" )\r\n\t{\r\n\t\tsetShowMilitary( true );\r\n\t\tm_proxy->requestMilitaryUpdate();\r\n\t}\r\n\telse if ( cmd == \"Inventory\" )\r\n\t{\r\n\t\tsetShowInventory( true );\r\n\t\tm_proxy->requestInventoryUpdate();\r\n\t}\r\n\telse if ( cmd == \"Missions\" )\r\n\t{\r\n\t\tsetShowNeighbors( true );\r\n\t\tm_proxy->requestNeighborsUpdate();\r\n\t\tm_proxy->requestMissionsUpdate();\r\n\t}\r\n\telse if ( cmd == \"Debug\" )\r\n\t{\r\n\t\tsetShowDebug( true );\r\n\t}\r\n}\r\n\r\nvoid GameModel::CmdLeftCommandButton( BaseComponent* param )\r\n{\r\n\tQString cmd( param->ToString().Str() );\r\n\tButtonSelection bs = ButtonSelection::None;\r\n\tif ( cmd == \"Build\" )\r\n\t\tbs = ButtonSelection::Build;\r\n\telse if ( cmd == \"Mine\" )\r\n\t\tbs = ButtonSelection::Mine;\r\n\telse if ( cmd == \"Agri\" )\r\n\t\tbs = ButtonSelection::Agriculture;\r\n\telse if ( cmd == \"Designation\" )\r\n\t\tbs = ButtonSelection::Designation;\r\n\telse if ( cmd == \"Job\" )\r\n\t\tbs = ButtonSelection::Job;\r\n\telse if ( cmd == \"Magic\" )\r\n\t\tbs = ButtonSelection::Magic;\r\n\r\n\tm_buildSelection = BuildSelection::None;\r\n\r\n\tif ( bs == m_selectedButtons )\r\n\t{\r\n\t\tm_selectedButtons = ButtonSelection::None;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_selectedButtons = bs;\r\n\t}\r\n\r\n\t_commandButtons->Clear();\r\n\tswitch ( m_selectedButtons )\r\n\t{\r\n\t\tcase ButtonSelection::Build:\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Workshop\", \"Workshop\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Wall\", \"Wall\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Floor\", \"Floor\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Stairs\", \"Stairs\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Ramp\", \"Ramp\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Fence\", \"Fence\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Containers\", \"Containers\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Furniture\", \"Furniture\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Utilities\", \"Utility\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Deconstruct\", \"Deconstruct\" ) );\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::Mine:\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Mine\", \"Mine\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Explorative Mine\", \"ExplorativeMine\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Remove floor\", \"RemoveFloor\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Stairs down\", \"DigStairsDown\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Stairs up\", \"MineStairsUp\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Ramp\", \"DigRampDown\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Hole\", \"DigHole\" ) );\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::Agriculture:\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Cut tree\", \"FellTree\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Plant tree\", \"\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Harvest tree\", \"HarvestTree\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Forage\", \"Forage\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Remove plant\", \"RemovePlant\" ) );\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::Designation:\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Stockpile\", \"CreateStockpile\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Farm\", \"CreateFarm\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Grove\", \"CreateGrove\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Pasture\", \"CreatePasture\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Personal Room\", \"CreateRoom\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Dormitory\", \"CreateDorm\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Dining Hall\", \"CreateDining\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Hospital\", \"CreateHospital\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Forbidden\", \"CreateNoPass\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Guard\", \"CreateGuardArea\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Remove\", \"RemoveDesignation\" ) );\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::Job:\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Suspend\", \"SuspendJob\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Resume\", \"ResumeJob\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Cancel\", \"CancelJob\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Lower priority\", \"LowerPrio\" ) );\r\n\t\t\t_commandButtons->Add( MakePtr<CommandButton>( \"Raise priority\", \"RaisePrio\" ) );\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::Magic:\r\n\t\t\tbreak;\r\n\t\tcase ButtonSelection::None:\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tOnPropertyChanged( \"ShowCommandButtons\" );\r\n\tOnPropertyChanged( \"ShowCategoryButtons\" );\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* GameModel::GetCmdLeftCommandButton() const\r\n{\r\n\treturn &_cmdLeftCommandButton;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* GameModel::GetCmdRightCommandButton() const\r\n{\r\n\treturn &_cmdRightCommandButton;\r\n}\r\n\r\n\r\nvoid GameModel::OnCmdSimple( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tm_proxy->setSelectionAction( param->ToString().Str() );\r\n\t}\r\n}\r\n\r\nvoid GameModel::onCloseWindowCmd( BaseComponent* param )\r\n{\r\n\tsetShownInfo( ShownInfo::None );\r\n}\r\n\r\nvoid GameModel::onOpenGnomeDetailsCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qParam( param->ToString().Str() );\r\n\t\tm_proxy->requestCreatureUpdate( qParam.toUInt() );\r\n\t\tsetShownInfo( ShownInfo::CreatureInfo );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowCreatureInfo() const\r\n{\r\n\tif ( m_shownInfo == ShownInfo::CreatureInfo )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid GameModel::setShownInfo( ShownInfo info )\r\n{\r\n\tm_shownInfo = info;\r\n\r\n\tif( m_shownInfo != ShownInfo::CreatureInfo )\r\n\t{\r\n\t\tm_proxy->requestCreatureUpdate( 0 );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"ShowPopulation\" );\r\n\tOnPropertyChanged( \"ShowWorkshop\" );\r\n\tOnPropertyChanged( \"ShowAgriculture\" );\r\n\tOnPropertyChanged( \"ShowStockpile\" );\r\n\tOnPropertyChanged( \"ShowTileInfo\" );\r\n\tOnPropertyChanged( \"ShowCreatureInfo\" );\r\n\tOnPropertyChanged( \"ShowDebug\" );\r\n\tOnPropertyChanged( \"ShowNeighbors\" );\r\n\tOnPropertyChanged( \"ShowMilitary\" );\r\n\tOnPropertyChanged( \"ShowInventory\" );\r\n\t\r\n\tOnPropertyChanged( \"ShowMessage\" );\r\n}\r\n\r\n\r\nconst char* GameModel::getShowMessage() const\r\n{\r\n\tif( m_showMessageWindow && m_shownInfo == ShownInfo::None )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* GameModel::getShowMessageButtonOk() const\r\n{\r\n\tif( m_showMessageButtonOk )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nconst char* GameModel::getShowMessageButtonYesNo() const\r\n{\r\n\tif( m_showMessageButtonYesNo )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* GameModel::getMessageHeader() const\r\n{\r\n\treturn m_messageHeader.Str();\r\n}\r\n\r\nconst char* GameModel::getMessageText() const\r\n{\r\n\treturn m_messageText.Str();\r\n}\r\n\r\nvoid GameModel::onMessageButtonCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qParam = param->ToString().Str();\r\n\t\tif( qParam != \"ok\" )\r\n\t\t{\r\n\t\t\tm_proxy->sendEventAnswer( m_messageID, qParam == \"yes\" );\r\n\t\t}\r\n\t\tm_showMessageWindow = false;\r\n\t\tif( !m_messageQueue.isEmpty() )\r\n\t\t{\r\n\t\t\tauto gme = m_messageQueue.takeFirst();\r\n\t\t\teventMessage( gme.id, gme.title, gme.msg, gme.pause, gme.yesno );\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"ShowMessage\" );\r\n}\r\n\r\nvoid GameModel::eventMessage( unsigned int id, QString title, QString msg, bool pause, bool yesno )\r\n{\r\n\tif( m_showMessageWindow )\r\n\t{\r\n\t\tm_messageQueue.append( { id, title, msg, pause, yesno } );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_messageID = id;\r\n\t\tm_messageHeader = title.toStdString().c_str();\r\n\t\tm_messageText = msg.toStdString().c_str();\r\n\t\tm_showMessageWindow = true;\r\n\r\n\t\tm_showMessageButtonOk = !yesno;\r\n\t\tm_showMessageButtonYesNo = yesno;\r\n\r\n\t\tif( pause )\r\n\t\t{\r\n\t\t\tsetPaused( true );\r\n\t\t}\r\n\t\t\r\n\t\tOnPropertyChanged( \"ShowMessageButtonOk\" );\r\n\t\tOnPropertyChanged( \"ShowMessageButtonYesNo\" );\r\n\t\tOnPropertyChanged( \"MessageText\" );\r\n\t\tOnPropertyChanged( \"MessageHeader\" );\r\n\r\n\t\tsetShownInfo( ShownInfo::None );\r\n\t}\r\n}\r\n\r\nconst char* GameModel::getShowSelection() const\r\n{\r\n\tif ( m_showSelection )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nvoid GameModel::setShowSelection( bool value )\r\n{\r\n\tif( m_showSelection != value )\r\n\t{\r\n\t\tm_showSelection = value;\r\n\t\tOnPropertyChanged( \"ShowSelection\" );\r\n\t}\r\n}\r\n\r\nvoid GameModel::updateWatchList( const QList<GuiWatchedItem>& list )\r\n{\r\n\tm_watchList->Clear();\r\n\tfor( const auto& item : list )\r\n\t{\r\n\t\tm_watchList->Add( MakePtr<GameItem>( item.guiString, \"\" ) );\r\n\t}\r\n\tOnPropertyChanged( \"WatchList\" );\r\n}\r\n\r\nNoesis::ObservableCollection<GameItem>* GameModel::GetWatchList() const\r\n{\r\n\treturn m_watchList;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( GameModel, \"IngnomiaGUI.GameModel\" )\r\n{\r\n\tNsProp( \"Paused\", &GameModel::getPaused, &GameModel::setPaused );\r\n\tNsProp( \"NormalSpeed\", &GameModel::getNormalSpeed, &GameModel::setNormalSpeed );\r\n\tNsProp( \"FastSpeed\", &GameModel::getFastSpeed, &GameModel::setFastSpeed );\r\n\r\n\tNsProp( \"Year\", &GameModel::getYear );\r\n\tNsProp( \"Day\", &GameModel::getDay );\r\n\tNsProp( \"Time\", &GameModel::getTime );\r\n\tNsProp( \"Level\", &GameModel::getLevel );\r\n\tNsProp( \"Sun\", &GameModel::getSun );\r\n\tNsProp( \"TimeImagePath\", &GameModel::getTimeImagePath );\r\n\r\n\tNsProp( \"KingdomName\", &GameModel::getKingdomName );\r\n\tNsProp( \"KingdomInfo1\", &GameModel::getKingdomInfo1 );\r\n\tNsProp( \"KingdomInfo2\", &GameModel::getKingdomInfo2 );\r\n\tNsProp( \"KingdomInfo3\", &GameModel::getKingdomInfo3 );\r\n\r\n\tNsProp( \"RenderDesignations\", &GameModel::getRenderDesignations, &GameModel::setRenderDesignations );\r\n\tNsProp( \"RenderJobs\", &GameModel::getRenderJobs, &GameModel::setRenderJobs );\r\n\tNsProp( \"RenderWalls\", &GameModel::getRenderWalls, &GameModel::setRenderWalls );\r\n\tNsProp( \"RenderAxles\", &GameModel::getRenderAxles, &GameModel::setRenderAxles );\r\n\r\n\tNsProp( \"CmdButtonCommand\", &GameModel::GetCmdButtonCommand );\r\n\tNsProp( \"CmdCategory\", &GameModel::GetCmdCategory );\r\n\r\n\tNsProp( \"CmdSimple\", &GameModel::GetSimpleCommand );\r\n\r\n\tNsProp( \"CmdLeftCommandButton\", &GameModel::GetCmdLeftCommandButton );\r\n\tNsProp( \"CmdRightCommandButton\", &GameModel::GetCmdRightCommandButton );\r\n\r\n\tNsProp( \"CommandButtons\", &GameModel::GetCommandButtons );\r\n\tNsProp( \"BuildButtons\", &GameModel::GetBuildButtons );\r\n\tNsProp( \"BuildItems\", &GameModel::GetBuildItems );\r\n\r\n\tNsProp( \"ShowCommandButtons\", &GameModel::showCommandButtons );\r\n\tNsProp( \"ShowCategoryButtons\", &GameModel::showCategoryButtons );\r\n\tNsProp( \"ShowTileInfo\", &GameModel::getShowTileInfo );\r\n\tNsProp( \"ShowStockpile\", &GameModel::getShowStockpile );\r\n\tNsProp( \"ShowWorkshop\", &GameModel::getShowWorkshop );\r\n\tNsProp( \"ShowAgriculture\", &GameModel::getShowAgriculture );\r\n\tNsProp( \"ShowPopulation\", &GameModel::getShowPopulation );\r\n\tNsProp( \"ShowDebug\", &GameModel::getShowDebug );\r\n\tNsProp( \"ShowCreatureInfo\", &GameModel::getShowCreatureInfo );\r\n\tNsProp( \"ShowNeighbors\", &GameModel::getShowNeighbors );\r\n\tNsProp( \"ShowMilitary\", &GameModel::getShowMilitary );\r\n\tNsProp( \"ShowInventory\", &GameModel::getShowInventory );\r\n\tNsProp( \"ShowSelection\", &GameModel::getShowSelection );\r\n\t\r\n\tNsProp( \"ShowMessage\", &GameModel::getShowMessage );\r\n\tNsProp( \"ShowMessageButtonOk\", &GameModel::getShowMessageButtonOk );\r\n\tNsProp( \"ShowMessageButtonYesNo\", &GameModel::getShowMessageButtonYesNo );\r\n\tNsProp( \"MessageHeader\", &GameModel::getMessageHeader );\r\n\tNsProp( \"MessageText\", &GameModel::getMessageText );\r\n\tNsProp( \"MessageCmd\", &GameModel::GetMessageButtonCmd );\r\n\r\n\tNsProp( \"CloseWindowCmd\", &GameModel::GetCloseWindowCmd );\r\n\tNsProp( \"OpenCreatureDetailsCmd\", &GameModel::GetOpenGnomeDetailsCmd );\r\n\r\n\tNsProp( \"WatchList\", &GameModel::GetWatchList );\r\n\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( CommandButton )\r\n{\r\n\tNsProp( \"Name\", &BuildButton::GetName );\r\n\tNsProp( \"ID\", &BuildButton::GetID );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( BuildButton )\r\n{\r\n\tNsProp( \"Name\", &BuildButton::GetName );\r\n\tNsProp( \"ID\", &BuildButton::GetID );\r\n\tNsProp( \"Image\", &BuildButton::GetImage );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( BuildItem )\r\n{\r\n\tNsProp( \"Name\", &BuildItem::GetName );\r\n\tNsProp( \"RequiredItems\", &BuildItem::requiredItems );\r\n\tNsProp( \"Build\", &BuildItem::GetCmdBuild );\r\n\tNsProp( \"ShowReplaceButton\", &BuildItem::GetShowReplaceButton );\r\n\tNsProp( \"ShowFillHoleButton\", &BuildItem::GetShowFillHoleButton );\r\n\tNsProp( \"Image\", &BuildItem::getBitmapSource );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( NRequiredItem )\r\n{\r\n\tNsProp( \"Name\", &NRequiredItem::GetName );\r\n\tNsProp( \"Amount\", &NRequiredItem::amount );\r\n\tNsProp( \"Materials\", &NRequiredItem::availableMaterials );\r\n\tNsProp( \"SelectedMaterial\", &NRequiredItem::GetSelectedMaterial, &NRequiredItem::SetSelectedMaterial );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( AvailableMaterial )\r\n{\r\n\tNsProp( \"Name\", &AvailableMaterial::GetName );\r\n\tNsProp( \"Amount\", &AvailableMaterial::amount );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/GameModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __GameModel_H__\r\n#define __GameModel_H__\r\n\r\n#include \"../../base/enums.h\"\r\n#include \"NewGameModel.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/BitmapImage.h>\r\n#include <NsGui/BitmapSource.h>\r\n#include <NsGui/Button.h>\r\n#include <NsGui/Collection.h>\r\n#include <NsGui/ImageSource.h>\r\n\r\n#include <QString>\r\n\r\nclass ProxyGameView;\r\nstruct GuiBuildItem;\r\nstruct GuiWatchedItem;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass CommandButton final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tCommandButton( QString name, QString sid );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetID() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tNoesis::String _sid;\r\n\r\n\tNS_DECLARE_REFLECTION( CommandButton, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass BuildButton final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tBuildButton( QString name, QString sid, QString image );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetID() const;\r\n\tconst char* GetImage() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tNoesis::String _sid;\r\n\tNoesis::String _image;\r\n\r\n\tNS_DECLARE_REFLECTION( BuildButton, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass AvailableMaterial final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tAvailableMaterial( QString sid, int amount, QString item );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* sid() const;\r\n\tconst char* amount() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tNoesis::String _sid;\r\n\tNoesis::String _amount;\r\n\r\n\tNS_DECLARE_REFLECTION( AvailableMaterial, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass NRequiredItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tNRequiredItem( QString sid, int amount, const QList<QPair<QString, int>>& mats );\r\n\tNRequiredItem( QString sid, int amount );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* amount() const;\r\n\tconst QString sid();\r\n\r\n\tNoesis::ObservableCollection<AvailableMaterial>* availableMaterials() const;\r\n\r\n\tvoid SetSelectedMaterial( AvailableMaterial* mat );\r\n\tAvailableMaterial* GetSelectedMaterial() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tQString _sid;\r\n\tNoesis::String _amount;\r\n\r\n\tAvailableMaterial* _selectedMaterial;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AvailableMaterial>> _availableMaterials;\r\n\r\n\tNS_DECLARE_REFLECTION( NRequiredItem, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass BuildItem final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tBuildItem( const GuiBuildItem& gbi, ProxyGameView* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tQString sid() const;\r\n\tNoesis::ObservableCollection<NRequiredItem>* requiredItems() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tQString m_sid;\r\n\tBuildItemType m_type;\r\n\tProxyGameView* m_proxy = nullptr;\r\n\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapSource;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<NRequiredItem>> m_requiredItems;\r\n\r\n\tconst char* GetShowReplaceButton() const;\r\n\tconst char* GetShowFillHoleButton() const;\r\n\r\n\tvoid onCmdBuild( BaseComponent* param );\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdBuild() const;\r\n\tconst Noesis::ImageSource* getBitmapSource() const;\r\n\r\n\tNoesisApp::DelegateCommand m_cmdBuild;\r\n\r\n\tNS_DECLARE_REFLECTION( BuildItem, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nstruct GuiMessageEvent {\r\n\tunsigned int id;\r\n\tQString title;\r\n\tQString msg;\r\n\tbool pause;\r\n\tbool yesno;\r\n};\r\n\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GameModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGameModel();\r\n\r\n\tvoid setTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus );\r\n\tvoid updateKingdomInfo( QString name, QString info1, QString info2, QString info3 );\r\n\tvoid setViewLevel( int level );\r\n\tvoid updatePause( bool value );\r\n\tvoid updateGameSpeed( GameSpeed speed );\r\n\tvoid updateRenderOptions( bool designation, bool jobs, bool walls, bool axles );\r\n\r\n\tvoid updateBuildItems( const QList<GuiBuildItem>& items );\r\n\tvoid updateWatchList( const QList<GuiWatchedItem>& list );\r\n\r\n\tvoid eventMessage( unsigned int id, QString title, QString msg, bool pause, bool yesno );\r\n\r\n\tvoid onBuild();\r\n\tvoid onShowTileInfo( unsigned tileID );\r\n\tvoid onShowStockpileInfo( unsigned stockpileID );\r\n\tvoid onShowWorkshopInfo( unsigned workshopID );\r\n\tvoid onShowAgriculture( unsigned id );\r\n\r\n\tvoid setShownInfo( ShownInfo info );\r\n\r\n\tvoid OnCmdBack( BaseComponent* param );\r\n\r\nprivate:\r\n\tvoid setGameSpeed( GameSpeed value );\r\n\r\n\tbool getPaused() const;\r\n\tbool getNormalSpeed() const;\r\n\tbool getFastSpeed() const;\r\n\r\n\tvoid setPaused( bool value );\r\n\tvoid setNormalSpeed( bool value );\r\n\tvoid setFastSpeed( bool value );\r\n\r\n\tconst char* getYear() const;\r\n\tconst char* getDay() const;\r\n\tconst char* getTime() const;\r\n\tconst char* getLevel() const;\r\n\tconst char* getSun() const;\r\n\tconst char* getTimeImagePath() const;\r\n\r\n\tconst char* getKingdomName() const;\r\n\tconst char* getKingdomInfo1() const;\r\n\tconst char* getKingdomInfo2() const;\r\n\tconst char* getKingdomInfo3() const;\r\n\r\n\r\n\tbool getRenderDesignations() const;\r\n\tbool getRenderJobs() const;\r\n\tbool getRenderWalls() const;\r\n\tbool getRenderAxles() const;\r\n\r\n\tvoid setRenderJobs( bool value );\r\n\tvoid setRenderDesignations( bool value );\r\n\tvoid setRenderWalls( bool value );\r\n\tvoid setRenderAxles( bool value );\r\n\r\n\tconst char* showCommandButtons() const;\r\n\r\n\tconst char* showCategoryButtons() const;\r\n\r\n\tconst char* getShowTileInfo() const;\r\n\tvoid setShowTileInfo( unsigned int tileID );\r\n\r\n\tconst char* getShowStockpile() const;\r\n\tvoid setShowStockpile( unsigned int stockpileID );\r\n\r\n\tconst char* getShowAgriculture() const;\r\n\tvoid setShowAgriculture( unsigned int id );\r\n\r\n\tconst char* getShowWorkshop() const;\r\n\tvoid setShowWorkshop( unsigned int workshopID );\r\n\r\n\tconst char* getShowPopulation() const;\r\n\tvoid setShowPopulation( bool value );\r\n\r\n\tconst char* getShowDebug() const;\r\n\tvoid setShowDebug( bool value );\r\n\r\n\tconst char* getShowNeighbors() const;\r\n\tvoid setShowNeighbors( bool value );\r\n\r\n\tconst char* getShowMilitary() const;\r\n\tvoid setShowMilitary( bool value );\r\n\r\n\tconst char* getShowInventory() const;\r\n\tvoid setShowInventory( bool value );\r\n\r\n\tconst char* getShowSelection() const;\r\n\tvoid setShowSelection( bool value );\r\n\r\n\tconst char* getShowCreatureInfo() const;\r\n\r\n\tNoesis::ObservableCollection<CommandButton>* GetCommandButtons() const;\r\n\tNoesis::ObservableCollection<BuildButton>* GetBuildButtons() const;\r\n\tNoesis::ObservableCollection<BuildItem>* GetBuildItems() const;\r\n\r\n\tNoesis::ObservableCollection<GameItem>* GetWatchList() const;\r\n\r\n\tvoid OnCmdButtonCommand( BaseComponent* param );\r\n\tvoid OnCmdCategory( BaseComponent* param );\r\n\r\n\tvoid OnCmdSimple( BaseComponent* param );\r\n\r\n\tvoid setCategory( const char* cat );\r\n\r\n\tvoid CmdLeftCommandButton( BaseComponent* param );\r\n\tvoid CmdRightCommandButton( BaseComponent* param );\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdButtonCommand() const;\r\n\tconst NoesisApp::DelegateCommand* GetCmdCategory() const;\r\n\tconst NoesisApp::DelegateCommand* GetSimpleCommand() const;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdLeftCommandButton() const;\r\n\tconst NoesisApp::DelegateCommand* GetCmdRightCommandButton() const;\r\n\r\n\tNoesisApp::DelegateCommand _cmdButtonCommand;\r\n\tNoesisApp::DelegateCommand _cmdCategory;\r\n\tNoesisApp::DelegateCommand _cmdSimple;\r\n\r\n\tNoesisApp::DelegateCommand _cmdLeftCommandButton;\r\n\tNoesisApp::DelegateCommand _cmdRightCommandButton;\r\n\r\nprivate:\r\n\tNoesis::String m_year;\r\n\tNoesis::String m_day;\r\n\tNoesis::String m_time;\r\n\tNoesis::String m_level;\r\n\tNoesis::String m_sun;\r\n\tNoesis::String m_timeImagePath;\r\n\r\n\tNoesis::String m_kingdomName;\r\n\tNoesis::String m_kingdomInfo1;\r\n\tNoesis::String m_kingdomInfo2;\r\n\tNoesis::String m_kingdomInfo3;\r\n\r\n\tbool m_paused = false;\r\n\tGameSpeed m_gameSpeed = GameSpeed::Normal;\r\n\r\n\tbool m_renderDesignations = true;\r\n\tbool m_renderJobs = true;\r\n\tbool m_wallsLowered = false;\r\n\tbool m_renderAxles = false;\r\n\r\n\tProxyGameView* m_proxy = nullptr;\r\n\r\n\tButtonSelection m_selectedButtons = ButtonSelection::None;\r\n\tBuildSelection m_buildSelection   = BuildSelection::None;\r\n\r\n\tShownInfo m_shownInfo         = ShownInfo::None;\r\n\tunsigned int m_tileInfoID     = 0;\r\n\tunsigned int m_prevTileInfoID = 0;\r\n\tunsigned int m_stockpileID    = 0;\r\n\tunsigned int m_workshopID     = 0;\r\n\tunsigned int m_agricultureID  = 0;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<CommandButton>> _commandButtons;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<BuildButton>> _buildButtons;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<BuildItem>> _buildItems;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> m_watchList;\r\n\r\n\tvoid onCloseWindowCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetCloseWindowCmd() const\r\n\t{\r\n\t\treturn &m_closeWindowCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_closeWindowCmd;\r\n\r\n\tvoid onOpenGnomeDetailsCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetOpenGnomeDetailsCmd() const\r\n\t{\r\n\t\treturn &m_openGnomeDetailsCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_openGnomeDetailsCmd;\r\n\r\n\tbool m_showMessageWindow = false;\r\n\tNoesis::String m_messageHeader;\r\n\tNoesis::String m_messageText;\r\n\tbool m_messageRequiresAnswer = false;\r\n\r\n\tconst char* getShowMessage() const;\r\n\tconst char* getShowMessageButtonOk() const;\r\n\tconst char* getShowMessageButtonYesNo() const;\r\n\r\n\tbool m_showMessageButtonOk = false;\r\n\tbool m_showMessageButtonYesNo = false;\r\n\tunsigned int m_messageID = 0;\r\n\r\n\tconst char* getMessageHeader() const;\r\n\tconst char* getMessageText() const;\r\n\r\n\tbool m_showSelection = true;\r\n\r\n\tvoid onMessageButtonCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetMessageButtonCmd() const\r\n\t{\r\n\t\treturn &m_messageButtonCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_messageButtonCmd;\r\n\r\n\tQList<GuiMessageEvent> m_messageQueue;\r\n\r\n\tNS_DECLARE_REFLECTION( GameModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/IngamePage.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"IngamePage.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nIngamePage::IngamePage()\r\n{\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid IngamePage::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"IngamePage.xaml\" );\r\n}\r\n\r\nbool IngamePage::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\t//NS_CONNECT_EVENT( Button, Click, onMMExit_Click );\r\n\t//NS_CONNECT_EVENT( Button, Click, onMMSettings_Click );\r\n\treturn false;\r\n}\r\n\r\n/*\r\nvoid IngamePage::onMMExit_Click( BaseComponent* sender, const RoutedEventArgs& args )\r\n{\r\n\t//emit signalExit();\r\n}\r\n\r\n*/\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::IngamePage, \"IngnomiaGUI.IngamePage\" );\r\n"
  },
  {
    "path": "src/gui/xaml/IngamePage.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __IngamePage_H__\r\n#define __IngamePage_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass IngamePage final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tIngamePage();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tNS_DECLARE_REFLECTION( IngamePage, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/LoadGameModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"LoadGameModel.h\"\r\n\r\n#include \"loadgameproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSaveItem::SaveItem( QString name, QString path, QString dir, QString version, QString date, bool compatible )\r\n{\r\n\t_name       = name.toStdString().c_str();\r\n\t_path       = path.toStdString().c_str();\r\n\t_dir        = dir.toStdString().c_str();\r\n\t_version    = version.toStdString().c_str();\r\n\t_date       = date.toStdString().c_str();\r\n\t_compatible = compatible;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nLoadGameModel::LoadGameModel() :\r\n\t_selectedKingdom( nullptr ),\r\n\t_selectedGame( nullptr )\r\n{\r\n\tm_proxy = new LoadGameProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\t_loadGame.SetExecuteFunc( MakeDelegate( this, &LoadGameModel::OnLoadGame ) );\r\n\r\n\t_savedKingdoms = *new ObservableCollection<SaveItem>();\r\n\t_savedGames    = *new ObservableCollection<SaveItem>();\r\n\r\n\tm_proxy->requestKingdoms();\r\n}\r\n\r\nNoesis::ObservableCollection<SaveItem>* LoadGameModel::GetSavedKingdoms() const\r\n{\r\n\treturn _savedKingdoms;\r\n}\r\n\r\nNoesis::ObservableCollection<SaveItem>* LoadGameModel::GetSavedGames() const\r\n{\r\n\treturn _savedGames;\r\n}\r\n\r\nvoid LoadGameModel::updateSavedKingdoms( const QList<GuiSaveInfo>& kingdoms )\r\n{\r\n\t_savedKingdoms->Clear();\r\n\r\n\tfor ( const auto& gsk : kingdoms )\r\n\t{\r\n\t\t_savedKingdoms->Add( MakePtr<SaveItem>( gsk.name, gsk.folder, \"\", gsk.version, gsk.date.toString() ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"SavedKingdoms\" );\r\n\r\n\tif ( _savedKingdoms->Count() > 0 )\r\n\t{\r\n\t\tSetSelectedKingdom( _savedKingdoms->Get( 0 ) );\r\n\t}\r\n}\r\n\r\nvoid LoadGameModel::updateSaveGames( const QList<GuiSaveInfo>& saveGames )\r\n{\r\n\t_savedGames->Clear();\r\n\r\n\tfor ( const auto& gsi : saveGames )\r\n\t{\r\n\t\t_savedGames->Add( MakePtr<SaveItem>( gsi.name, gsi.folder, gsi.dir, gsi.version, gsi.date.toString(), gsi.compatible ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"SavedGames\" );\r\n\r\n\tif ( _savedGames->Count() > 0 )\r\n\t{\r\n\t\tSetSelectedGame( _savedGames->Get( 0 ) );\r\n\t}\r\n}\r\n\r\nvoid LoadGameModel::SetSelectedKingdom( SaveItem* item )\r\n{\r\n\tif ( _selectedKingdom != item )\r\n\t{\r\n\t\t_selectedKingdom = item;\r\n\t\tOnPropertyChanged( \"SelectedKingdom\" );\r\n\r\n\t\tif ( item )\r\n\t\t{\r\n\t\t\tm_proxy->requestSaveGames( item->_path.Str() );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nSaveItem* LoadGameModel::GetSelectedKingdom() const\r\n{\r\n\treturn _selectedKingdom;\r\n}\r\n\r\nvoid LoadGameModel::SetSelectedGame( SaveItem* item )\r\n{\r\n\tif ( _selectedGame != item )\r\n\t{\r\n\t\t_selectedGame = item;\r\n\t\tOnPropertyChanged( \"SelectedGame\" );\r\n\t}\r\n}\r\n\r\nSaveItem* LoadGameModel::GetSelectedGame() const\r\n{\r\n\treturn _selectedGame;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* LoadGameModel::GetLoadGame() const\r\n{\r\n\treturn &_loadGame;\r\n}\r\n\r\nvoid LoadGameModel::OnLoadGame( BaseComponent* param )\r\n{\r\n\tif ( _selectedGame )\r\n\t{\r\n\t\t\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( LoadGameModel, \"IngnomiaGUI.LoadGameModel\" )\r\n{\r\n\tNsProp( \"LoadGame\", &LoadGameModel::GetLoadGame );\r\n\r\n\tNsProp( \"SavedKingdoms\", &LoadGameModel::GetSavedKingdoms );\r\n\tNsProp( \"SavedGames\", &LoadGameModel::GetSavedGames );\r\n\r\n\tNsProp( \"SelectedKingdom\", &LoadGameModel::GetSelectedKingdom, &LoadGameModel::SetSelectedKingdom );\r\n\tNsProp( \"SelectedGame\", &LoadGameModel::GetSelectedGame, &LoadGameModel::SetSelectedGame );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( SaveItem )\r\n{\r\n\tNsProp( \"Name\", &SaveItem::_name );\r\n\tNsProp( \"Path\", &SaveItem::_path );\r\n\tNsProp( \"Dir\", &SaveItem::_dir );\r\n\tNsProp( \"Version\", &SaveItem::_version );\r\n\tNsProp( \"Date\", &SaveItem::_date );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/LoadGameModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __MENU3D_LOADGAMEMODEL_H__\r\n#define __MENU3D_LOADGAMEMODEL_H__\r\n\r\n#include \"../aggregatorloadgame.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\n#include <QString>\r\n\r\nclass LoadGameProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nstruct SaveItem : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tSaveItem( QString name, QString path, QString dir, QString version, QString date, bool compatible = true );\r\n\r\n\tNoesis::String _name;\r\n\tNoesis::String _path;\r\n\tNoesis::String _dir;\r\n\tNoesis::String _version;\r\n\tNoesis::String _date;\r\n\tbool _compatible;\r\n\r\n\tNS_DECLARE_REFLECTION( SaveItem, BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass LoadGameModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tLoadGameModel();\r\n\r\n\tvoid updateSavedKingdoms( const QList<GuiSaveInfo>& kingdoms );\r\n\tvoid updateSaveGames( const QList<GuiSaveInfo>& kingdoms );\r\n\r\nprivate:\r\n\tLoadGameProxy* m_proxy = nullptr;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetLoadGame() const;\r\n\r\n\tvoid OnLoadGame( BaseComponent* param );\r\n\r\n\tNoesis::ObservableCollection<SaveItem>* GetSavedKingdoms() const;\r\n\tSaveItem* _selectedKingdom;\r\n\r\n\tNoesis::ObservableCollection<SaveItem>* GetSavedGames() const;\r\n\tSaveItem* _selectedGame;\r\n\r\n\tvoid SetSelectedKingdom( SaveItem* item );\r\n\tSaveItem* GetSelectedKingdom() const;\r\n\tvoid SetSelectedGame( SaveItem* item );\r\n\tSaveItem* GetSelectedGame() const;\r\n\r\n\tNoesisApp::DelegateCommand _loadGame;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<SaveItem>> _savedKingdoms;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<SaveItem>> _savedGames;\r\n\r\n\tNS_DECLARE_REFLECTION( LoadGameModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/LoadGamePage.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"LoadGamePage.xaml.h\"\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nLoadGamePage::LoadGamePage()\r\n{\r\n\tLoaded() += MakeDelegate( this, &LoadGamePage::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid LoadGamePage::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"LoadGamePage.xaml\" );\r\n}\r\n\r\nbool LoadGamePage::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\t//NS_CONNECT_EVENT( Button, Click, onBack_Click );\r\n\treturn false;\r\n}\r\n\r\nvoid LoadGamePage::onBack_Click( BaseComponent* sender, const RoutedEventArgs& args )\r\n{\r\n}\r\n\r\nvoid LoadGamePage::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::LoadGamePage, \"IngnomiaGUI.LoadGamePage\" )\r\n"
  },
  {
    "path": "src/gui/xaml/LoadGamePage.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __LoadGamePage_H__\r\n#define __LoadGamePage_H__\r\n\r\n#include <NoesisPCH.h>\r\n#include <NsGui/RoutedEvent.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass LoadGamePage final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tLoadGamePage();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( Noesis::BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid onBack_Click( Noesis::BaseComponent* sender, const Noesis::RoutedEventArgs& args );\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( LoadGamePage, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/Main.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"Main.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nMain::Main()\r\n{\r\n\tLoaded() += MakeDelegate( this, &Main::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid Main::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"Main.xaml\" );\r\n}\r\n\r\nbool Main::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid Main::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::Main, \"IngnomiaGUI.Main\" )\r\n"
  },
  {
    "path": "src/gui/xaml/Main.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __MAIN_H__\r\n#define __MAIN_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass Main final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tMain();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( Main, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/MainMenu.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"MainMenu.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nMainMenu::MainMenu()\r\n{\r\n\tLoaded() += MakeDelegate( this, &MainMenu::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid MainMenu::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"MainMenu.xaml\" );\r\n}\r\n\r\nbool MainMenu::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid MainMenu::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::MainMenu, \"IngnomiaGUI.MainMenu\" )\r\n"
  },
  {
    "path": "src/gui/xaml/MainMenu.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __MAINMENU_H__\r\n#define __MAINMENU_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass MainMenu final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tMainMenu();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( MainMenu, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/MainPage.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"MainPage.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nMainPage::MainPage()\r\n{\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid MainPage::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"MainPage.xaml\" );\r\n}\r\n\r\nbool MainPage::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\t//NS_CONNECT_EVENT( Button, Click, onMMExit_Click );\r\n\t//NS_CONNECT_EVENT( Button, Click, onMMSettings_Click );\r\n\treturn false;\r\n}\r\n\r\n/*\r\nvoid MainPage::onMMExit_Click( BaseComponent* sender, const RoutedEventArgs& args )\r\n{\r\n\t//emit signalExit();\r\n}\r\n\r\n*/\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::MainPage, \"IngnomiaGUI.MainPage\" )\r\n"
  },
  {
    "path": "src/gui/xaml/MainPage.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __MainPage_H__\r\n#define __MainPage_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass MainPage final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tMainPage();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tNS_DECLARE_REFLECTION( MainPage, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/NewGameModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"NewGameModel.h\"\r\n\r\n#include \"../../base/db.h\"\r\n#include \"../../game/newgamesettings.h\"\r\n\r\n#include \"../eventconnector.h\"\r\n#include \"../strings.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nPreset::Preset( const char* name ) :\r\n\t_name( name )\r\n{\r\n}\r\n\r\nconst char* Preset::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nGameItem::GameItem( QString name, QString sid )\r\n{\r\n\t_name = name.toStdString().c_str();\r\n\t_sid  = sid.toStdString().c_str();\r\n}\r\n\r\nGameItem::GameItem( QString name, QString sid, int amount ) :\r\n\t_name( name.toStdString().c_str() ),\r\n\t_sid( sid.toStdString().c_str() ),\r\n\tm_amount( amount )\r\n{\r\n\tm_amountString = QString::number( amount ).toStdString().c_str();\r\n}\r\n\r\n\r\nconst char* GameItem::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst char* GameItem::sid()\r\n{\r\n\treturn _sid.Str();\r\n}\r\n\t\r\nconst char* GameItem::getAmount() const\r\n{\r\n\treturn m_amountString.Str();\r\n}\r\n\r\nvoid GameItem::setAmount( const char* value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tm_amountString = value;\r\n\t\tif( m_amountString.Size() > 0 )\r\n\t\t{\r\n\t\t\tm_amount = std::stoi( value );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_amount = 0;\r\n\t\t}\r\n\t\tGlobal::newGameSettings->setAmount( _sid.Str(), m_amount );\r\n\r\n\t\tGlobal::newGameSettings->setChecked( _sid.Str(), m_amount != 0 );\r\n\t\t\r\n\t\tOnPropertyChanged( \"IsChecked\" );\r\n\t}\r\n}\r\n\r\nbool GameItem::isChecked() const\r\n{\r\n\treturn Global::newGameSettings->isChecked( _sid.Str() );\r\n}\r\n\r\nvoid GameItem::setChecked( bool value )\r\n{\r\n\tm_amount = value ? -1 : 0;\r\n\tm_amountString = QString::number( m_amount ).toStdString().c_str();\r\n\r\n\tGlobal::newGameSettings->setAmount( _sid.Str(), m_amount );\r\n\tGlobal::newGameSettings->setChecked( _sid.Str(), value );\r\n\r\n\tOnPropertyChanged( \"Amount\" );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nStartItem::StartItem( QString name, QString mat1, QString mat2, int amount )\r\n{\r\n\t_tag = ( name + \"_\" + mat1 + \"_\" + mat2 ).toStdString().c_str();\r\n\r\n\t_name = S::s( \"$ItemName_\" + name ).toStdString().c_str();\r\n\tif ( !mat1.isEmpty() )\r\n\t{\r\n\t\t_mat1 = S::s( \"$MaterialName_\" + mat1 ).toStdString().c_str();\r\n\t}\r\n\tif ( !mat2.isEmpty() )\r\n\t{\r\n\t\t_mat2 = S::s( \"$MaterialName_\" + mat2 ).toStdString().c_str();\r\n\t}\r\n\t_amount = QString::number( amount ).toStdString().c_str();\r\n}\r\n\r\nStartAnimal::StartAnimal( QString type, QString gender, int amount )\r\n{\r\n\t_tag    = ( type + \"_\" + gender ).toStdString().c_str();\r\n\t_type   = S::s( \"$CreatureName_\" + type ).toStdString().c_str();\r\n\t_gender = gender.toStdString().c_str();\r\n\t_amount = QString::number( amount ).toStdString().c_str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNewGameModel::NewGameModel() :\r\n\t_selectedPreset( nullptr ),\r\n\t_selectedItem( nullptr ),\r\n\t_selectedAnimal( nullptr ),\r\n\t_selectedGender( nullptr ),\r\n\t_selectedItemMaterial1( nullptr ),\r\n\t_selectedItemMaterial2( nullptr )\r\n{\r\n\t_randomKingdomName.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnRandomKingdomName ) );\r\n\t_randomSeed.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnRandomSeed ) );\r\n\t_newPreset.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnNewPreset ) );\r\n\t_savePreset.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnSavePreset ) );\r\n\t_deletePreset.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnDeletePreset ) );\r\n\t_addItem.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnAddItem ) );\r\n\t_removeItem.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnRemoveItem ) );\r\n\t_addAnimal.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnAddAnimal ) );\r\n\t_removeAnimal.SetExecuteFunc( MakeDelegate( this, &NewGameModel::OnRemoveAnimal ) );\r\n\r\n\t_startingItems   = *new ObservableCollection<StartItem>();\r\n\t_startingAnimals = *new ObservableCollection<StartAnimal>();\r\n\r\n\t_allowedWildAnimals = *new ObservableCollection<GameItem>();\r\n\t_allowedPlants      = *new ObservableCollection<GameItem>();\r\n\t_allowedTrees       = *new ObservableCollection<GameItem>();\r\n\r\n\t_kingdomName  = Global::newGameSettings->kingdomName().toStdString().c_str();\r\n\t_seed         = Global::newGameSettings->seed().toStdString().c_str();\r\n\t_itemAmount   = \"1\";\r\n\t_animalAmount = \"1\";\r\n\r\n\t_presets = *new ObservableCollection<Preset>();\r\n\tfor ( auto name : Global::newGameSettings->presetNames() )\r\n\t{\r\n\t\t_presets->Add( MakePtr<Preset>( name.toStdString().c_str() ) );\r\n\t}\r\n\tupdateStartingItems();\r\n\tupdateStartingAnimals();\r\n\t//SetSelectedPreset( _presets->Get( 0 ) );\r\n\r\n\t_itemMaterials1 = *new ObservableCollection<GameItem>();\r\n\t_itemMaterials2 = *new ObservableCollection<GameItem>();\r\n\r\n\t_items             = *new ObservableCollection<GameItem>();\r\n\tQStringList diKeys = DB::ids( \"Items\" );\r\n\tdiKeys.sort();\r\n\tfor ( auto key : diKeys )\r\n\t{\r\n\t\t_items->Add( MakePtr<GameItem>( S::s( \"$ItemName_\" + key ), key ) );\r\n\t}\r\n\tSetSelectedItem( _items->Get( 0 ) );\r\n\r\n\t_animals               = *new ObservableCollection<GameItem>();\r\n\tQStringList allAnimals = DB::ids( \"Animals\" );\r\n\tallAnimals.sort();\r\n\tfor ( auto animal : allAnimals )\r\n\t{\r\n\t\tif ( DB::select( \"Pasture\", \"Animals\", animal ).toBool() || DB::select( \"Embark\", \"Animals\", animal ).toBool() )\r\n\t\t{\r\n\t\t\t_animals->Add( MakePtr<GameItem>( S::s( \"$CreatureName_\" + animal ), animal ) );\r\n\t\t}\r\n\t}\r\n\tSetSelectedAnimal( _animals->Get( 0 ) );\r\n\r\n\t_genders = *new ObservableCollection<GameItem>();\r\n\t_genders->Add( MakePtr<GameItem>( \"Male\", \"Male\" ) );\r\n\t_genders->Add( MakePtr<GameItem>( \"Female\", \"Female\" ) );\r\n\tSetSelectedGender( _genders->Get( 0 ) );\r\n\r\n\tfor ( auto vt : Global::newGameSettings->trees() )\r\n\t{\r\n\t\tauto vm = vt.toMap();\r\n\t\tauto gi = MakePtr<GameItem>( vm.value( \"Name\" ).toString(), vm.value( \"ID\" ).toString() );\r\n\t\t//gi->setChecked( vm.value( \"Allowed\" ).toBool() ? true : false );\r\n\t\t_allowedTrees->Add( gi );\r\n\t}\r\n\r\n\tfor ( auto vt : Global::newGameSettings->plants() )\r\n\t{\r\n\t\tauto vm = vt.toMap();\r\n\t\tauto gi = MakePtr<GameItem>( vm.value( \"Name\" ).toString(), vm.value( \"ID\" ).toString() );\r\n\t\t//gi->setChecked( vm.value( \"Allowed\" ).toBool() ? true : false );\r\n\t\t_allowedPlants->Add( gi );\r\n\t}\r\n\r\n\tfor ( auto vt : Global::newGameSettings->animals() )\r\n\t{\r\n\t\tauto vm = vt.toMap();\r\n\t\tauto gi = MakePtr<GameItem>( vm.value( \"Name\" ).toString(), vm.value( \"ID\" ).toString(), vm.value( \"Amount\" ).toInt() );\r\n\t\t_allowedWildAnimals->Add( gi );\r\n\t}\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetRandomKingdomName() const\r\n{\r\n\treturn &_randomKingdomName;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetRandomSeed() const\r\n{\r\n\treturn &_randomSeed;\r\n}\r\nconst DelegateCommand* NewGameModel::GetNewPreset() const\r\n{\r\n\treturn &_newPreset;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetSavePreset() const\r\n{\r\n\treturn &_savePreset;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetDeletePreset() const\r\n{\r\n\treturn &_deletePreset;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetAddItem() const\r\n{\r\n\treturn &_addItem;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetRemoveItem() const\r\n{\r\n\treturn &_removeItem;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetAddAnimal() const\r\n{\r\n\treturn &_addAnimal;\r\n}\r\n\r\nconst DelegateCommand* NewGameModel::GetRemoveAnimal() const\r\n{\r\n\treturn &_removeAnimal;\r\n}\r\n\r\nvoid NewGameModel::OnRandomKingdomName( BaseComponent* param )\r\n{\r\n\tGlobal::newGameSettings->setRandomName();\r\n\t_kingdomName = Global::newGameSettings->kingdomName().toStdString().c_str();\r\n\tOnPropertyChanged( \"KingdomName\" );\r\n}\r\n\r\nvoid NewGameModel::OnRandomSeed( BaseComponent* param )\r\n{\r\n\tGlobal::newGameSettings->setRandomSeed();\r\n\t_seed = Global::newGameSettings->seed().toStdString().c_str();\r\n\tOnPropertyChanged( \"Seed\" );\r\n}\r\n\r\nvoid NewGameModel::OnNewPreset( BaseComponent* param )\r\n{\r\n\tQString newName = Global::newGameSettings->addPreset();\r\n\tif ( !newName.isEmpty() )\r\n\t{\r\n\t\t_presets->Add( MakePtr<Preset>( newName.toStdString().c_str() ) );\r\n\t}\r\n\tSetSelectedPreset( _presets->Get( _presets->Count() - 1 ) );\r\n}\r\n\r\nvoid NewGameModel::OnSavePreset( BaseComponent* param )\r\n{\r\n\tGlobal::newGameSettings->onSavePreset();\r\n}\r\n\r\nvoid NewGameModel::OnDeletePreset( BaseComponent* param )\r\n{\r\n\t//get name from combobox\r\n\tauto name = _selectedPreset->GetName();\r\n\tif ( Global::newGameSettings->removePreset( name ) )\r\n\t{\r\n\t\tSetSelectedPreset( _presets->Get( 0 ) );\r\n\t\tfor ( int i = 0; i < _presets->Count(); ++i )\r\n\t\t{\r\n\t\t\tif ( _presets->Get( i )->GetName() == name )\r\n\t\t\t{\r\n\t\t\t\t_presets->RemoveAt( i );\r\n\t\t\t\tOnPropertyChanged( \"SelectedPreset\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid NewGameModel::OnAddItem( BaseComponent* param )\r\n{\r\n\tQString itemSID;\r\n\tQString mat1;\r\n\tQString mat2;\r\n\tint amount = QString( _itemAmount.Str() ).toInt();\r\n\tif ( _selectedItem )\r\n\t{\r\n\t\titemSID = _selectedItem->sid();\r\n\t}\r\n\tif ( _selectedItemMaterial1 )\r\n\t{\r\n\t\tmat1 = _selectedItemMaterial1->sid();\r\n\t}\r\n\tif ( _selectedItemMaterial2 )\r\n\t{\r\n\t\tmat2 = _selectedItemMaterial2->sid();\r\n\t}\r\n\r\n\tGlobal::newGameSettings->addStartingItem( itemSID, mat1, mat2, amount );\r\n\r\n\tupdateStartingItems();\r\n}\r\nvoid NewGameModel::OnRemoveItem( BaseComponent* param )\r\n{\r\n\tGlobal::newGameSettings->removeStartingItem( param->ToString().Str() );\r\n\tupdateStartingItems();\r\n}\r\n\r\nvoid NewGameModel::OnAddAnimal( BaseComponent* param )\r\n{\r\n\tQString type;\r\n\tQString gender;\r\n\tint amount = QString( _animalAmount.Str() ).toInt();\r\n\tif ( _selectedAnimal )\r\n\t{\r\n\t\ttype = _selectedAnimal->sid();\r\n\t}\r\n\r\n\tif ( _selectedGender )\r\n\t{\r\n\t\tgender = _selectedGender->sid();\r\n\t}\r\n\r\n\tGlobal::newGameSettings->addStartingAnimal( type, gender, amount );\r\n\r\n\tupdateStartingAnimals();\r\n}\r\nvoid NewGameModel::OnRemoveAnimal( BaseComponent* param )\r\n{\r\n\tGlobal::newGameSettings->removeStartingAnimal( param->ToString().Str() );\r\n\tupdateStartingAnimals();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetWorldSize() const\r\n{\r\n\treturn Global::newGameSettings->worldSize();\r\n}\r\nvoid NewGameModel::SetWorldSize( int size )\r\n{\r\n\tif ( Global::newGameSettings->setWorldSize( size ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"WorldSize\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetZLevels() const\r\n{\r\n\treturn Global::newGameSettings->zLevels();\r\n}\r\nvoid NewGameModel::SetZLevels( int value )\r\n{\r\n\tif ( Global::newGameSettings->setZLevels( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"ZLevels\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetGround() const\r\n{\r\n\treturn Global::newGameSettings->ground();\r\n}\r\nvoid NewGameModel::SetGround( int value )\r\n{\r\n\tif ( Global::newGameSettings->setGround( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"Ground\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetFlatness() const\r\n{\r\n\treturn Global::newGameSettings->flatness();\r\n}\r\nvoid NewGameModel::SetFlatness( int value )\r\n{\r\n\tif ( Global::newGameSettings->setFlatness( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"Flatness\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetOceanSize() const\r\n{\r\n\treturn Global::newGameSettings->oceanSize();\r\n}\r\nvoid NewGameModel::SetOceanSize( int value )\r\n{\r\n\tif ( Global::newGameSettings->setOceanSize( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"OceanSize\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetRivers() const\r\n{\r\n\treturn Global::newGameSettings->rivers();\r\n}\r\nvoid NewGameModel::SetRivers( int value )\r\n{\r\n\tif ( Global::newGameSettings->setRivers( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"Rivers\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetRiverSize() const\r\n{\r\n\treturn Global::newGameSettings->riverSize();\r\n}\r\nvoid NewGameModel::SetRiverSize( int value )\r\n{\r\n\tif ( Global::newGameSettings->setRiverSize( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"RiverSize\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetNumGnomes() const\r\n{\r\n\treturn Global::newGameSettings->numGnomes();\r\n}\r\nvoid NewGameModel::SetNumGnomes( int value )\r\n{\r\n\tif ( Global::newGameSettings->setNumGnomes( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"NumGnomes\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetStartZone() const\r\n{\r\n\treturn Global::newGameSettings->startZone();\r\n}\r\nvoid NewGameModel::SetStartZone( int value )\r\n{\r\n\tif ( Global::newGameSettings->setStartZone( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"StartZone\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetTreeDensity() const\r\n{\r\n\treturn Global::newGameSettings->treeDensity();\r\n}\r\nvoid NewGameModel::SetTreeDensity( int value )\r\n{\r\n\tif ( Global::newGameSettings->setTreeDensity( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"TreeDensity\" );\r\n\t}\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetPlantDensity() const\r\n{\r\n\treturn Global::newGameSettings->plantDensity();\r\n}\r\nvoid NewGameModel::SetPlantDensity( int value )\r\n{\r\n\tif ( Global::newGameSettings->setPlantDensity( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"PlantDensity\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst char* NewGameModel::GetKingdomName() const\r\n{\r\n\treturn _kingdomName.Str();\r\n}\r\nvoid NewGameModel::SetKingdomName( const char* value )\r\n{\r\n\tif ( Global::newGameSettings->setKingdomName( value ) )\r\n\t{\r\n\t\t_kingdomName = Global::newGameSettings->kingdomName().toStdString().c_str();\r\n\t\tOnPropertyChanged( \"KingdomName\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst char* NewGameModel::GetSeed() const\r\n{\r\n\treturn _seed.Str();\r\n}\r\nvoid NewGameModel::SetSeed( const char* value )\r\n{\r\n\tif ( Global::newGameSettings->setSeed( value ) )\r\n\t{\r\n\t\t_seed = Global::newGameSettings->seed().toStdString().c_str();\r\n\t\tOnPropertyChanged( \"Seed\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetMaxPerType() const\r\n{\r\n\treturn Global::newGameSettings->globalMaxPerType();\r\n}\r\n\r\nvoid NewGameModel::SetMaxPertype( int value )\r\n{\r\n\tif ( Global::newGameSettings->setMaxPerType( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"MaxPerType\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nint NewGameModel::GetNumWildAnimals() const\r\n{\r\n\treturn Global::newGameSettings->numWildAnimals();\r\n}\r\n\r\nvoid NewGameModel::SetNumWildAnimals( int value )\r\n{\r\n\tif ( Global::newGameSettings->setNumWildAnimals( value ) )\r\n\t{\r\n\t\tOnPropertyChanged( \"NumWildAnimals\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nbool NewGameModel::GetPeaceful() const\r\n{\r\n\treturn Global::newGameSettings->isPeaceful();\r\n}\r\n\r\nvoid NewGameModel::SetPeaceful( bool value )\r\n{\r\n\tGlobal::newGameSettings->setPeaceful( value );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst char* NewGameModel::GetItemAmount() const\r\n{\r\n\treturn _itemAmount.Str();\r\n}\r\nvoid NewGameModel::SetItemAmount( const char* value )\r\n{\r\n\tif ( _itemAmount != value )\r\n\t{\r\n\t\t_itemAmount = value;\r\n\t\tOnPropertyChanged( \"ItemAmount\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst char* NewGameModel::GetAnimalAmount() const\r\n{\r\n\treturn _animalAmount.Str();\r\n}\r\nvoid NewGameModel::SetAnimalAmount( const char* value )\r\n{\r\n\tif ( _animalAmount != value )\r\n\t{\r\n\t\t_animalAmount = value;\r\n\t\tOnPropertyChanged( \"AnimalAmount\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nObservableCollection<Preset>* NewGameModel::GetPresets() const\r\n{\r\n\treturn _presets;\r\n}\r\nvoid NewGameModel::SetSelectedPreset( Preset* preset )\r\n{\r\n\tif ( _selectedPreset != preset )\r\n\t{\r\n\t\tGlobal::newGameSettings->setPreset( preset->GetName() );\r\n\r\n\t\t_selectedPreset = preset;\r\n\t\tOnPropertyChanged( \"SelectedPreset\" );\r\n\r\n\t\tupdateStartingItems();\r\n\t\tupdateStartingAnimals();\r\n\t}\r\n}\r\n\r\nvoid NewGameModel::updateStartingItems()\r\n{\r\n\t_startingItems->Clear();\r\n\r\n\tfor ( auto si : Global::newGameSettings->startingItems() )\r\n\t{\r\n\t\t_startingItems->Add( MakePtr<StartItem>( si.itemSID, si.mat1, si.mat2, si.amount ) );\r\n\t}\r\n\tOnPropertyChanged( \"StartingItems\" );\r\n}\r\n\r\nvoid NewGameModel::updateStartingAnimals()\r\n{\r\n\t_startingAnimals->Clear();\r\n\r\n\tfor ( auto sa : Global::newGameSettings->startingAnimals() )\r\n\t{\r\n\t\t_startingAnimals->Add( MakePtr<StartAnimal>( sa.type, sa.gender, sa.amount ) );\r\n\t}\r\n\tOnPropertyChanged( \"StartingAnimals\" );\r\n}\r\n\r\nPreset* NewGameModel::GetSelectedPreset() const\r\n{\r\n\treturn _selectedPreset;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nObservableCollection<GameItem>* NewGameModel::GetItems() const\r\n{\r\n\treturn _items;\r\n}\r\nvoid NewGameModel::SetSelectedItem( GameItem* item )\r\n{\r\n\tif ( _selectedItem != item )\r\n\t{\r\n\t\t_selectedItem = item;\r\n\t\tOnPropertyChanged( \"SelectedItem\" );\r\n\r\n\t\t_itemMaterials1->Clear();\r\n\t\t_itemMaterials2->Clear();\r\n\r\n\t\tQStringList mats1;\r\n\t\tQStringList mats2;\r\n\r\n\t\tGlobal::newGameSettings->materialsForItem( item->sid(), mats1, mats2 );\r\n\r\n\t\tif ( mats1.size() )\r\n\t\t{\r\n\t\t\tfor ( auto mat : mats1 )\r\n\t\t\t{\r\n\t\t\t\t_itemMaterials1->Add( MakePtr<GameItem>( S::s( \"$MaterialName_\" + mat ), mat ) );\r\n\t\t\t}\r\n\t\t\tSetSelectedMaterial1( _itemMaterials1->Get( 0 ) );\r\n\t\t}\r\n\t\tif ( mats2.size() )\r\n\t\t{\r\n\t\t\tfor ( auto mat : mats2 )\r\n\t\t\t{\r\n\t\t\t\t_itemMaterials2->Add( MakePtr<GameItem>( S::s( \"$MaterialName_\" + mat ), mat ) );\r\n\t\t\t}\r\n\t\t\tSetSelectedMaterial2( _itemMaterials2->Get( 0 ) );\r\n\t\t}\r\n\t}\r\n}\r\nGameItem* NewGameModel::GetSelectedItem() const\r\n{\r\n\treturn _selectedItem;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nObservableCollection<GameItem>* NewGameModel::GetAnimals() const\r\n{\r\n\treturn _animals;\r\n}\r\nvoid NewGameModel::SetSelectedAnimal( GameItem* item )\r\n{\r\n\tif ( _selectedAnimal != item )\r\n\t{\r\n\t\t_selectedAnimal = item;\r\n\t\tOnPropertyChanged( \"SelectedAnimal\" );\r\n\t}\r\n}\r\nGameItem* NewGameModel::GetSelectedAnimal() const\r\n{\r\n\treturn _selectedAnimal;\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nObservableCollection<GameItem>* NewGameModel::GetGenders() const\r\n{\r\n\treturn _genders;\r\n}\r\nvoid NewGameModel::SetSelectedGender( GameItem* item )\r\n{\r\n\tif ( _selectedGender != item )\r\n\t{\r\n\t\t_selectedGender = item;\r\n\t\tOnPropertyChanged( \"SelectedGender\" );\r\n\t}\r\n}\r\nGameItem* NewGameModel::GetSelectedGender() const\r\n{\r\n\treturn _selectedGender;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nObservableCollection<GameItem>* NewGameModel::GetMaterials1() const\r\n{\r\n\treturn _itemMaterials1;\r\n}\r\nvoid NewGameModel::SetSelectedMaterial1( GameItem* mat )\r\n{\r\n\tif ( _selectedItemMaterial1 != mat )\r\n\t{\r\n\t\t_selectedItemMaterial1 = mat;\r\n\t\tOnPropertyChanged( \"SelectedMaterial1\" );\r\n\t}\r\n}\r\nGameItem* NewGameModel::GetSelectedMaterial1() const\r\n{\r\n\treturn _selectedItemMaterial1;\r\n}\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nObservableCollection<GameItem>* NewGameModel::GetMaterials2() const\r\n{\r\n\treturn _itemMaterials2;\r\n}\r\nvoid NewGameModel::SetSelectedMaterial2( GameItem* mat )\r\n{\r\n\tif ( _selectedItemMaterial2 != mat )\r\n\t{\r\n\t\t_selectedItemMaterial2 = mat;\r\n\t\tOnPropertyChanged( \"Selectedmaterial2\" );\r\n\t}\r\n}\r\nGameItem* NewGameModel::GetSelectedMaterial2() const\r\n{\r\n\treturn _selectedItemMaterial2;\r\n}\r\n\r\nObservableCollection<StartItem>* NewGameModel::GetStartingItems() const\r\n{\r\n\treturn _startingItems;\r\n}\r\n\r\nObservableCollection<StartAnimal>* NewGameModel::GetStartingAnimals() const\r\n{\r\n\treturn _startingAnimals;\r\n}\r\n\r\nObservableCollection<GameItem>* NewGameModel::GetAllowedTrees() const\r\n{\r\n\treturn _allowedTrees;\r\n}\r\n\r\nObservableCollection<GameItem>* NewGameModel::GetAllowedPlants() const\r\n{\r\n\treturn _allowedPlants;\r\n}\r\n\r\nObservableCollection<GameItem>* NewGameModel::GetAllowedWildAnimals() const\r\n{\r\n\treturn _allowedWildAnimals;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( NewGameModel, \"IngnomiaGUI.NewGameModel\" )\r\n{\r\n\t// menu properties\r\n\tNsProp( \"RandomKingdomName\", &NewGameModel::GetRandomKingdomName );\r\n\tNsProp( \"RandomSeed\", &NewGameModel::GetRandomSeed );\r\n\tNsProp( \"NewPreset\", &NewGameModel::GetNewPreset );\r\n\tNsProp( \"SavePreset\", &NewGameModel::GetSavePreset );\r\n\tNsProp( \"DeletePreset\", &NewGameModel::GetDeletePreset );\r\n\tNsProp( \"AddItem\", &NewGameModel::GetAddItem );\r\n\tNsProp( \"RemoveItem\", &NewGameModel::GetRemoveItem );\r\n\tNsProp( \"AddAnimal\", &NewGameModel::GetAddAnimal );\r\n\tNsProp( \"RemoveAnimal\", &NewGameModel::GetRemoveAnimal );\r\n\r\n\t// New Game properties\r\n\tNsProp( \"WorldSize\", &NewGameModel::GetWorldSize, &NewGameModel::SetWorldSize );\r\n\tNsProp( \"ZLevels\", &NewGameModel::GetZLevels, &NewGameModel::SetZLevels );\r\n\tNsProp( \"Ground\", &NewGameModel::GetGround, &NewGameModel::SetGround );\r\n\tNsProp( \"Flatness\", &NewGameModel::GetFlatness, &NewGameModel::SetFlatness );\r\n\tNsProp( \"OceanSize\", &NewGameModel::GetOceanSize, &NewGameModel::SetOceanSize );\r\n\tNsProp( \"Rivers\", &NewGameModel::GetRivers, &NewGameModel::SetRivers );\r\n\tNsProp( \"RiverSize\", &NewGameModel::GetRiverSize, &NewGameModel::SetRiverSize );\r\n\tNsProp( \"NumGnomes\", &NewGameModel::GetNumGnomes, &NewGameModel::SetNumGnomes );\r\n\tNsProp( \"StartZone\", &NewGameModel::GetStartZone, &NewGameModel::SetStartZone );\r\n\tNsProp( \"KingdomName\", &NewGameModel::GetKingdomName, &NewGameModel::SetKingdomName );\r\n\tNsProp( \"Seed\", &NewGameModel::GetSeed, &NewGameModel::SetSeed );\r\n\tNsProp( \"ItemAmount\", &NewGameModel::GetItemAmount, &NewGameModel::SetItemAmount );\r\n\tNsProp( \"AnimalAmount\", &NewGameModel::GetAnimalAmount, &NewGameModel::SetAnimalAmount );\r\n\tNsProp( \"MaxPerType\", &NewGameModel::GetMaxPerType, &NewGameModel::SetMaxPertype );\r\n\tNsProp( \"NumWildAnimals\", &NewGameModel::GetNumWildAnimals, &NewGameModel::SetNumWildAnimals );\r\n\tNsProp( \"StartingItems\", &NewGameModel::GetStartingItems );\r\n\tNsProp( \"StartingAnimals\", &NewGameModel::GetStartingAnimals );\r\n\tNsProp( \"AllowedTrees\", &NewGameModel::GetAllowedTrees );\r\n\tNsProp( \"AllowedPlants\", &NewGameModel::GetAllowedPlants );\r\n\tNsProp( \"AllowedWildAnimals\", &NewGameModel::GetAllowedWildAnimals );\r\n\tNsProp( \"TreeDensity\", &NewGameModel::GetTreeDensity, &NewGameModel::SetTreeDensity );\r\n\tNsProp( \"PlantDensity\", &NewGameModel::GetPlantDensity, &NewGameModel::SetPlantDensity );\r\n\tNsProp( \"Peaceful\", &NewGameModel::GetPeaceful, &NewGameModel::SetPeaceful );\r\n\r\n\tNsProp( \"Presets\", &NewGameModel::GetPresets );\r\n\tNsProp( \"SelectedPreset\", &NewGameModel::GetSelectedPreset, &NewGameModel::SetSelectedPreset );\r\n\tNsProp( \"Items\", &NewGameModel::GetItems );\r\n\tNsProp( \"SelectedItem\", &NewGameModel::GetSelectedItem, &NewGameModel::SetSelectedItem );\r\n\tNsProp( \"Materials1\", &NewGameModel::GetMaterials1 );\r\n\tNsProp( \"SelectedMaterial1\", &NewGameModel::GetSelectedMaterial1, &NewGameModel::SetSelectedMaterial1 );\r\n\tNsProp( \"Materials2\", &NewGameModel::GetMaterials2 );\r\n\tNsProp( \"SelectedMaterial2\", &NewGameModel::GetSelectedMaterial2, &NewGameModel::SetSelectedMaterial2 );\r\n\tNsProp( \"Animals\", &NewGameModel::GetAnimals );\r\n\tNsProp( \"SelectedAnimal\", &NewGameModel::GetSelectedAnimal, &NewGameModel::SetSelectedAnimal );\r\n\tNsProp( \"Genders\", &NewGameModel::GetGenders );\r\n\tNsProp( \"SelectedGender\", &NewGameModel::GetSelectedGender, &NewGameModel::SetSelectedGender );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( Preset )\r\n{\r\n\tNsProp( \"Name\", &Preset::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( GameItem )\r\n{\r\n\tNsProp( \"Name\", &GameItem::GetName );\r\n\tNsProp( \"IsChecked\", &GameItem::isChecked, &GameItem::setChecked );\r\n\tNsProp( \"Amount\", &GameItem::getAmount, &GameItem::setAmount );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( StartItem )\r\n{\r\n\tNsProp( \"Tag\", &StartItem::_tag );\r\n\tNsProp( \"Name\", &StartItem::_name );\r\n\tNsProp( \"Material1\", &StartItem::_mat1 );\r\n\tNsProp( \"Material2\", &StartItem::_mat2 );\r\n\tNsProp( \"Amount\", &StartItem::_amount );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( StartAnimal )\r\n{\r\n\tNsProp( \"Tag\", &StartAnimal::_tag );\r\n\tNsProp( \"Name\", &StartAnimal::_type );\r\n\tNsProp( \"Gender\", &StartAnimal::_gender );\r\n\tNsProp( \"Amount\", &StartAnimal::_amount );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/NewGameModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __MENU3D_NEWGAMEMODEL_H__\r\n#define __MENU3D_NEWGAMEMODEL_H__\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n#include <NsGui/ObservableCollection.h>\r\n\r\n#include <QString>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass Preset final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tPreset( const char* name );\r\n\r\n\tconst char* GetName() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\r\n\tNS_DECLARE_REFLECTION( Preset, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GameItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGameItem( QString name, QString sid );\r\n\tGameItem( QString name, QString sid, int amount );\r\n\r\n\tconst char* GetName() const;\r\n\tbool isChecked() const;\r\n\tconst char* sid();\r\n\r\n\tvoid setChecked( bool value );\r\n\r\n\tconst char* getAmount() const;\r\n\tvoid setAmount( const char* value );\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tNoesis::String _sid;\r\n\t\r\n\tNoesis::String m_amountString = \"0\";\r\n\tint m_amount = 0;\r\n\r\n\tNS_DECLARE_REFLECTION( GameItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nstruct StartItem : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tStartItem( QString name, QString mat1, QString mat2, int amount );\r\n\r\n\tNoesis::String _tag;\r\n\tNoesis::String _name;\r\n\tNoesis::String _mat1;\r\n\tNoesis::String _mat2;\r\n\tNoesis::String _amount;\r\n\r\n\tNS_DECLARE_REFLECTION( StartItem, BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nstruct StartAnimal : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tStartAnimal( QString type, QString gender, int amount );\r\n\r\n\tNoesis::String _tag;\r\n\tNoesis::String _type;\r\n\tNoesis::String _gender;\r\n\tNoesis::String _amount;\r\n\r\n\tNS_DECLARE_REFLECTION( StartAnimal, BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass NewGameModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tNewGameModel();\r\n\r\nprivate:\r\n\tconst NoesisApp::DelegateCommand* GetRandomKingdomName() const;\r\n\tconst NoesisApp::DelegateCommand* GetRandomSeed() const;\r\n\tconst NoesisApp::DelegateCommand* GetNewPreset() const;\r\n\tconst NoesisApp::DelegateCommand* GetSavePreset() const;\r\n\tconst NoesisApp::DelegateCommand* GetDeletePreset() const;\r\n\tconst NoesisApp::DelegateCommand* GetAddItem() const;\r\n\tconst NoesisApp::DelegateCommand* GetRemoveItem() const;\r\n\tconst NoesisApp::DelegateCommand* GetAddAnimal() const;\r\n\tconst NoesisApp::DelegateCommand* GetRemoveAnimal() const;\r\n\r\n\tvoid OnRandomKingdomName( BaseComponent* param );\r\n\tvoid OnRandomSeed( BaseComponent* param );\r\n\tvoid OnNewPreset( BaseComponent* param );\r\n\tvoid OnSavePreset( BaseComponent* param );\r\n\tvoid OnDeletePreset( BaseComponent* param );\r\n\tvoid OnAddItem( BaseComponent* param );\r\n\tvoid OnRemoveItem( BaseComponent* param );\r\n\tvoid OnAddAnimal( BaseComponent* param );\r\n\tvoid OnRemoveAnimal( BaseComponent* param );\r\n\r\n\tint GetWorldSize() const;\r\n\tvoid SetWorldSize( int value );\r\n\r\n\tint GetZLevels() const;\r\n\tvoid SetZLevels( int value );\r\n\r\n\tint GetGround() const;\r\n\tvoid SetGround( int value );\r\n\r\n\tint GetFlatness() const;\r\n\tvoid SetFlatness( int value );\r\n\r\n\tint GetOceanSize() const;\r\n\tvoid SetOceanSize( int value );\r\n\r\n\tint GetRivers() const;\r\n\tvoid SetRivers( int value );\r\n\r\n\tint GetRiverSize() const;\r\n\tvoid SetRiverSize( int value );\r\n\r\n\tint GetNumGnomes() const;\r\n\tvoid SetNumGnomes( int value );\r\n\r\n\tint GetStartZone() const;\r\n\tvoid SetStartZone( int value );\r\n\r\n\tint GetTreeDensity() const;\r\n\tvoid SetTreeDensity( int value );\r\n\r\n\tint GetPlantDensity() const;\r\n\tvoid SetPlantDensity( int value );\r\n\r\n\tconst char* GetKingdomName() const;\r\n\tvoid SetKingdomName( const char* value );\r\n\r\n\tconst char* GetSeed() const;\r\n\tvoid SetSeed( const char* value );\r\n\r\n\tconst char* GetItemAmount() const;\r\n\tvoid SetItemAmount( const char* value );\r\n\r\n\tconst char* GetAnimalAmount() const;\r\n\tvoid SetAnimalAmount( const char* value );\r\n\r\n\tbool GetPeaceful() const;\r\n\tvoid SetPeaceful( bool value );\r\n\r\n\tint GetMaxPerType() const;\r\n\tvoid SetMaxPertype( int value );\r\n\r\n\tint GetNumWildAnimals() const;\r\n\tvoid SetNumWildAnimals( int value );\r\n\r\n\tNoesis::ObservableCollection<Preset>* GetPresets() const;\r\n\tvoid SetSelectedPreset( Preset* preset );\r\n\tPreset* GetSelectedPreset() const;\r\n\r\n\tNoesis::ObservableCollection<GameItem>* GetItems() const;\r\n\tvoid SetSelectedItem( GameItem* item );\r\n\tGameItem* GetSelectedItem() const;\r\n\r\n\tNoesis::ObservableCollection<GameItem>* GetMaterials1() const;\r\n\tvoid SetSelectedMaterial1( GameItem* item );\r\n\tGameItem* GetSelectedMaterial1() const;\r\n\r\n\tNoesis::ObservableCollection<GameItem>* GetMaterials2() const;\r\n\tvoid SetSelectedMaterial2( GameItem* item );\r\n\tGameItem* GetSelectedMaterial2() const;\r\n\r\n\tNoesis::ObservableCollection<StartItem>* GetStartingItems() const;\r\n\tNoesis::ObservableCollection<StartAnimal>* GetStartingAnimals() const;\r\n\tNoesis::ObservableCollection<GameItem>* GetAllowedTrees() const;\r\n\tNoesis::ObservableCollection<GameItem>* GetAllowedPlants() const;\r\n\tNoesis::ObservableCollection<GameItem>* GetAllowedWildAnimals() const;\r\n\r\n\tNoesis::ObservableCollection<GameItem>* GetAnimals() const;\r\n\tvoid SetSelectedAnimal( GameItem* item );\r\n\tGameItem* GetSelectedAnimal() const;\r\n\r\n\tNoesis::ObservableCollection<GameItem>* GetGenders() const;\r\n\tvoid SetSelectedGender( GameItem* item );\r\n\tGameItem* GetSelectedGender() const;\r\n\r\nprivate:\r\n\tNoesisApp::DelegateCommand _randomKingdomName;\r\n\tNoesisApp::DelegateCommand _randomSeed;\r\n\tNoesisApp::DelegateCommand _newPreset;\r\n\tNoesisApp::DelegateCommand _savePreset;\r\n\tNoesisApp::DelegateCommand _deletePreset;\r\n\tNoesisApp::DelegateCommand _addItem;\r\n\tNoesisApp::DelegateCommand _removeItem;\r\n\tNoesisApp::DelegateCommand _addAnimal;\r\n\tNoesisApp::DelegateCommand _removeAnimal;\r\n\r\n\tNoesis::String _seed;\r\n\tNoesis::String _kingdomName;\r\n\r\n\tNoesis::String _itemAmount;\r\n\tNoesis::String _animalAmount;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<Preset>> _presets;\r\n\tPreset* _selectedPreset;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _items;\r\n\tGameItem* _selectedItem;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _animals;\r\n\tGameItem* _selectedAnimal;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _genders;\r\n\tGameItem* _selectedGender;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _itemMaterials1;\r\n\tGameItem* _selectedItemMaterial1;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _itemMaterials2;\r\n\tGameItem* _selectedItemMaterial2;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<StartItem>> _startingItems;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<StartAnimal>> _startingAnimals;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _allowedTrees;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _allowedPlants;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GameItem>> _allowedWildAnimals;\r\n\r\n\tvoid updateStartingItems();\r\n\tvoid updateStartingAnimals();\r\n\r\n\tNS_DECLARE_REFLECTION( NewGameModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/NewGamePage.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"NewGamePage.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNewGamePage::NewGamePage()\r\n{\r\n\tLoaded() += MakeDelegate( this, &NewGamePage::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid NewGamePage::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"NewGamePage.xaml\" );\r\n}\r\n\r\nbool NewGamePage::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid NewGamePage::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::NewGamePage, \"IngnomiaGUI.NewGamePage\" )\r\n"
  },
  {
    "path": "src/gui/xaml/NewGamePage.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __NewGamePage_H__\r\n#define __NewGamePage_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass NewGamePage final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tNewGamePage();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( NewGamePage, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/Population.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"Population.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nPopulationWindow::PopulationWindow()\r\n{\r\n\tLoaded() += MakeDelegate( this, &PopulationWindow::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid PopulationWindow::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"PopulationWindow.xaml\" );\r\n}\r\n\r\nstatic Noesis::ScrollViewer* getVirtualListScroller( Noesis::FrameworkElement* root )\r\n{\r\n\tNS_CHECK( root != 0, \"Missing input\" );\r\n\tif ( auto scrollViewer = Noesis::DynamicCast<Noesis::ScrollViewer*>(root) )\r\n\t{\r\n\t\treturn scrollViewer;\r\n\t}\r\n\tif(auto child = root->GetTemplateChild<BaseComponent>( \"PART_Scroll\" ))\r\n\t{\r\n\t\tif ( auto scrollViewer = Noesis::DynamicCast<Noesis::ScrollViewer*>( child ) )\r\n\t\t{\r\n\t\t\treturn scrollViewer;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tNS_CHECK( root != 0, \"Type mismatch\" );\r\n\t\t}\r\n\t}\r\n\tNS_CHECK( false, \"No ScrollViewer found\" );\r\n\treturn nullptr;\r\n}\r\n\r\nvoid PopulationWindow::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n\r\n\tm_skillNameScroll       = getVirtualListScroller( this->FindName<FrameworkElement>( \"SVNames\" ) );\r\n\tm_skillContentScroll    = getVirtualListScroller( this->FindName<FrameworkElement>( \"SVSkills\" ) );\r\n\tm_skillHeaderScroll     = getVirtualListScroller( this->FindName<FrameworkElement>( \"SVSkillHeaders\" ) );\r\n\tm_scheduleNameScroll    = getVirtualListScroller( this->FindName<FrameworkElement>( \"SchedNames\" ) );\r\n\tm_scheduleContentScroll = getVirtualListScroller( this->FindName<FrameworkElement>( \"SVActivities\" ) );\r\n\r\n\tauto scrollHandler = Noesis::MakeDelegate( this, &SelfClass::OnScroll );\r\n\tm_skillNameScroll->ScrollChanged() += scrollHandler;\r\n\tm_skillContentScroll->ScrollChanged() += scrollHandler;\r\n\tm_skillHeaderScroll->ScrollChanged() += scrollHandler;\r\n\tm_scheduleNameScroll->ScrollChanged() += scrollHandler;\r\n\tm_scheduleContentScroll->ScrollChanged() += scrollHandler;\r\n}\r\n\r\nvoid PopulationWindow::OnScroll( Noesis::BaseComponent* sender, const Noesis::ScrollChangedEventArgs& args )\r\n{\r\n\tif ( sender == m_skillNameScroll )\r\n\t{\r\n\t\tm_skillContentScroll->ScrollToVerticalOffset( m_skillNameScroll->GetVerticalOffset() );\r\n\t}\r\n\telse if ( sender == m_skillContentScroll )\r\n\t{\r\n\t\tm_skillNameScroll->ScrollToVerticalOffset( m_skillContentScroll->GetVerticalOffset() );\r\n\t\tm_skillHeaderScroll->ScrollToHorizontalOffset( m_skillContentScroll->GetHorizontalOffset() );\r\n\t}\r\n\telse if ( sender == m_skillHeaderScroll )\r\n\t{\r\n\t\tm_skillContentScroll->ScrollToHorizontalOffset( m_skillHeaderScroll->GetHorizontalOffset() );\r\n\t}\r\n\telse if ( sender == m_scheduleNameScroll )\r\n\t{\r\n\t\tm_scheduleContentScroll->ScrollToVerticalOffset( m_scheduleNameScroll->GetVerticalOffset() );\r\n\t}\r\n\telse if ( sender == m_scheduleContentScroll )\r\n\t{\r\n\t\tm_scheduleNameScroll->ScrollToVerticalOffset( m_scheduleContentScroll->GetVerticalOffset() );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::PopulationWindow, \"IngnomiaGUI.PopulationWindow\" )\r\n"
  },
  {
    "path": "src/gui/xaml/Population.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __PopulationWindow_H__\r\n#define __PopulastionPage_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass PopulationWindow final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tPopulationWindow();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tvoid OnScroll( Noesis::BaseComponent* sender, const Noesis::ScrollChangedEventArgs& );\r\n\r\n\tNoesis::ScrollViewer* m_skillNameScroll = nullptr;\r\n\tNoesis::ScrollViewer* m_skillContentScroll = nullptr;\r\n\tNoesis::ScrollViewer* m_skillHeaderScroll = nullptr;\r\n\tNoesis::ScrollViewer* m_scheduleNameScroll  = nullptr;\r\n\tNoesis::ScrollViewer* m_scheduleContentScroll = nullptr;\r\n\t\r\n\r\n\tNS_DECLARE_REFLECTION( PopulationWindow, UserControl )\r\n\r\n\r\n\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/PopulationModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"PopulationModel.h\"\r\n\r\n#include \"populationproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nProfItem::ProfItem( QString name )\r\n{\r\n\tm_name = name.toStdString().c_str();\r\n}\r\n\r\nconst char* ProfItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nvoid ProfItem::SetName( const char* name )\r\n{\r\n\tm_name = name;\r\n\tOnPropertyChanged( \"Name\" );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nGnomeSkill::GnomeSkill( const GuiSkillInfo& skill, unsigned int gnomeID, PopulationProxy* proxy ) :\r\n\tm_gnomeID( gnomeID ),\r\n\tm_proxy( proxy )\r\n{\r\n\tm_name      = skill.name.toStdString().c_str();\r\n\tm_level\t= QString::number( skill.level ).toStdString().c_str();\r\n\tm_checked   = skill.active;\r\n\tm_color = skill.color.toStdString().c_str();\r\n\tm_skillID = skill.sid.toStdString().c_str();\r\n}\r\n\r\nconst char* GnomeSkill::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* GnomeSkill::GetID() const\r\n{\r\n\treturn m_skillID.Str();\r\n}\r\n\r\n\r\nconst char* GnomeSkill::GetLevel() const\r\n{\r\n\treturn m_level.Str();\r\n}\r\n\r\nbool GnomeSkill::GetChecked() const\r\n{\r\n\treturn m_checked;\r\n}\r\n\r\nvoid GnomeSkill::SetChecked( bool value )\r\n{\r\n\tm_checked = value;\r\n\tif( m_proxy )\r\n\t{\r\n\t\tm_proxy->setSkillActive( m_gnomeID, m_skillID.Str(), value );\r\n\t}\r\n}\r\n\r\nconst char* GnomeSkill::GetColor() const\r\n{\r\n\treturn m_color.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nGnomeRow::GnomeRow( const GuiGnomeInfo& gnome, Noesis::Ptr<Noesis::ObservableCollection<ProfItem>> professions, PopulationProxy* proxy ) :\r\n\tm_proxy( proxy )\r\n{\r\n\tm_id        = gnome.id;\r\n\tm_idString  = QString::number( gnome.id ).toStdString().c_str();\r\n\tm_name      = gnome.name.toStdString().c_str();\r\n\tm_professionName = gnome.profession;\r\n\r\n\tm_skills = *new ObservableCollection<GnomeSkill>();\r\n\r\n\tfor( const auto& skill : gnome.skills )\r\n\t{\r\n\t\tm_skills->Add( MakePtr<GnomeSkill>( skill, m_id, proxy ) );\r\n\t}\r\n\r\n\tm_professions = professions;\r\n\r\n\tfor( int i = 0; i < m_professions->Count(); ++i )\r\n\t{\r\n\t\tif( m_professions->Get( i )->GetName() == gnome.profession )\r\n\t\t{\r\n\t\t\tSetProfession( m_professions->Get( i ) );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid GnomeRow::updateProfessionList( Noesis::Ptr<Noesis::ObservableCollection<ProfItem>> professions )\r\n{\r\n\tm_professions = professions;\r\n\tm_selectedProfession = nullptr;\r\n\tfor( int i = 0; i < m_professions->Count(); ++i )\r\n\t{\r\n\t\tif( m_professions->Get( i )->GetName() == m_professionName )\r\n\t\t{\r\n\t\t\tSetProfession( m_professions->Get( i ) );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tif ( m_selectedProfession == nullptr )\r\n\t{\r\n\t\tSetProfession( m_professions->Get( 0 ) );\r\n\t}\r\n}\r\n\r\nconst char* GnomeRow::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* GnomeRow::GetID() const\r\n{\r\n\treturn m_idString.Str();\r\n}\r\n\r\nNoesis::ObservableCollection<ProfItem>* GnomeRow::GetProfessions() const\r\n{\r\n\treturn m_professions;\r\n}\r\n\t\r\nvoid GnomeRow::SetProfession( ProfItem* item )\r\n{\r\n\tif ( item && m_selectedProfession != item )\r\n\t{\r\n\t\tm_selectedProfession = item;\r\n\t\tm_proxy->setProfession( m_id, item->GetName() );\r\n\r\n\t\tOnPropertyChanged( \"Profession\" );\r\n\t}\r\n}\r\n\r\nProfItem* GnomeRow::GetProfession() const\r\n{\r\n\treturn m_selectedProfession;\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nGnomeScheduleEntry::GnomeScheduleEntry( unsigned int id, int hour, ScheduleActivity activity, PopulationProxy* proxy ) :\r\n\tm_proxy( proxy ),\r\n\tm_id( id ),\r\n\tm_hour( hour ),\r\n\tm_activity( activity )\r\n{\r\n\tswitch ( activity )\r\n\t{\r\n\t\tcase ScheduleActivity::Eat:\r\n\t\t\tm_activityString = \"E\";\r\n\t\t\tbreak;\r\n\t\tcase ScheduleActivity::Sleep:\r\n\t\t\tm_activityString = \"S\";\r\n\t\t\tbreak;\r\n\t\tcase ScheduleActivity::Training:\r\n\t\t\tm_activityString = \"T\";\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\tm_activityString = \"N\";\r\n\t\t\tbreak;\r\n\t}\r\n\tm_setHourCmd.SetExecuteFunc( MakeDelegate( this, &GnomeScheduleEntry::onSetHourCmd ) );\r\n\r\n}\r\n\r\nconst char* GnomeScheduleEntry::GetActivity() const\r\n{\r\n\treturn m_activityString.Str();\r\n}\r\n\r\nvoid GnomeScheduleEntry::onSetHourCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setSchedule( m_id, m_hour, m_activity );\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nGnomeScheduleRow::GnomeScheduleRow( const GuiGnomeScheduleInfo& gnome, PopulationProxy* proxy  ) :\r\n\tm_proxy( proxy )\r\n{\r\n\tm_id        = gnome.id;\r\n\tm_idString  = QString::number( gnome.id ).toStdString().c_str();\r\n\tm_name      = gnome.name.toStdString().c_str();\r\n\r\n\tm_schedule = *new ObservableCollection<GnomeScheduleEntry>();\r\n\tint hour = 0;\r\n\r\n\tfor( const auto& activity : gnome.schedule )\r\n\t{\r\n\t\tm_schedule->Add( MakePtr<GnomeScheduleEntry>( m_id, hour++, activity, proxy ) );\r\n\t}\r\n\r\n}\r\n\r\nconst char* GnomeScheduleRow::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* GnomeScheduleRow::GetID() const\r\n{\r\n\treturn m_idString.Str();\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nPopulationModel::PopulationModel()\r\n{\r\n\tm_proxy = new PopulationProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_gnomes = *new ObservableCollection<GnomeRow>();\r\n\tm_skills = *new ObservableCollection<GnomeSkill>();\r\n\tm_profSkills = *new ObservableCollection<GnomeSkill>();\r\n\tm_scheduleGnomes = *new ObservableCollection<GnomeScheduleRow>();\r\n\r\n\tm_allGnomesCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onAllGnomesCmd ) );\r\n\tm_removeAllGnomesCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onRemoveAllGnomesCmd ) );\r\n\tm_allSkillsCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onAllSkillsCmd ) );\r\n\tm_removeAllSkillsCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onRemoveAllSkillsCmd ) );\r\n\tm_sortCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onSortCmd ) );\r\n\tm_pageCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onPageCmd ) );\r\n\tm_setActivityCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onSetActivityCmd ) );\r\n\tm_setAllHoursCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onSetAllHoursCmd ) );\r\n\tm_setHoursForAllCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onSetHoursForAllCmd ) );\r\n\r\n\tm_profSkillUpCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onProfSkillUpCmd ) );\r\n\tm_profSkillDownCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onProfSkillDownCmd ) );\r\n\tm_profSkillAddCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onProfSkillAddCmd ) );\r\n\tm_profSkillRemoveCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onProfSkillRemoveCmd ) );\r\n\t\r\n\tm_newProfCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onNewProfCmd ) );\r\n\tm_deleteProfCmd.SetExecuteFunc( MakeDelegate( this, &PopulationModel::onDeleteProfCmd ) );\r\n\r\n\tm_professions = *new ObservableCollection<ProfItem>();\r\n}\r\n\r\nvoid PopulationModel::updateProfessionList( const QStringList& professions )\r\n{\r\n\tm_professions->Clear();\r\n\tfor( const auto& prof : professions )\r\n\t{\r\n\t\tm_professions->Add( MakePtr<ProfItem>( prof.toStdString().c_str() ) );\r\n\t}\r\n\tif( m_professions->Count() > 0 )\r\n\t{\r\n\t\tSetProfession( m_professions->Get( 0 ) );\r\n\t}\r\n\r\n\tfor( int i = 0; i < m_gnomes->Count(); ++i )\r\n\t{\r\n\t\tm_gnomes->Get( i )->updateProfessionList( m_professions );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"Professions\" );\r\n}\r\n\r\nvoid PopulationModel::updateInfo( const GuiPopulationInfo& info )\r\n{\r\n\tm_gnomes->Clear();\r\n\r\n\tfor( const auto& gnome : info.gnomes )\r\n\t{\r\n\t\tm_gnomes->Add( MakePtr<GnomeRow>( gnome, m_professions, m_proxy ) );\r\n\t}\r\n\r\n\tif( m_skills->Count() == 0 )\r\n\t{\r\n\t\tif( info.gnomes.size() )\r\n\t\t{\r\n\t\t\tauto& first = info.gnomes.first();\r\n\t\t\tfor( const auto& skill : first.skills )\r\n\t\t\t{\r\n\t\t\t\tm_skills->Add( MakePtr<GnomeSkill>( skill, 0, m_proxy ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tOnPropertyChanged( \"Gnomes\" );\r\n\tOnPropertyChanged( \"SkillHeaders\" );\r\n}\r\n\r\nvoid PopulationModel::updateSingleGnome( const GuiGnomeInfo& gnome )\r\n{\r\n\tfor( int i = 0; i < m_gnomes->Count(); ++i )\r\n\t{\r\n\t\tauto info = m_gnomes->Get( i );\r\n\t\tif( info->gnomeID() == gnome.id )\r\n\t\t{\r\n\t\t\tm_gnomes->RemoveAt( i );\r\n\t\t\tm_gnomes->Insert( i, MakePtr<GnomeRow>( gnome, m_professions, m_proxy ) );\r\n\t\t\tOnPropertyChanged( \"Gnomes\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid PopulationModel::onAllGnomesCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setSkillForAllGnomes( param->ToString().Str(), true );\r\n}\r\n\r\nvoid PopulationModel::onRemoveAllGnomesCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setSkillForAllGnomes( param->ToString().Str(), false );\r\n}\r\n\r\n\r\nvoid PopulationModel::onAllSkillsCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setAllSkillsForGnome( QString(param->ToString().Str() ).toUInt(), true );\r\n}\r\n\r\nvoid PopulationModel::onRemoveAllSkillsCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setAllSkillsForGnome( QString(param->ToString().Str() ).toUInt(), false );\r\n}\r\n\r\nvoid PopulationModel::onSortCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->sortGnomes( param->ToString().Str() );\r\n}\r\n\r\nvoid PopulationModel::onPageCmd( BaseComponent* param )\r\n{\r\n\tm_state = PopState::Skills;\r\n\tif( param->ToString() == \"Schedule\" )\r\n\t{\r\n\t\tm_state = PopState::Schedule;\r\n\t\tm_proxy->requestSchedules();\r\n\t}\r\n\tif( param->ToString() == \"ProfEdit\" )\r\n\t{\r\n\t\tm_state = PopState::ProfEdit;\r\n\t\t//m_proxy->requestProfessions();\r\n\t}\r\n\r\n\tOnPropertyChanged( \"ShowSkills\" );\r\n\tOnPropertyChanged( \"ShowSchedule\" );\r\n\tOnPropertyChanged( \"ShowProfEdit\" );\r\n}\r\n\r\nconst char* PopulationModel::GetShowSkills() const\r\n{\r\n\tif( m_state == PopState::Skills )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nconst char* PopulationModel::GetShowSchedule() const\r\n{\r\n\tif( m_state == PopState::Schedule )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* PopulationModel::GetShowProfEdit() const\r\n{\r\n\tif( m_state == PopState::ProfEdit )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid PopulationModel::updateSchedules( const GuiScheduleInfo& info )\r\n{\r\n\tm_scheduleGnomes->Clear();\r\n\r\n\tfor( const auto& gnome : info.schedules )\r\n\t{\r\n\t\tm_scheduleGnomes->Add( MakePtr<GnomeScheduleRow>( gnome, m_proxy ) );\r\n\t}\r\n\tOnPropertyChanged( \"Schedules\" );\r\n}\r\n\r\nvoid PopulationModel::updateScheduleSingleGnome( const GuiGnomeScheduleInfo& gnome )\r\n{\r\n\tfor( int i = 0; i < m_scheduleGnomes->Count(); ++i )\r\n\t{\r\n\t\tauto info = m_scheduleGnomes->Get( i );\r\n\t\tif( info->gnomeID() == gnome.id )\r\n\t\t{\r\n\t\t\tm_scheduleGnomes->RemoveAt( i );\r\n\t\t\tm_scheduleGnomes->Insert( i, MakePtr<GnomeScheduleRow>( gnome, m_proxy ) );\r\n\t\t\tOnPropertyChanged( \"Schedules\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::onSetActivityCmd( BaseComponent* param )\r\n{\r\n\tQString qParam = param->ToString().Str();\r\n\tif( qParam == \"Eat\" ) m_scheduleActivity = ScheduleActivity::Eat;\r\n\telse if( qParam == \"Sleep\" ) m_scheduleActivity = ScheduleActivity::Sleep;\r\n\telse if( qParam == \"Train\" ) m_scheduleActivity = ScheduleActivity::Training;\r\n\telse m_scheduleActivity = ScheduleActivity::None;\r\n\r\n\tm_proxy->setCurrentActivity( m_scheduleActivity );\r\n\r\n\tOnPropertyChanged( \"ScheduleActivity\" );\r\n}\r\n\r\nconst char* PopulationModel::GetScheduleActivity() const\r\n{\r\n\tswitch( m_scheduleActivity )\r\n\t{\r\n\t\tcase ScheduleActivity::Eat:\r\n\t\t\treturn \"E\";\r\n\t\t\tbreak;\r\n\t\tcase ScheduleActivity::Sleep:\r\n\t\t\treturn \"S\";\r\n\t\t\tbreak;\r\n\t\tcase ScheduleActivity::Training:\r\n\t\t\treturn \"T\";\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\t\t\treturn \"N\";\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::onSetAllHoursCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setAllHours( QString( param->ToString().Str() ).toUInt(), m_scheduleActivity );\r\n}\r\n\r\nvoid PopulationModel::onSetHoursForAllCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->setHourForAll( QString( param->ToString().Str() ).toInt(), m_scheduleActivity );\r\n}\r\n\r\nNoesis::ObservableCollection<ProfItem>* PopulationModel::GetProfessions() const\r\n{\r\n\treturn m_professions;\r\n}\r\n\t\r\nvoid PopulationModel::SetProfession( ProfItem* item )\r\n{\r\n\tif ( item && m_selectedProfession != item )\r\n\t{\r\n\t\tm_selectedProfession = item;\r\n\t\tm_proxy->requestSkills( m_selectedProfession->GetName() );\r\n\r\n\t\tm_lockProfessionEdit = ( item->GetName() == QString( \"Gnomad\" ) );\r\n\t\t\r\n\t\tm_profName = item->GetName();\r\n\r\n\t\tOnPropertyChanged( \"Profession\" );\r\n\t\tOnPropertyChanged( \"ProfName\" );\r\n\t}\r\n}\r\n\r\nProfItem* PopulationModel::GetProfession() const\r\n{\r\n\treturn m_selectedProfession;\r\n}\r\n\r\nvoid PopulationModel::updateProfessionSkills( const QString profession, const QList<GuiSkillInfo>& skills )\r\n{\r\n\tm_profSkills->Clear();\r\n\r\n\tfor( const auto& skill : skills )\r\n\t{\r\n\t\tm_profSkills->Add( MakePtr<GnomeSkill>( skill, 0, m_proxy ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"ProfSkills\" );\r\n}\r\n\r\nvoid PopulationModel::onProfSkillUpCmd( BaseComponent* param )\r\n{\r\n\tif( m_lockProfessionEdit ) return;\r\n\tif( param )\r\n\t{\r\n\t\tNoesis::String skillID = param->ToString();\r\n\t\tfor( int i = 1; i < m_profSkills->Count(); ++i )\r\n\t\t{\r\n\t\t\tif( m_profSkills->Get( i )->GetID() == skillID )\r\n\t\t\t{\r\n\t\t\t\tm_profSkills->Move( i, i - 1 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsendModifiedProfession();\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::onProfSkillDownCmd( BaseComponent* param )\r\n{\r\n\tif( m_lockProfessionEdit ) return;\r\n\tif( param )\r\n\t{\r\n\t\tNoesis::String skillID = param->ToString();\r\n\t\tfor( int i = 0; i < m_profSkills->Count() - 1; ++i )\r\n\t\t{\r\n\t\t\tif( m_profSkills->Get( i )->GetID() == skillID )\r\n\t\t\t{\r\n\t\t\t\tm_profSkills->Move( i, i + 1 );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsendModifiedProfession();\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::onProfSkillAddCmd( BaseComponent* param )\r\n{\r\n\tif( m_lockProfessionEdit ) return;\r\n\tif( param )\r\n\t{\r\n\t\tNoesis::String skillID = param->ToString();\r\n\t\tfor( int i = 0; i < m_profSkills->Count(); ++i )\r\n\t\t{\r\n\t\t\tif( m_profSkills->Get( i )->GetID() == skillID )\r\n\t\t\t{\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor( int i = 0; i < m_skills->Count(); ++i )\r\n\t\t{\r\n\t\t\tif( m_skills->Get( i )->GetID() == skillID )\r\n\t\t\t{\r\n\t\t\t\tGuiSkillInfo gsi;\r\n\t\t\t\tgsi.sid = skillID.Str();\r\n\t\t\t\tgsi.name = m_skills->Get( i )->GetName();\r\n\t\t\t\tm_profSkills->Add( MakePtr<GnomeSkill>( gsi, 0, m_proxy ) );\r\n\t\t\t\tOnPropertyChanged( \"ProfSkills\" );\r\n\t\t\t\tsendModifiedProfession();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::onProfSkillRemoveCmd( BaseComponent* param )\r\n{\r\n\tif( m_lockProfessionEdit ) return;\r\n\tif( param )\r\n\t{\r\n\t\tNoesis::String skillID = param->ToString();\r\n\t\tfor( int i = 0; i < m_profSkills->Count(); ++i )\r\n\t\t{\r\n\t\t\tif( m_profSkills->Get( i )->GetID() == skillID )\r\n\t\t\t{\r\n\t\t\t\tm_profSkills->RemoveAt( i );\r\n\t\t\t\tOnPropertyChanged( \"ProfSkills\" );\r\n\t\t\t\tsendModifiedProfession();\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::sendModifiedProfession()\r\n{\r\n\tif( m_selectedProfession )\r\n\t{\r\n\t\tQStringList skills;\r\n\t\tfor( int i = 0; i < m_profSkills->Count(); ++i )\r\n\t\t{\r\n\t\t\tskills.append( m_profSkills->Get( i )->GetID() );\r\n\t\t}\r\n\r\n\t\tQString oldName = m_selectedProfession->GetName();\r\n\t\tm_selectedProfession->SetName( m_profName.Str() );\r\n\t\t/*\r\n\t\tQString name = m_selectedProfession->GetName();\r\n\t\tfor( int i = 0; i < m_professions->Count(); ++i )\r\n\t\t{\r\n\t\t\tif( m_professions->Get( i )->GetName() == name )\r\n\t\t\t{\r\n\t\t\t\tm_professions->Get( i )->SetName( m_profName.Str() );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\t*/\r\n\t\tOnPropertyChanged( \"Profession\" );\r\n\t\tOnPropertyChanged( \"Professions\" );\r\n\r\n\t\tm_proxy->updateProfession( oldName, m_profName.Str(), skills );\r\n\t}\r\n}\r\n\r\nconst char* PopulationModel::GetProfName() const\r\n{\r\n\treturn m_profName.Str();\r\n}\r\n\r\nvoid PopulationModel::SetProfName( const char* value )\r\n{\r\n\tif( strcmp( value, m_profName.Str() ) != 0 )\r\n\t{\r\n\t\tQString newName = value; \r\n\t\r\n\t\tbool nameExists = false;\r\n\r\n\t\tfor( int i = 0; i < m_professions->Count(); ++i )\r\n\t\t{\r\n\t\t\tif( m_professions->Get( i )->GetName() == newName )\r\n\t\t\t{\r\n\t\t\t\tnameExists = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tm_profName = value;\r\n\t\r\n\t\tif( newName.length() > 3 && !nameExists )\r\n\t\t{\r\n\t\t\tsendModifiedProfession();\r\n\t\t}\r\n\t\tOnPropertyChanged( \"ProfName\" );\r\n\t}\r\n}\r\n\r\n\r\nvoid PopulationModel::onNewProfCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->newProfession();\r\n}\r\n\r\nvoid PopulationModel::onDeleteProfCmd( BaseComponent* param )\r\n{\r\n\tif( m_selectedProfession )\r\n\t{\r\n\t\tQString name = m_selectedProfession->GetName();\r\n\t\tm_proxy->deleteProfession( name );\r\n\t}\r\n}\r\n\r\nvoid PopulationModel::selectEditProfession( const QString name )\r\n{\r\n\tfor( int i = 0; i < m_professions->Count(); ++i )\r\n\t{\r\n\t\tif( m_professions->Get( i )->GetName() == name )\r\n\t\t{\r\n\t\t\tSetProfession( m_professions->Get( i ) );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\n\r\nNS_IMPLEMENT_REFLECTION( ProfItem )\r\n{\r\n\tNsProp( \"Name\", &ProfItem::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( PopulationModel, \"IngnomiaGUI.PopulationModel\" )\r\n{\r\n\tNsProp( \"Gnomes\", &PopulationModel::GetGnomes );\r\n\tNsProp( \"SkillHeaders\", &PopulationModel::GetSkills );\r\n\tNsProp( \"CmdAllGnomes\", &PopulationModel::GetAllGnomesCmd );\r\n\tNsProp( \"CmdRemoveAllGnomes\", &PopulationModel::GetRemoveAllGnomesCmd );\r\n\tNsProp( \"CmdAllSkills\", &PopulationModel::GetAllSkillsCmd );\r\n\tNsProp( \"CmdRemoveAllSkills\", &PopulationModel::GetRemoveAllSkillsCmd );\r\n\tNsProp( \"CmdSort\", &PopulationModel::GetSortCmd );\r\n\tNsProp( \"ShowSkills\", &PopulationModel::GetShowSkills );\r\n\tNsProp( \"ShowSchedule\", &PopulationModel::GetShowSchedule );\r\n\tNsProp( \"ShowProfEdit\", &PopulationModel::GetShowProfEdit );\r\n\tNsProp( \"PageCmd\", &PopulationModel::GetPageCmd );\r\n\tNsProp( \"Schedules\", &PopulationModel::GetScheduleGnomes );\r\n\tNsProp( \"CmdSetActivityType\", &PopulationModel::GetSetActivityCmd );\r\n\tNsProp( \"ScheduleActivity\", &PopulationModel::GetScheduleActivity );\r\n\tNsProp( \"CmdAllHours\", &PopulationModel::GetSetAllHoursCmd );\r\n\tNsProp( \"CmdSetHourForAll\", &PopulationModel::GetSetHoursForAllCmd );\r\n\tNsProp( \"Professions\", &PopulationModel::GetProfessions );\r\n\tNsProp( \"Profession\", &PopulationModel::GetProfession, &PopulationModel::SetProfession );\r\n\tNsProp( \"AllProfSkills\", &PopulationModel::GetSkills );\r\n\tNsProp( \"ProfSkills\", &PopulationModel::GetProfessionSkills );\r\n\r\n\tNsProp( \"CmdSkillUp\", &PopulationModel::GetProfSkillUpCmd );\r\n\tNsProp( \"CmdSkillDown\", &PopulationModel::GetProfSkillDownCmd );\r\n\tNsProp( \"CmdSkillAdd\", &PopulationModel::GetProfSkillAddCmd );\r\n\tNsProp( \"CmdSkillRemove\", &PopulationModel::GetProfSkillRemoveCmd );\r\n\tNsProp( \"ProfName\", &PopulationModel::GetProfName, &PopulationModel::SetProfName );\r\n\r\n\tNsProp( \"CmdProfNew\", &PopulationModel::GetNewProfCmd );\r\n\tNsProp( \"CmdProfDelete\", &PopulationModel::GetDeleteProfCmd );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( GnomeRow )\r\n{\r\n\tNsProp( \"Name\", &GnomeRow::GetName );\r\n\tNsProp( \"GnomeID\", &GnomeRow::GetID );\r\n\tNsProp( \"Skills\", &GnomeRow::GetSkills );\r\n\tNsProp( \"Professions\", &GnomeRow::GetProfessions );\r\n\tNsProp( \"Profession\", &GnomeRow::GetProfession, &GnomeRow::SetProfession );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( GnomeSkill )\r\n{\r\n\tNsProp( \"Name\", &GnomeSkill::GetName );\r\n\tNsProp( \"SkillID\", &GnomeSkill::GetID );\r\n\tNsProp( \"Level\", &GnomeSkill::GetLevel );\r\n\tNsProp( \"Checked\", &GnomeSkill::GetChecked, &GnomeSkill::SetChecked );\r\n\tNsProp( \"Color\", &GnomeSkill::GetColor );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( GnomeScheduleRow )\r\n{\r\n\tNsProp( \"Name\", &GnomeScheduleRow::GetName );\r\n\tNsProp( \"GnomeID\", &GnomeScheduleRow::GetID );\r\n\tNsProp( \"Schedule\", &GnomeScheduleRow::GetSchedule );\r\n\t\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( GnomeScheduleEntry )\r\n{\r\n\tNsProp( \"Activity\", &GnomeScheduleEntry::GetActivity );\r\n\tNsProp( \"CmdSetHour\", &GnomeScheduleEntry::GetSetHourCmd );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/PopulationModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __PopulationModel_H__\r\n#define __PopulationModel_H__\r\n\r\n#include \"../aggregatorpopulation.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\n\r\n#include <QString>\r\n\r\nclass PopulationProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\nenum class PopState\r\n{\r\n\tSkills,\r\n\tSchedule,\r\n\tProfEdit\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass ProfItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tProfItem( QString name );\r\n\r\n\tconst char* GetName() const;\r\n\tvoid SetName( const char* name );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\r\n\tNS_DECLARE_REFLECTION( ProfItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GnomeSkill : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tGnomeSkill( const GuiSkillInfo& skill, unsigned int gnomeID, PopulationProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetID() const;\r\n\tbool GetChecked() const;\r\n\tvoid SetChecked( bool value );\r\n\tconst char* GetLevel() const;\r\n\tconst char* GetColor() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_level = \"-1\";\r\n\tbool m_checked         = false;\r\n\tunsigned int m_gnomeID = 0;\r\n\tNoesis::String m_color;\r\n\tNoesis::String m_skillID;\r\n\r\n\tPopulationProxy* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( GnomeSkill, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GnomeRow : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGnomeRow( const GuiGnomeInfo& gnome, Noesis::Ptr<Noesis::ObservableCollection<ProfItem>> professions, PopulationProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetID() const;\r\n\r\n\tunsigned int gnomeID() { return m_id; }\r\n\r\n\tvoid updateProfessionList( Noesis::Ptr<Noesis::ObservableCollection<ProfItem>> professions );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tunsigned int m_id;\r\n\tNoesis::String m_idString;\r\n\tQString m_professionName;\r\n\r\n\tNoesis::ObservableCollection<GnomeSkill>* GetSkills() const\r\n\t{\r\n\t\treturn m_skills;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GnomeSkill>> m_skills;\r\n\r\n\tNoesis::ObservableCollection<ProfItem>* GetProfessions() const;\r\n\tvoid SetProfession( ProfItem* item );\r\n\tProfItem* GetProfession() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<ProfItem>> m_professions;\r\n\tProfItem* m_selectedProfession = nullptr;\r\n\r\n\r\n\tPopulationProxy* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( GnomeRow, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GnomeScheduleEntry : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGnomeScheduleEntry( unsigned int id, int hour, ScheduleActivity activity, PopulationProxy* proxy );\r\n\r\n\tPopulationProxy* m_proxy = nullptr;\r\n\r\n\tconst char* GetActivity() const;\r\n\t\r\nprivate:\r\n\tScheduleActivity m_activity;\r\n\tNoesis::String m_activityString;\r\n\tunsigned int m_id = 0;\r\n\tint m_hour = 0;\r\n\r\n\tvoid onSetHourCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSetHourCmd() const\r\n\t{\r\n\t\treturn &m_setHourCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_setHourCmd;\r\n\r\nNS_DECLARE_REFLECTION( GnomeScheduleEntry, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GnomeScheduleRow : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGnomeScheduleRow( const GuiGnomeScheduleInfo& gnome, PopulationProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetID() const;\r\n\r\n\tunsigned int gnomeID() { return m_id; }\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tunsigned int m_id;\r\n\tNoesis::String m_idString;\r\n\r\n\tNoesis::ObservableCollection<GnomeScheduleEntry>* GetSchedule() const\r\n\t{\r\n\t\treturn m_schedule;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GnomeScheduleEntry>> m_schedule;\r\n\r\n\tPopulationProxy* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( GnomeScheduleRow, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass PopulationModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tPopulationModel();\r\n\r\n\tvoid updateInfo( const GuiPopulationInfo& info );\r\n\tvoid updateProfessionList( const QStringList& professions );\r\n\tvoid updateProfessionSkills( const QString profession, const QList<GuiSkillInfo>& skills );\r\n\tvoid updateSingleGnome( const GuiGnomeInfo& gnome );\r\n\r\n\tvoid updateSchedules( const GuiScheduleInfo& info );\r\n\tvoid updateScheduleSingleGnome( const GuiGnomeScheduleInfo& info );\r\n\r\n\tvoid selectEditProfession( const QString name );\r\n\r\nprivate:\r\n\tPopulationProxy* m_proxy = nullptr;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<ProfItem>> m_professions;\r\n\tProfItem* m_selectedProfession = nullptr;\r\n\r\n\tNoesis::ObservableCollection<GnomeRow>* GetGnomes() const\r\n\t{\r\n\t\treturn m_gnomes;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GnomeRow>> m_gnomes;\r\n\r\n\tNoesis::ObservableCollection<GnomeSkill>* GetSkills() const\r\n\t{\r\n\t\treturn m_skills;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GnomeSkill>> m_skills;\r\n\r\n\tNoesis::ObservableCollection<GnomeSkill>* GetProfessionSkills() const\r\n\t{\r\n\t\treturn m_profSkills;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GnomeSkill>> m_profSkills;\r\n\r\n\r\n\tvoid onAllGnomesCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetAllGnomesCmd() const\r\n\t{\r\n\t\treturn &m_allGnomesCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_allGnomesCmd;\r\n\r\n\tvoid onRemoveAllGnomesCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetRemoveAllGnomesCmd() const\r\n\t{\r\n\t\treturn &m_removeAllGnomesCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_removeAllGnomesCmd;\r\n\r\n\tvoid onAllSkillsCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetAllSkillsCmd() const\r\n\t{\r\n\t\treturn &m_allSkillsCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_allSkillsCmd;\r\n\r\n\tvoid onRemoveAllSkillsCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetRemoveAllSkillsCmd() const\r\n\t{\r\n\t\treturn &m_removeAllSkillsCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_removeAllSkillsCmd;\r\n\r\n\tvoid onSortCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSortCmd() const\r\n\t{\r\n\t\treturn &m_sortCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_sortCmd;\r\n\r\n\tvoid onPageCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetPageCmd() const\r\n\t{\r\n\t\treturn &m_pageCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_pageCmd;\r\n\r\n\tvoid onSetActivityCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSetActivityCmd() const\r\n\t{\r\n\t\treturn &m_setActivityCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_setActivityCmd;\r\n\r\n\tconst char* GetShowSkills() const;\r\n\tconst char* GetShowSchedule() const;\r\n\tconst char* GetShowProfEdit() const;\r\n\r\n\tPopState m_state = PopState::Skills;\r\n\r\n\tScheduleActivity m_scheduleActivity = ScheduleActivity::None;\r\n\r\n\tNoesis::ObservableCollection<GnomeScheduleRow>* GetScheduleGnomes() const\r\n\t{\r\n\t\treturn m_scheduleGnomes;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GnomeScheduleRow>> m_scheduleGnomes;\r\n\r\n\tconst char* GetScheduleActivity() const;\r\n\r\n\tvoid onSetAllHoursCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSetAllHoursCmd() const\r\n\t{\r\n\t\treturn &m_setAllHoursCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_setAllHoursCmd;\r\n\r\n\tvoid onSetHoursForAllCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSetHoursForAllCmd() const\r\n\t{\r\n\t\treturn &m_setHoursForAllCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_setHoursForAllCmd;\r\n\r\n\r\n\tNoesis::ObservableCollection<ProfItem>* GetProfessions() const;\r\n\tvoid SetProfession( ProfItem* item );\r\n\tProfItem* GetProfession() const;\r\n\r\n\tvoid onProfSkillUpCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetProfSkillUpCmd() const\r\n\t{\r\n\t\treturn &m_profSkillUpCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_profSkillUpCmd;\r\n\r\n\tvoid onProfSkillDownCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetProfSkillDownCmd() const\r\n\t{\r\n\t\treturn &m_profSkillDownCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_profSkillDownCmd;\r\n\r\n\tvoid onProfSkillAddCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetProfSkillAddCmd() const\r\n\t{\r\n\t\treturn &m_profSkillAddCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_profSkillAddCmd;\r\n\r\n\tvoid onProfSkillRemoveCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetProfSkillRemoveCmd() const\r\n\t{\r\n\t\treturn &m_profSkillRemoveCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_profSkillRemoveCmd;\r\n\r\n\tbool m_lockProfessionEdit = false;\r\n\tvoid sendModifiedProfession();\r\n\r\n\tNoesis::String m_profName;\r\n\tconst char* GetProfName() const;\r\n\tvoid SetProfName( const char* value );\r\n\r\n\r\n\tvoid onNewProfCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetNewProfCmd() const\r\n\t{\r\n\t\treturn &m_newProfCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_newProfCmd;\r\n\r\n\tvoid onDeleteProfCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetDeleteProfCmd() const\r\n\t{\r\n\t\treturn &m_deleteProfCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_deleteProfCmd;\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( PopulationModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/ProxyGameView.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"ProxyGameView.h\"\r\n\r\n#include \"../aggregatoragri.h\"\r\n#include \"../aggregatortileinfo.h\"\r\n#include \"../aggregatorneighbors.h\"\r\n#include \"../aggregatorpopulation.h\"\r\n#include \"../aggregatorcreatureinfo.h\"\r\n#include \"../aggregatormilitary.h\"\r\n#include \"../aggregatorworkshop.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include \"ViewModel.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nProxyGameView::ProxyGameView( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector, &EventConnector::signalKeyEsc, this, &ProxyGameView::onKeyEscape, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalPropagateEscape, Global::eventConnector, &EventConnector::onPropagateEscape );\r\n\r\n\tconnect( Global::eventConnector, &EventConnector::signalTimeAndDate, this, &ProxyGameView::onTimeAndDate, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector, &EventConnector::signalKingdomInfo, this, &ProxyGameView::onKingdomInfo, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector, &EventConnector::signalViewLevel, this, &ProxyGameView::onViewLevel, Qt::QueuedConnection );\r\n\t\r\n\tconnect( Global::eventConnector, &EventConnector::signalHeartbeat, this, &ProxyGameView::onHeartbeat, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector, &EventConnector::signalUpdatePause, this, &ProxyGameView::onUpdatePause, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector, &EventConnector::signalUpdateGameSpeed, this, &ProxyGameView::onUpdateGameSpeed, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector, &EventConnector::signalBuild, this, &ProxyGameView::onBuild, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::signalShowTileInfo, this, &ProxyGameView::onShowTileInfo, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorStockpile(), &AggregatorStockpile::signalOpenStockpileWindow, this, &ProxyGameView::onOpenStockpileWindow, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalOpenWorkshopWindow, this, &ProxyGameView::onOpenWorkshopWindow, Qt::QueuedConnection );\r\n\t//connect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalShowAgri, this, &ProxyGameView::onOpenAgriWindow, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyGameView::signalCloseStockpileWindow, Global::eventConnector->aggregatorStockpile(), &AggregatorStockpile::onCloseWindow, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalCloseWorkshopWindow, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onCloseWindow, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalCloseAgricultureWindow, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onCloseWindow, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyGameView::signalRequestPopulationUpdate, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onRequestPopulationUpdate, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalRequestCreatureUpdate, Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::onRequestCreatureUpdate, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalRequestNeighborsUpdate, Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::onRequestNeighborsUpdate, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalRequestMissionsUpdate, Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::onRequestMissions, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyGameView::signalRequestMilitaryUpdate, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRequestMilitary, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalRequestInventoryUpdate, Global::eventConnector->aggregatorInventory(), &AggregatorInventory::onRequestCategories, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector, &EventConnector::signalEvent, this, &ProxyGameView::onEvent, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalEventAnswer, Global::eventConnector, &EventConnector::onAnswer, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyGameView::signalSetPaused, Global::eventConnector, &EventConnector::onSetPause, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalSetGameSpeed, Global::eventConnector, &EventConnector::onSetGameSpeed, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyGameView::signalSetRenderOptions, Global::eventConnector, &EventConnector::onSetRenderOptions, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector, &EventConnector::signalUpdateRenderOptions, this, &ProxyGameView::onUpdateRenderOptions, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyGameView::signalRequestBuildItems, Global::eventConnector->aggregatorInventory(), &AggregatorInventory::onRequestBuildItems, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorInventory(), &AggregatorInventory::signalBuildItems, this,  &ProxyGameView::onBuildItems, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorInventory(), &AggregatorInventory::signalWatchList, this,  &ProxyGameView::onWatchList, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalRequestCmdBuild, Global::eventConnector, &EventConnector::onCmdBuild, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalSetSelectionAction, Global::eventConnector, &EventConnector::onSetSelectionAction, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyGameView::signalHeartbeatResponse, Global::eventConnector, &EventConnector::onHeartbeatResponse, Qt::QueuedConnection );\r\n\t\r\n}\r\n\r\nProxyGameView::~ProxyGameView()\r\n{\r\n}\r\n\r\nvoid ProxyGameView::setParent( IngnomiaGUI::GameModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid ProxyGameView::onTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->setTimeAndDate( minute, hour, day, season, year, sunStatus );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onKingdomInfo( QString name, QString info1, QString info2, QString info3 )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateKingdomInfo( name, info1, info2, info3 );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onHeartbeat( int value )\r\n{\r\n\temit signalHeartbeatResponse(value);\r\n\r\n}\r\n\r\nvoid ProxyGameView::onViewLevel( int level )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->setViewLevel( level );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onUpdatePause( bool value )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updatePause( value );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onUpdateGameSpeed( GameSpeed speed )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateGameSpeed( speed );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onBuild()\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onBuild();\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onShowTileInfo( unsigned int tileID )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onShowTileInfo( tileID );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onOpenStockpileWindow( unsigned int stockpileID )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onShowStockpileInfo( stockpileID );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onOpenWorkshopWindow( unsigned int workshopID )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onShowWorkshopInfo( workshopID );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::onOpenAgriWindow( unsigned int ID )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onShowAgriculture( ID );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::closeStockpileWindow()\r\n{\r\n\temit signalCloseStockpileWindow();\r\n}\r\n\r\nvoid ProxyGameView::closeWorkshopWindow()\r\n{\r\n\temit signalCloseWorkshopWindow();\r\n}\r\n\r\nvoid ProxyGameView::closeAgricultureWindow()\r\n{\r\n\temit signalCloseAgricultureWindow();\r\n}\r\n\r\nvoid ProxyGameView::requestPopulationUpdate()\r\n{\r\n\temit signalRequestPopulationUpdate();\r\n}\r\n\r\nvoid ProxyGameView::requestNeighborsUpdate()\r\n{\r\n\temit signalRequestNeighborsUpdate();\r\n}\r\n\r\nvoid ProxyGameView::requestMissionsUpdate()\r\n{\r\n\temit signalRequestMissionsUpdate();\r\n}\r\n\r\nvoid ProxyGameView::requestCreatureUpdate( unsigned int id )\r\n{\r\n\temit signalRequestCreatureUpdate( id );\r\n}\r\n\r\nvoid ProxyGameView::onEvent( unsigned int id, QString title, QString msg, bool pause, bool yesno )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->eventMessage( id, title, msg, pause, yesno );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::sendEventAnswer( unsigned int eventID, bool answer )\r\n{\r\n\temit signalEventAnswer( eventID, answer );\r\n}\r\n\r\nvoid ProxyGameView::requestMilitaryUpdate()\r\n{\r\n\temit signalRequestMilitaryUpdate();\r\n}\r\n\r\nvoid ProxyGameView::requestInventoryUpdate()\r\n{\r\n\temit signalRequestInventoryUpdate();\r\n}\r\n\r\n\r\nvoid ProxyGameView::onKeyEscape()\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->OnCmdBack( nullptr );\r\n\t}\r\n}\r\n\t\r\nvoid ProxyGameView::propagateEscape()\r\n{\r\n\temit signalPropagateEscape();\r\n}\r\n\r\nvoid ProxyGameView::setGameSpeed( GameSpeed speed )\r\n{\r\n\temit signalSetGameSpeed( speed );\r\n}\r\n\t\r\nvoid ProxyGameView::setPaused( bool paused )\r\n{\r\n\temit signalSetPaused( paused );\r\n}\r\n\r\nvoid ProxyGameView::setRenderOptions( bool designations, bool jobs, bool walls, bool axles )\r\n{\r\n\temit signalSetRenderOptions( designations, jobs, walls, axles );\r\n}\r\n\r\nvoid ProxyGameView::onUpdateRenderOptions( bool designation, bool jobs, bool walls, bool axles )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateRenderOptions( designation, jobs, walls, axles );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::requestBuildItems( BuildSelection buildSelection, QString category )\r\n{\r\n\temit signalRequestBuildItems( buildSelection, category );\r\n}\r\n\r\nvoid ProxyGameView::onBuildItems( const QList<GuiBuildItem>& items )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateBuildItems( items );\r\n\t}\r\n}\r\n\r\nvoid ProxyGameView::requestCmdBuild( BuildItemType type, QString param, QString item, QStringList mats )\r\n{\r\n\temit signalRequestCmdBuild( type, param, item, mats );\r\n}\r\n\r\nvoid ProxyGameView::setSelectionAction( QString action )\r\n{\r\n\temit signalSetSelectionAction( action );\r\n}\r\n\r\nvoid ProxyGameView::onWatchList( const QList<GuiWatchedItem>& watchlist )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateWatchList( watchlist );\r\n\t}\r\n}"
  },
  {
    "path": "src/gui/xaml/ProxyGameView.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"GameModel.h\"\r\n\r\n#include \"../aggregatorinventory.h\"\r\n\r\n#include <QObject>\r\n\r\nclass ProxyGameView : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tProxyGameView( QObject* parent = nullptr );\r\n\t~ProxyGameView();\r\n\r\n\tvoid setParent( IngnomiaGUI::GameModel* parent );\r\n\r\n\tvoid closeStockpileWindow();\r\n\tvoid closeWorkshopWindow();\r\n\tvoid closeAgricultureWindow();\r\n\tvoid requestPopulationUpdate();\r\n\tvoid requestNeighborsUpdate();\r\n\tvoid requestMissionsUpdate();\r\n\tvoid requestCreatureUpdate( unsigned int id );\r\n\tvoid requestMilitaryUpdate();\r\n\tvoid requestInventoryUpdate();\r\n\r\n\tvoid sendEventAnswer( unsigned int eventID, bool answer );\r\n\r\n\tvoid propagateEscape();\r\n\r\n\tvoid setGameSpeed( GameSpeed speed );\r\n\tvoid setPaused( bool paused );\r\n\r\n\tvoid setRenderOptions( bool designations, bool jobs, bool walls, bool axels );\r\n\r\n\tvoid setSelectionAction( QString action );\r\n\r\n\tvoid requestBuildItems( BuildSelection buildSelection, QString category );\r\n\tvoid requestCmdBuild( BuildItemType type, QString param, QString item, QStringList mats );\r\n\r\nprivate:\r\n\tIngnomiaGUI::GameModel* m_parent = nullptr;\r\n\r\nprivate slots:\r\n\tvoid onTimeAndDate( int minute, int hour, int day, QString season, int year, QString sunStatus );\r\n\tvoid onKingdomInfo( QString name, QString info1, QString info2, QString info3 );\r\n\tvoid onViewLevel( int level );\r\n\t\r\n\tvoid onHeartbeat( int value );\r\n\r\n\tvoid onUpdatePause( bool value );\r\n\tvoid onUpdateGameSpeed( GameSpeed speed );\r\n\r\n\tvoid onShowTileInfo( unsigned int tileID );\r\n\r\n\tvoid onBuild();\r\n\r\n\tvoid onOpenStockpileWindow( unsigned int stockpileID );\r\n\tvoid onOpenWorkshopWindow( unsigned int workshopID );\r\n\tvoid onOpenAgriWindow( unsigned int ID );\r\n\r\n\tvoid onEvent( unsigned int id, QString title, QString msg, bool pause, bool yesno );\r\n\r\n\tvoid onKeyEscape();\r\n\tvoid onUpdateRenderOptions( bool designation, bool jobs, bool walls, bool axles );\r\n\r\n\tvoid onBuildItems( const QList<GuiBuildItem>& items );\r\n\r\n\tvoid onWatchList( const QList<GuiWatchedItem>& watchedItemList );\r\n\r\nsignals:\r\n\tvoid signalCloseStockpileWindow();\r\n\tvoid signalCloseWorkshopWindow();\r\n\tvoid signalCloseAgricultureWindow();\r\n\tvoid signalRequestPopulationUpdate();\r\n\tvoid signalRequestNeighborsUpdate();\r\n\tvoid signalRequestMissionsUpdate();\r\n\tvoid signalRequestCreatureUpdate( unsigned int id );\r\n\tvoid signalEventAnswer( unsigned int eventID, bool answer );\r\n\tvoid signalRequestMilitaryUpdate();\r\n\tvoid signalRequestInventoryUpdate();\r\n\tvoid signalPropagateEscape();\r\n\tvoid signalSetGameSpeed( GameSpeed speed );\r\n\tvoid signalSetPaused( bool paused );\r\n\tvoid signalSetRenderOptions( bool designations, bool jobs, bool walls, bool axles );\r\n\r\n\tvoid signalRequestBuildItems( BuildSelection buildSelection, QString category );\r\n\tvoid signalRequestCmdBuild( BuildItemType type, QString param, QString item, QStringList mats );\r\n\tvoid signalSetSelectionAction( QString action );\r\n\t\r\n\tvoid signalHeartbeatResponse( int value );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/ProxyMainView.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"ProxyMainView.h\"\r\n\r\n#include \"../../base/global.h\"\r\n\r\n#include \"../aggregatorloadgame.h\"\r\n#include \"../aggregatorsettings.h\"\r\n#include \"../eventconnector.h\"\r\n#include \"ViewModel.h\"\r\n\r\nProxyMainView::ProxyMainView( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector, &EventConnector::signalWindowSize, this, &ProxyMainView::onWindowSize, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector, &EventConnector::signalPropagateKeyEsc, this, &ProxyMainView::onKeyEsc, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorSettings(), &AggregatorSettings::signalUIScale, this, &ProxyMainView::onUIScale, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyMainView::signalRequestLoadScreenUpdate, Global::eventConnector->aggregatorLoadGame(), &AggregatorLoadGame::onRequestKingdoms );\r\n\r\n\tconnect( this, &ProxyMainView::signalRequestUIScale, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onRequestUIScale, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyMainView::signalRequestVersion, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onRequestVersion, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorSettings(), &AggregatorSettings::signalVersion, this, &ProxyMainView::onVersion, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyMainView::signalStartNewGame, Global::eventConnector, &EventConnector::onStartNewGame, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyMainView::signalContinueLastGame, Global::eventConnector, &EventConnector::onContinueLastGame, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyMainView::signalLoadGame, Global::eventConnector, &EventConnector::onLoadGame, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyMainView::signalSaveGame, Global::eventConnector, &EventConnector::onSaveGame, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyMainView::signalSetShowMainMenu, Global::eventConnector, &EventConnector::onSetShowMainMenu, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyMainView::signalEndGame, Global::eventConnector, &EventConnector::onEndGame, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector, &EventConnector::signalResume, this, &ProxyMainView::onResume, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector, &EventConnector::signalLoadGameDone, this, &ProxyMainView::onLoadGameDone, Qt::QueuedConnection );\r\n}\r\n\r\nProxyMainView::~ProxyMainView()\r\n{\r\n}\r\n\r\nvoid ProxyMainView::setParent( IngnomiaGUI::ViewModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid ProxyMainView::onWindowSize( int w, int h )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->setWindowSize( w, h );\r\n\t}\r\n}\r\n\r\nvoid ProxyMainView::onKeyEsc()\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->OnBack( nullptr );\r\n\t}\r\n}\r\n\r\nvoid ProxyMainView::onUIScale( float value )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->setUIScale( value );\r\n\t}\r\n}\r\n\r\nvoid ProxyMainView::requestLoadScreenUpdate()\r\n{\r\n\temit signalRequestLoadScreenUpdate();\r\n}\r\n\r\nvoid ProxyMainView::requestUIScale()\r\n{\r\n\temit signalRequestUIScale();\r\n}\r\n\r\nvoid ProxyMainView::startNewGame()\r\n{\r\n\temit signalStartNewGame();\r\n}\r\n\t\r\nvoid ProxyMainView::continueLastGame()\r\n{\r\n\temit signalContinueLastGame();\r\n}\r\n\r\nvoid ProxyMainView::loadGame( QString param )\r\n{\r\n\temit signalLoadGame( param );\r\n}\r\n\r\nvoid ProxyMainView::saveGame()\r\n{\r\n\temit signalSaveGame();\r\n}\r\n\r\nvoid ProxyMainView::setShowMainMenu( bool value )\r\n{\r\n\temit signalSetShowMainMenu( value );\r\n}\r\n\r\nvoid ProxyMainView::onResume()\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->OnResume();\r\n\t}\r\n}\r\n\r\nvoid ProxyMainView::onLoadGameDone( bool value )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->OnContinueGameFinished( value );\r\n\t}\r\n}\r\n\r\nvoid ProxyMainView::endGame()\r\n{\r\n\temit signalEndGame();\r\n}\r\n\r\nvoid ProxyMainView::requestVersion()\r\n{\r\n\temit signalRequestVersion();\r\n}\r\n\r\nvoid ProxyMainView::onVersion( QString version )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateVersion( version );\r\n\t}\r\n}"
  },
  {
    "path": "src/gui/xaml/ProxyMainView.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"ViewModel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass ProxyMainView : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tProxyMainView( QObject* parent = nullptr );\r\n\t~ProxyMainView();\r\n\r\n\tvoid setParent( IngnomiaGUI::ViewModel* parent );\r\n\r\n\tvoid requestLoadScreenUpdate();\r\n\tvoid requestUIScale();\r\n\tvoid requestVersion();\r\n\r\n\tvoid startNewGame();\r\n\tvoid continueLastGame();\r\n\tvoid loadGame( QString param );\r\n\tvoid saveGame();\r\n\tvoid setShowMainMenu( bool value );\r\n\r\n\tvoid endGame();\r\n\r\nprivate:\r\n\tIngnomiaGUI::ViewModel* m_parent = nullptr;\r\n\r\nprivate slots:\r\n\tvoid onWindowSize( int w, int h );\r\n\tvoid onKeyEsc();\r\n\r\n\tvoid onUIScale( float value );\r\n\r\n\tvoid onResume();\r\n\tvoid onLoadGameDone( bool value );\r\n\tvoid onVersion( QString version );\r\n\r\nsignals:\r\n\tvoid signalRequestLoadScreenUpdate();\r\n\tvoid signalRequestUIScale();\r\n\tvoid signalRequestVersion();\r\n\r\n\tvoid signalStartNewGame();\r\n\tvoid signalContinueLastGame();\r\n\tvoid signalLoadGame( QString param );\r\n\tvoid signalSaveGame();\r\n\tvoid signalSetShowMainMenu( bool value );\r\n\tvoid signalEndGame();\r\n\t\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/ProxyTileInfo.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"ProxyTileInfo.h\"\r\n\r\n#include \"../../base/db.h\"\r\n#include \"../../base/gamestate.h\"\r\n#include \"../../gfx/sprite.h\"\r\n#include \"../../gfx/spritefactory.h\"\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n#include \"TileInfoModel.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nProxyTileInfo::ProxyTileInfo( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::signalUpdateTileInfo, this, &ProxyTileInfo::onUpdateTileInfo, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyTileInfo::signalTerrainCommand, Global::eventConnector, &EventConnector::onTerrainCommand, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyTileInfo::signalManageCommand, Global::eventConnector, &EventConnector::onManageCommand, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyTileInfo::signalRequestStockpileItems, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onRequestStockpileItems, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyTileInfo::signalSetTennant, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onSetTennant, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyTileInfo::signalSetAlarm, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onSetAlarm, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::signalUpdateSPInfo, this,  &ProxyTileInfo::onUpdateStockpileInfo, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyTileInfo::signalToggleMechActive, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onToggleMechActive, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyTileInfo::signalToggleMechInvert, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onToggleMechInvert, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &ProxyTileInfo::signalSetAutomatonRefuel, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onSetAutomatonRefuel, Qt::QueuedConnection );\r\n\tconnect( this, &ProxyTileInfo::signalSetAutomatonCore, Global::eventConnector->aggregatorTileInfo(), &AggregatorTileInfo::onSetAutomatonCore, Qt::QueuedConnection );\r\n}\r\n\r\nProxyTileInfo::~ProxyTileInfo()\r\n{\r\n}\r\n\r\nvoid ProxyTileInfo::setParent( IngnomiaGUI::TileInfoModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid ProxyTileInfo::onUpdateTileInfo( const GuiTileInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onUpdateTileInfo( info );\r\n\t}\r\n}\r\n\r\nvoid ProxyTileInfo::sendTerrainCommand( unsigned int tileID, QString cmd )\r\n{\r\n\temit signalTerrainCommand( tileID, cmd );\r\n}\r\n\r\nvoid ProxyTileInfo::sendManageCommand( unsigned int tileID )\r\n{\r\n\temit signalManageCommand( tileID );\r\n}\r\n\r\nvoid ProxyTileInfo::requestStockpileItems( unsigned int tileID )\r\n{\r\n\temit signalRequestStockpileItems( tileID );\r\n}\r\n\r\nvoid ProxyTileInfo::onUpdateStockpileInfo( const GuiStockpileInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateMiniStockpile( info );\r\n\t}\r\n}\r\n\r\nvoid ProxyTileInfo::setTennant( unsigned int designationID, unsigned int gnomeID )\r\n{\r\n\temit signalSetTennant( designationID, gnomeID );\r\n}\r\n\r\nvoid ProxyTileInfo::setAlarm( unsigned int designationID, bool value )\r\n{\r\n\temit signalSetAlarm( designationID, value );\r\n}\r\n\r\nvoid ProxyTileInfo::toggleMechActive( unsigned int id )\r\n{\r\n\temit signalToggleMechActive( id );\r\n}\r\n\t\r\nvoid ProxyTileInfo::toggleMechInvert( unsigned int id )\r\n{\r\n\temit signalToggleMechInvert( id );\r\n}\r\n\r\nvoid ProxyTileInfo::setAutomatonRefuel( unsigned int id, bool refuel )\r\n{\r\n\r\n\temit signalSetAutomatonRefuel( id, refuel );\r\n}\r\n\t\r\nvoid ProxyTileInfo::setAutomatonCore( unsigned int id, QString core )\r\n{\r\n\temit signalSetAutomatonCore( id, core );\r\n}"
  },
  {
    "path": "src/gui/xaml/ProxyTileInfo.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatortileinfo.h\"\r\n#include \"TileInfoModel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass ProxyTileInfo : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tProxyTileInfo( QObject* parent = nullptr );\r\n\t~ProxyTileInfo();\r\n\r\n\tvoid setParent( IngnomiaGUI::TileInfoModel* parent );\r\n\r\n\tvoid sendTerrainCommand( unsigned int tileID, QString cmd );\r\n\tvoid sendManageCommand( unsigned int tileID );\r\n\r\n\tvoid requestStockpileItems( unsigned int tileID );\r\n\r\n\tvoid setTennant( unsigned int designationID, unsigned int gnomeID );\r\n\tvoid setAlarm( unsigned int designationID, bool value );\r\n\r\n\tvoid toggleMechActive( unsigned int id );\r\n\tvoid toggleMechInvert( unsigned int id );\r\n\r\n\tvoid setAutomatonRefuel( unsigned int id, bool refuel );\r\n\tvoid setAutomatonCore( unsigned int id, QString core );\r\n\r\nprivate:\r\n\tIngnomiaGUI::TileInfoModel* m_parent = nullptr;\r\n\r\nprivate slots:\r\n\tvoid onUpdateTileInfo( const GuiTileInfo& info );\r\n\tvoid onUpdateStockpileInfo( const GuiStockpileInfo& info );\r\n\r\nsignals:\r\n\tvoid signalTerrainCommand( unsigned int tileID, QString cmd );\r\n\tvoid signalManageCommand( unsigned int tileID );\r\n\tvoid signalRequestStockpileItems( unsigned int tileID );\r\n\tvoid signalSetTennant( unsigned int designationID, unsigned int gnomeID );\r\n\tvoid signalSetAlarm( unsigned int designationID, bool value );\r\n\tvoid signalToggleMechActive( unsigned int id );\r\n\tvoid signalToggleMechInvert( unsigned int id );\r\n\r\n\tvoid signalSetAutomatonRefuel( unsigned int id, bool refuel );\r\n\tvoid signalSetAutomatonCore( unsigned int id, QString core );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/SettingsModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"SettingsModel.h\"\r\n#include \"settingsproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nLanguageEntry::LanguageEntry( QString name ) :\r\n\tm_name( name.toStdString().c_str() )\r\n{\r\n}\r\n\r\nconst char* LanguageEntry::getName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nScaleEntry::ScaleEntry( QString name, float scale ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n    m_scale( scale )\r\n{\r\n}\r\n\r\nconst char* ScaleEntry::getName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSettingsModel::SettingsModel()\r\n{\r\n    m_proxy = new SettingsProxy;\r\n\tm_proxy->setParent( this );\r\n     \r\n    m_languages = *new ObservableCollection<LanguageEntry>();\r\n    m_proxy->requestSettings();\r\n\r\n    m_scales = *new ObservableCollection<ScaleEntry>();\r\n}\r\n\r\nvoid SettingsModel::updateSettings( const GuiSettings& settings )\r\n{\r\n    m_languages->Clear();  \r\n    for( auto lang : settings.languages )\r\n\t{\r\n        m_languages->Add( MakePtr<LanguageEntry>( lang ) );\r\n\t}\r\n\r\n    if( settings.languages.contains( settings.language ) )\r\n    {\r\n        setLanguage( m_languages->Get( settings.languages.indexOf( settings.language ) ) );\r\n    }\r\n\telse\r\n\t{\r\n        setLanguage( m_languages->Get( 0 ) );\r\n\t}\r\n\r\n    m_scale = settings.scale;\r\n    m_scales->Add( MakePtr<ScaleEntry>( \"50%\", 0.5f ) );\r\n    m_scales->Add( MakePtr<ScaleEntry>( \"75%\", 0.75f ) );\r\n    m_scales->Add( MakePtr<ScaleEntry>( \"100%\", 1.f ) );\r\n    m_scales->Add( MakePtr<ScaleEntry>( \"150%\", 1.5f ) );\r\n    m_scales->Add( MakePtr<ScaleEntry>( \"200%\", 2.0f ) );\r\n\r\n    if( m_scale < 0.75 ) setScale( m_scales->Get( 0 ) );\r\n\telse if( m_scale < 1.0 ) setScale( m_scales->Get( 1 ) );\r\n    else if( m_scale < 1.5 ) setScale( m_scales->Get( 2 ) );\r\n    else if( m_scale < 2.0 ) setScale( m_scales->Get( 3 ) );\r\n    else setScale( m_scales->Get( 4 ) );\r\n\r\n    m_fullScreen = settings.fullscreen;\r\n    m_keyboardSpeed = settings.keyboardSpeed;\r\n    m_lightMin = settings.lightMin;\r\n    m_toggleMouseWheel = settings.toggleMouseWheel;\r\n\tm_audioMasterVolume = settings.audioMasterVolume;\r\n\r\n    OnPropertyChanged( \"Languages\" );\r\n    OnPropertyChanged( \"SelectedLanguage\" );\r\n    OnPropertyChanged( \"UIScale\" );\r\n    OnPropertyChanged( \"UIScales\" );\r\n    OnPropertyChanged( \"KeyboardSpeed\" );\r\n    OnPropertyChanged( \"FullScreen\" );\r\n    OnPropertyChanged( \"LightMin\" );\r\n    OnPropertyChanged( \"MouseWheelBehavior\" );\r\n\tOnPropertyChanged( \"AudioMasterVolume\" );\r\n}\r\n\r\n    \r\nNoesis::ObservableCollection<LanguageEntry>* SettingsModel::getLanguages() const\r\n{\r\n    return m_languages;\r\n}\r\n\r\nvoid SettingsModel::setLanguage( LanguageEntry* item )\r\n{\r\n    if( item && m_selectedLanguage != item )\r\n\t{\r\n        m_selectedLanguage = item;\r\n        m_proxy->setLanguage( item->getName() );\r\n\t}\r\n}\r\n\r\nLanguageEntry* SettingsModel::getLanguage() const\r\n{\r\n    return m_selectedLanguage;\r\n}\r\n\r\nNoesis::ObservableCollection<ScaleEntry>* SettingsModel::getScales() const\r\n{\r\n    return m_scales;\r\n}\r\n\t\r\nvoid SettingsModel::setScale( ScaleEntry* item )\r\n{\r\n    if( item && m_selectedScale != item )\r\n\t{\r\n        m_selectedScale = item;\r\n        m_proxy->setUIScale( item->m_scale );\r\n\t}\r\n}\r\n\r\nScaleEntry* SettingsModel::getScale() const\r\n{\r\n    return m_selectedScale;\r\n}\r\n    \r\n\r\n\r\n\r\nbool SettingsModel::getFullScreen() const\r\n{\r\n    return m_fullScreen;\r\n}\r\n\r\nvoid SettingsModel::setFullScreen( bool value )\r\n{\r\n    if( value != m_fullScreen )\r\n\t{\r\n\t    m_fullScreen = value;\r\n        m_proxy->setFullScreen( value );\r\n    }\r\n}\r\n\r\n    \r\nint SettingsModel::getKeyboardSpeed() const\r\n{\r\n    return m_keyboardSpeed;\r\n}\r\n\r\nvoid SettingsModel::setKeyboardSpeed( int value )\r\n{\r\n    if( value != m_keyboardSpeed )\r\n\t{\r\n        m_keyboardSpeed = value;\r\n        m_proxy->setKeyboardSpeed( value );\r\n\t}\r\n}\r\n\r\nint SettingsModel::getLightMin() const\r\n{\r\n    return m_lightMin;\r\n}\r\n\r\nvoid SettingsModel::setLightMin( int value )\r\n{\r\n    if( value != m_lightMin )\r\n\t{\r\n        m_lightMin = value;\r\n        m_proxy->setLightMin( value );\r\n\t}\r\n}\r\n\r\n    \r\nbool SettingsModel::getMouseWheelBehavior() const\r\n{\r\n    return m_toggleMouseWheel;\r\n}\r\n\r\nvoid SettingsModel::setMouseWheelBehavior( bool value )\r\n{\r\n    if( value != m_toggleMouseWheel )\r\n\t{\r\n\t    m_toggleMouseWheel = value;\r\n        m_proxy->setToggleMouseWheel( value );\r\n    }\r\n}\r\n\r\nfloat SettingsModel::getAudioMasterVolume() const\r\n{\r\n\treturn m_audioMasterVolume;\r\n}\r\n\r\nvoid SettingsModel::setAudioMasterVolume( float value )\r\n{\r\n\tm_audioMasterVolume = value;\r\n\tm_proxy->setAudioMasterVolume( value );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( SettingsModel, \"IngnomiaGUI.SettingsModel\" )\r\n{\r\n    NsProp( \"Languages\", &SettingsModel::getLanguages );\r\n    NsProp( \"SelectedLanguage\", &SettingsModel::getLanguage, &SettingsModel::setLanguage );\r\n    NsProp( \"UIScales\", &SettingsModel::getScales );\r\n    NsProp( \"UIScale\", &SettingsModel::getScale, &SettingsModel::setScale );\r\n    NsProp( \"KeyboardSpeed\", &SettingsModel::getKeyboardSpeed, &SettingsModel::setKeyboardSpeed );\r\n    NsProp( \"FullScreen\", &SettingsModel::getFullScreen, &SettingsModel::setFullScreen );\r\n    NsProp( \"LightMin\", &SettingsModel::getLightMin, &SettingsModel::setLightMin );\r\n    NsProp( \"MouseWheelBehavior\", &SettingsModel::getMouseWheelBehavior, &SettingsModel::setMouseWheelBehavior );\r\n\tNsProp( \"AudioMasterVolume\", &SettingsModel::getAudioMasterVolume, &SettingsModel::setAudioMasterVolume );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( LanguageEntry )\r\n{\r\n\tNsProp( \"Name\", &LanguageEntry::getName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( ScaleEntry )\r\n{\r\n\tNsProp( \"Name\", &ScaleEntry::getName );\r\n}"
  },
  {
    "path": "src/gui/xaml/SettingsModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __SETTINGSMODEL_H__\r\n#define __SETTINGSMODEL_H__\r\n\r\n#include \"../aggregatorsettings.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\n#include <QString>\r\n\r\nclass SettingsProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\nstruct LanguageEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tLanguageEntry( QString name );\r\n\r\n\tNoesis::String m_name;\r\n\r\n    const char* getName() const;\r\n\t\r\n\tNS_DECLARE_REFLECTION( LanguageEntry, BaseComponent )\r\n};\r\n\r\nstruct ScaleEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tScaleEntry( QString name, float scale );\r\n\r\n\tNoesis::String m_name;\r\n    float m_scale;\r\n\r\n    const char* getName() const;\r\n\t\r\n\tNS_DECLARE_REFLECTION( ScaleEntry, BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SettingsModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tSettingsModel();\r\n\r\n    void updateSettings( const GuiSettings& settings );\r\n\r\nprivate:\r\n    SettingsProxy* m_proxy = nullptr;\r\n\r\n    Noesis::ObservableCollection<LanguageEntry>* getLanguages() const;\r\n\tvoid setLanguage( LanguageEntry* item );\r\n\tLanguageEntry* getLanguage() const;\r\n\r\n    Noesis::ObservableCollection<ScaleEntry>* getScales() const;\r\n\tvoid setScale( ScaleEntry* item );\r\n\tScaleEntry* getScale() const;\r\n\r\n    bool getFullScreen() const;\r\n\tvoid setFullScreen( bool value );\r\n\r\n    int getKeyboardSpeed() const;\r\n\tvoid setKeyboardSpeed( int value );\r\n\r\n    int getLightMin() const;\r\n\tvoid setLightMin( int value );\r\n\r\n    bool getMouseWheelBehavior() const;\r\n\tvoid setMouseWheelBehavior( bool value );\r\n\t\r\n\tfloat getAudioMasterVolume() const;\r\n\tvoid setAudioMasterVolume( float value );\r\n\r\n    Noesis::Ptr<Noesis::ObservableCollection<LanguageEntry>> m_languages;\r\n    LanguageEntry* m_selectedLanguage = nullptr;;\r\n\r\n    Noesis::Ptr<Noesis::ObservableCollection<ScaleEntry>> m_scales;\r\n    ScaleEntry* m_selectedScale = nullptr;;\r\n\r\n    float m_scale = 1.0f;\r\n    bool m_fullScreen = false;\r\n    bool m_toggleMouseWheel = false;\r\n    int m_keyboardSpeed = 20;\r\n    int m_lightMin = 30;\r\n\t float m_audioMasterVolume = 50.0f;\r\n\r\n\tNS_DECLARE_REFLECTION( SettingsModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/SettingsPage.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"SettingsPage.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSettingsPage::SettingsPage()\r\n{\r\n\tLoaded() += MakeDelegate( this, &SettingsPage::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid SettingsPage::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"SettingsPage.xaml\" );\r\n}\r\n\r\nbool SettingsPage::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid SettingsPage::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::SettingsPage, \"IngnomiaGUI.SettingsPage\" )\r\n"
  },
  {
    "path": "src/gui/xaml/SettingsPage.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __SettingsPage_H__\r\n#define __SettingsPage_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SettingsPage final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tSettingsPage();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( SettingsPage, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/StockpileModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"StockpileModel.h\"\r\n\r\n#include \"../../base/filter.h\"\r\n#include \"StockpileProxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\nGuiLimitItem::GuiLimitItem( QString name )\r\n{\r\n\tm_name = name.toStdString().c_str();\r\n}\r\n\r\nconst char* GuiLimitItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nStockedItemSummary::StockedItemSummary( QString name )\r\n{\r\n\tm_name = name.toStdString().c_str();\r\n}\r\n\r\nconst char* StockedItemSummary::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\n#pragma region MaterialItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::MaterialItem::MaterialItem( unsigned int stockpileID, QString name, QString sid, QString cat, QString group, QString item, Filter& filter, StockpileProxy* proxy ) :\r\n\tm_stockpileID( stockpileID ),\r\n\tm_proxy( proxy ),\r\n\tm_sid( sid ),\r\n\tm_category( cat ),\r\n\tm_group( group ),\r\n\tm_item( item )\r\n{\r\n\tm_name   = name.toStdString().c_str();\r\n\tm_active = filter.getCheckState( cat, group, item, sid );\r\n}\r\n\r\nconst char* IngnomiaGUI::MaterialItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nbool IngnomiaGUI::MaterialItem::GetChecked() const\r\n{\r\n\treturn m_active;\r\n}\r\n\r\nvoid IngnomiaGUI::MaterialItem::SetChecked( bool value )\r\n{\r\n\tif ( m_active != value )\r\n\t{\r\n\t\tm_proxy->setActive( m_stockpileID, value, m_category, m_group, m_item, m_sid );\r\n\t}\r\n}\r\n\r\nvoid IngnomiaGUI::MaterialItem::UpdateChecked( Filter& filter )\r\n{\r\n\tif ( filter.getCheckState( m_category, m_group, m_item, m_sid ) != m_active )\r\n\t{\r\n\t\tm_active = !m_active;\r\n\t\tOnPropertyChanged( \"Checked\" );\r\n\t\tOnPropertyChanged( \"Expanded\" );\r\n\t}\r\n}\r\n\r\n#pragma endregion MaterialItem\r\n\r\n#pragma region ItemItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::ItemItem::ItemItem( unsigned int stockpileID, QString name, QString sid, QString cat, QString group, Filter& filter, StockpileProxy* proxy ) :\r\n\tm_stockpileID( stockpileID ),\r\n\tm_proxy( proxy ),\r\n\tm_sid( sid ),\r\n\tm_category( cat ),\r\n\tm_group( group )\r\n{\r\n\tm_name = name.toStdString().c_str();\r\n\r\n\tm_materials = *new ObservableCollection<MaterialItem>();\r\n\r\n\tfor ( auto mat : filter.materials( cat, group, sid ) )\r\n\t{\r\n\t\tm_materials->Add( MakePtr<MaterialItem>( m_stockpileID, mat, mat, cat, group, sid, filter, proxy ) );\r\n\t}\r\n\r\n\tUpdateState();\r\n}\r\n\r\nconst char* IngnomiaGUI::ItemItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst Noesis::Nullable<bool>& IngnomiaGUI::ItemItem::GetState() const\r\n{\r\n\treturn m_state;\r\n}\r\n\r\nbool IngnomiaGUI::ItemItem::getExpanded() const\r\n{\r\n\treturn !GetState().HasValue();\r\n}\r\n\r\nvoid IngnomiaGUI::ItemItem::SetState( const Noesis::Nullable<bool>& value )\r\n{\r\n\tbool active = value.HasValue() && value.GetValue();\r\n\tm_proxy->setActive( m_stockpileID, active, m_category, m_group, m_sid );\r\n}\r\n\r\nvoid IngnomiaGUI::ItemItem::UpdateChecked( Filter& filter )\r\n{\r\n\tauto mats = filter.materials( m_category, m_group, m_sid );\r\n\r\n\tfor ( int i = 0; i < m_materials->Count(); ++i )\r\n\t{\r\n\t\tm_materials->Get( i )->UpdateChecked( filter );\r\n\t}\r\n\tUpdateState();\r\n}\r\n\r\nvoid IngnomiaGUI::ItemItem::UpdateState()\r\n{\r\n\tbool allChecked   = true;\r\n\tbool allUnchecked = true;\r\n\tfor ( int i = 0; i < m_materials->Count(); ++i )\r\n\t{\r\n\t\tbool checked = m_materials->Get( i )->GetChecked();\r\n\t\tif ( checked != true )\r\n\t\t{\r\n\t\t\tallChecked = false;\r\n\t\t}\r\n\t\telse if ( checked != false )\r\n\t\t{\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t}\r\n\tif ( allChecked && !allUnchecked )\r\n\t{\r\n\t\tm_state = true;\r\n\t}\r\n\telse if ( !allChecked && allUnchecked )\r\n\t{\r\n\t\tm_state = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = nullptr;\r\n\t}\r\n\r\n\tOnPropertyChanged( \"Checked\" );\r\n\tOnPropertyChanged( \"Expanded\" );\r\n}\r\n\r\n#pragma endregion ItemItem\r\n\r\n#pragma region GroupItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::GroupItem::GroupItem( unsigned int stockpileID, QString name, QString sid, QString cat, Filter& filter, StockpileProxy* proxy ) :\r\n\tm_stockpileID( stockpileID ),\r\n\tm_proxy( proxy ),\r\n\tm_sid( sid ),\r\n\tm_category( cat )\r\n{\r\n\tm_name = name.toStdString().c_str();\r\n\r\n\tm_items = *new ObservableCollection<ItemItem>();\r\n\r\n\tfor ( auto item : filter.items( cat, sid ) )\r\n\t{\r\n\t\tm_items->Add( MakePtr<ItemItem>( m_stockpileID, item, item, cat, sid, filter, proxy ) );\r\n\t}\r\n\r\n\tUpdateState();\r\n}\r\n\r\nconst char* IngnomiaGUI::GroupItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst Noesis::Nullable<bool>& IngnomiaGUI::GroupItem::GetState() const\r\n{\r\n\treturn m_state;\r\n}\r\n\r\nbool IngnomiaGUI::GroupItem::getExpanded() const\r\n{\r\n\treturn !GetState().HasValue();\r\n}\r\n\r\nvoid IngnomiaGUI::GroupItem::SetState( const Noesis::Nullable<bool>& value )\r\n{\r\n\tbool active = value.HasValue() && value.GetValue();\r\n\tm_proxy->setActive( m_stockpileID, active, m_category, m_sid );\r\n}\r\n\r\nvoid IngnomiaGUI::GroupItem::UpdateChecked( Filter& filter )\r\n{\r\n\tauto items = filter.items( m_category, m_sid );\r\n\r\n\tfor ( int i = 0; i < m_items->Count(); ++i )\r\n\t{\r\n\t\tm_items->Get( i )->UpdateChecked( filter );\r\n\t}\r\n\r\n\tUpdateState();\r\n}\r\nvoid IngnomiaGUI::GroupItem::UpdateState()\r\n{\r\n\tbool allChecked   = true;\r\n\tbool allUnchecked = true;\r\n\tfor ( int i = 0; i < m_items->Count(); ++i )\r\n\t{\r\n\t\tauto checked = m_items->Get( i )->GetState();\r\n\t\tif ( checked.HasValue() && checked )\r\n\t\t{\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t\telse if ( checked.HasValue() && !checked )\r\n\t\t{\r\n\t\t\tallChecked = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tallChecked   = false;\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t}\r\n\tif ( allChecked && !allUnchecked )\r\n\t{\r\n\t\tm_state = true;\r\n\t}\r\n\telse if ( !allChecked && allUnchecked )\r\n\t{\r\n\t\tm_state = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = nullptr;\r\n\t}\r\n\tOnPropertyChanged( \"Checked\" );\r\n\tOnPropertyChanged( \"Expanded\" );\r\n}\r\n#pragma endregion GroupItem\r\n\r\n#pragma region CategoryItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::CategoryItem::CategoryItem( unsigned int stockpileID, QString name, QString sid, Filter& filter, StockpileProxy* proxy ) :\r\n\tm_stockpileID( stockpileID ),\r\n\tm_proxy( proxy ),\r\n\tm_sid( sid )\r\n{\r\n\tm_name = name.toStdString().c_str();\r\n\r\n\tm_groups = *new ObservableCollection<GroupItem>();\r\n\r\n\tfor ( auto group : filter.groups( sid ) )\r\n\t{\r\n\t\tm_groups->Add( MakePtr<GroupItem>( m_stockpileID, group, group, sid, filter, proxy ) );\r\n\t}\r\n\r\n\tUpdateState();\r\n}\r\n\r\nconst char* IngnomiaGUI::CategoryItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst Noesis::Nullable<bool>& IngnomiaGUI::CategoryItem::GetState() const\r\n{\r\n\treturn m_state;\r\n}\r\n\r\nbool IngnomiaGUI::CategoryItem::getExpanded() const\r\n{\r\n\treturn !GetState().HasValue();\r\n}\r\n\r\nvoid IngnomiaGUI::CategoryItem::SetState( const Noesis::Nullable<bool>& value )\r\n{\r\n\tbool active = value.HasValue() && value.GetValue();\r\n\tm_proxy->setActive( m_stockpileID, active, m_sid );\r\n}\r\n\r\nvoid IngnomiaGUI::CategoryItem::UpdateChecked( Filter& filter )\r\n{\r\n\tfor ( int i = 0; i < m_groups->Count(); ++i )\r\n\t{\r\n\t\tm_groups->Get( i )->UpdateChecked( filter );\r\n\t}\r\n\r\n\tUpdateState();\r\n}\r\nvoid IngnomiaGUI::CategoryItem::UpdateState()\r\n{\r\n\tbool allChecked   = true;\r\n\tbool allUnchecked = true;\r\n\tfor ( int i = 0; i < m_groups->Count(); ++i )\r\n\t{\r\n\t\tauto checked = m_groups->Get( i )->GetState();\r\n\t\tif ( checked.HasValue() && checked )\r\n\t\t{\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t\telse if ( checked.HasValue() && !checked )\r\n\t\t{\r\n\t\t\tallChecked = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tallChecked   = false;\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t}\r\n\tif ( allChecked && !allUnchecked )\r\n\t{\r\n\t\tm_state = true;\r\n\t}\r\n\telse if ( !allChecked && allUnchecked )\r\n\t{\r\n\t\tm_state = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = nullptr;\r\n\t}\r\n\tOnPropertyChanged( \"Checked\" );\r\n\tOnPropertyChanged( \"Expanded\" );\r\n}\r\n#pragma endregion CategoryItem\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSpPriority::SpPriority( const char* name ) :\r\n\t_name( name )\r\n{\r\n}\r\n\r\nconst char* SpPriority::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nStockpileModel::StockpileModel()\r\n{\r\n\tm_proxy = new StockpileProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_prios = *new ObservableCollection<SpPriority>();\r\n\tfor ( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tm_prios->Add( MakePtr<SpPriority>( ( QString( \"Priority \" ) + QString::number( i + 1 ) ).toStdString().c_str() ) );\r\n\t}\r\n\tm_selectedPrio = m_prios->Get( 0 );\r\n\r\n\tm_categories = *new ObservableCollection<CategoryItem>();\r\n\r\n\tm_summary = *new ObservableCollection<StockedItemSummary>();\r\n\r\n\tm_limitItems = *new ObservableCollection<GuiLimitItem>();\r\n}\r\n\r\nvoid StockpileModel::onUpdateInfo( const GuiStockpileInfo& info )\r\n{\r\n\tm_blockSignals = true;\r\n\r\n\tbool isSameStockpile = ( m_stockpileID == info.stockpileID );\r\n\tm_stockpileID        = info.stockpileID;\r\n\tm_name               = info.name.toStdString().c_str();\r\n\tm_suspended          = info.suspended;\r\n\tm_pullFrom           = info.allowPullFromHere;\r\n\tm_pullOthers         = info.pullFromOthers;\r\n\r\n\tm_prios->Clear();\r\n\tfor ( int i = 0; i < info.maxPriority; ++i )\r\n\t{\r\n\t\tm_prios->Add( MakePtr<SpPriority>( ( QString( \"Priority \" ) + QString::number( i + 1 ) ).toStdString().c_str() ) );\r\n\t}\r\n\tm_selectedPrio = m_prios->Get( qMin( qMax( 0, info.priority ), m_prios->Count() ) );\r\n\r\n\t//auto cats = info.filter.categories();\r\n\tauto filter = info.filter;\r\n\tif ( isSameStockpile )\r\n\t{\r\n\t\tfor ( int i = 0; i < m_categories->Count(); ++i )\r\n\t\t{\r\n\t\t\tm_categories->Get( i )->UpdateChecked( filter );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_categories->Clear();\r\n\t\tfor ( auto cat : filter.categories() )\r\n\t\t{\r\n\t\t\tm_categories->Add( MakePtr<CategoryItem>( m_stockpileID, cat, cat, filter, m_proxy ) );\r\n\t\t}\r\n\t}\r\n\r\n\tm_summary->Clear();\r\n\tm_limitItems->Clear();\r\n\tfor ( auto is : info.summary )\r\n\t{\r\n\t\tif ( is.count > 0 )\r\n\t\t{\r\n\t\t\tm_summary->Add( MakePtr<StockedItemSummary>( QString::number( is.count ) + \" \" + is.materialName + \" \" + is.itemName ) );\r\n\t\t}\r\n\t\tm_limitItems->Add( MakePtr<GuiLimitItem>( is.materialName + \" \" + is.itemName ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"Priorities\" );\r\n\tOnPropertyChanged( \"SelectedPrio\" );\r\n\r\n\tOnPropertyChanged( \"Name\" );\r\n\tOnPropertyChanged( \"Suspended\" );\r\n\tOnPropertyChanged( \"PullFromHere\" );\r\n\tOnPropertyChanged( \"PullFromOther\" );\r\n\r\n\tOnPropertyChanged( \"Summary\" );\r\n\tOnPropertyChanged( \"Limits\" );\r\n\r\n\tm_blockSignals = false;\r\n}\r\n\r\nvoid StockpileModel::setBasicOptions()\r\n{\r\n\tif( !m_blockSignals )\r\n\t{\r\n\t\tm_proxy->setBasicOptions( m_stockpileID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_pullOthers, m_pullFrom );\r\n\t}\r\n}\r\n\r\nvoid StockpileModel::onUpdateContent( const GuiStockpileInfo& info )\r\n{\r\n\tbool isSameStockpile = ( m_stockpileID == info.stockpileID );\r\n\tif ( isSameStockpile )\r\n\t{\r\n\t\tm_summary->Clear();\r\n\r\n\t\tfor ( auto is : info.summary )\r\n\t\t{\r\n\t\t\tif ( is.count > 0 )\r\n\t\t\t{\r\n\t\t\t\tm_summary->Add( MakePtr<StockedItemSummary>( QString::number( is.count ) + \" \" + is.materialName + \" \" + is.itemName ) );\r\n\t\t\t}\r\n\t\t}\r\n\t\tOnPropertyChanged( \"Summary\" );\r\n\t}\r\n}\r\n\r\nconst char* StockpileModel::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nvoid StockpileModel::SetName( const char* value )\r\n{\r\n\tm_name = value;\r\n\tsetBasicOptions();\r\n\tOnPropertyChanged( \"Name\" );\r\n}\r\n\r\nbool StockpileModel::GetSuspended() const\r\n{\r\n\treturn m_suspended;\r\n}\r\n\r\nvoid StockpileModel::SetSuspended( bool value )\r\n{\r\n\tm_suspended = value;\r\n\tsetBasicOptions();\r\n\tOnPropertyChanged( \"Suspended\" );\r\n}\r\n\r\nbool StockpileModel::GetPullFrom() const\r\n{\r\n\treturn m_pullFrom;\r\n}\r\n\r\nvoid StockpileModel::SetPullFrom( bool value )\r\n{\r\n\tm_pullFrom = value;\r\n\tsetBasicOptions();\r\n\tOnPropertyChanged( \"PullFromHere\" );\r\n}\r\n\r\nbool StockpileModel::GetPullOthers() const\r\n{\r\n\treturn m_pullOthers;\r\n}\r\n\r\nvoid StockpileModel::SetPullOthers( bool value )\r\n{\r\n\tm_pullOthers = value;\r\n\tsetBasicOptions();\r\n\tOnPropertyChanged( \"PullFromOther\" );\r\n}\r\n\r\nNoesis::ObservableCollection<SpPriority>* StockpileModel::GetPrios() const\r\n{\r\n\treturn m_prios;\r\n}\r\n\r\nNoesis::ObservableCollection<StockedItemSummary>* StockpileModel::GetSummary() const\r\n{\r\n\treturn m_summary;\r\n}\r\n\r\nNoesis::ObservableCollection<GuiLimitItem>* StockpileModel::GetLimitItems() const\r\n{\r\n\treturn m_limitItems;\r\n}\r\n\r\nvoid StockpileModel::SetSelectedPriority( SpPriority* prio )\r\n{\r\n\tif ( m_selectedPrio != prio )\r\n\t{\r\n\t\tm_selectedPrio = prio;\r\n\t\tsetBasicOptions();\r\n\t\tOnPropertyChanged( \"SelectedPrio\" );\r\n\t}\r\n}\r\n\r\nSpPriority* StockpileModel::GetSelectedPriority() const\r\n{\r\n\treturn m_selectedPrio;\r\n}\r\n\r\nNoesis::ObservableCollection<CategoryItem>* StockpileModel::GetCategories() const\r\n{\r\n\treturn m_categories;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( StockpileModel, \"IngnomiaGUI.StockpileModel\" )\r\n{\r\n\tNsProp( \"Name\", &StockpileModel::GetName, &StockpileModel::SetName );\r\n\tNsProp( \"Suspended\", &StockpileModel::GetSuspended, &StockpileModel::SetSuspended );\r\n\tNsProp( \"PullFromHere\", &StockpileModel::GetPullFrom, &StockpileModel::SetPullFrom );\r\n\tNsProp( \"PullFromOther\", &StockpileModel::GetPullOthers, &StockpileModel::SetPullOthers );\r\n\r\n\tNsProp( \"Priorities\", &StockpileModel::GetPrios );\r\n\tNsProp( \"SelectedPrio\", &StockpileModel::GetSelectedPriority, &StockpileModel::SetSelectedPriority );\r\n\r\n\tNsProp( \"Filters\", &StockpileModel::GetCategories );\r\n\tNsProp( \"StockedItems\", &StockpileModel::GetSummary );\r\n\tNsProp( \"Limits\", &StockpileModel::GetLimitItems );\r\n\t//NsProp( \"\", &StockpileModel::Get );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( SpPriority )\r\n{\r\n\tNsProp( \"Name\", &SpPriority::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::CategoryItem )\r\n{\r\n\tNsProp( \"Name\", &CategoryItem::GetName );\r\n\tNsProp( \"Checked\", &CategoryItem::GetState, &CategoryItem::SetState );\r\n\tNsProp( \"Expanded\", &CategoryItem::getExpanded );\r\n\tNsProp( \"Children\", &CategoryItem::GetGroups );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::GroupItem )\r\n{\r\n\tNsProp( \"Name\", &GroupItem::GetName );\r\n\tNsProp( \"Checked\", &GroupItem::GetState, &GroupItem::SetState );\r\n\tNsProp( \"Expanded\", &GroupItem::getExpanded );\r\n\tNsProp( \"Children\", &GroupItem::GetItems );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::ItemItem )\r\n{\r\n\tNsProp( \"Name\", &ItemItem::GetName );\r\n\tNsProp( \"Checked\", &ItemItem::GetState, &ItemItem::SetState );\r\n\tNsProp( \"Expanded\", &ItemItem::getExpanded );\r\n\tNsProp( \"Children\", &ItemItem::GetMaterials );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::MaterialItem )\r\n{\r\n\tNsProp( \"Name\", &MaterialItem::GetName );\r\n\tNsProp( \"Checked\", &MaterialItem::GetChecked, &MaterialItem::SetChecked );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::StockedItemSummary )\r\n{\r\n\tNsProp( \"Name\", &StockedItemSummary::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::GuiLimitItem )\r\n{\r\n\tNsProp( \"Name\", &GuiLimitItem::GetName );\r\n}"
  },
  {
    "path": "src/gui/xaml/StockpileModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __StockpileModel_H__\r\n#define __StockpileModel_H__\r\n\r\n#include \"../aggregatorstockpile.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\n#include <QString>\r\n\r\nclass StockpileProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GuiLimitItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGuiLimitItem( QString name );\r\n\r\n\tconst char* GetName() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\r\n\tNS_DECLARE_REFLECTION( GuiLimitItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass StockedItemSummary final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tStockedItemSummary( QString name );\r\n\r\n\tconst char* GetName() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\r\n\tNS_DECLARE_REFLECTION( StockedItemSummary, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n#pragma region FilterItems\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass MaterialItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tMaterialItem( unsigned int stockpileID, QString name, QString sid, QString cat, QString group, QString item, Filter& filter, StockpileProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tbool GetChecked() const;\r\n\tvoid SetChecked( bool value );\r\n\tvoid UpdateChecked( Filter& filter );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tunsigned int m_stockpileID = 0;\r\n\tQString m_sid;\r\n\tQString m_item;\r\n\tQString m_group;\r\n\tQString m_category;\r\n\r\n\tbool m_active = false;\r\n\r\n\tStockpileProxy* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( MaterialItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass ItemItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tItemItem( unsigned int stockpileID, QString name, QString sid, QString cat, QString group, Filter& filter, StockpileProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tconst Noesis::Nullable<bool>& GetState() const;\r\n\tvoid SetState( const Noesis::Nullable<bool>& value );\r\n\tbool getExpanded() const;\r\n\tvoid UpdateChecked( Filter& filter );\r\n\r\nprivate:\r\n\tvoid UpdateState();\r\n\tNoesis::String m_name;\r\n\tunsigned int m_stockpileID = 0;\r\n\tQString m_sid;\r\n\tQString m_group;\r\n\tQString m_category;\r\n\r\n\tunsigned char m_active = 0;\r\n\tNoesis::Nullable<bool> m_state;\r\n\r\n\tStockpileProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<MaterialItem>* GetMaterials() const\r\n\t{\r\n\t\treturn m_materials;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<MaterialItem>> m_materials;\r\n\r\n\tNS_DECLARE_REFLECTION( ItemItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass GroupItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tGroupItem( unsigned int stockpileID, QString name, QString sid, QString cat, Filter& filter, StockpileProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tconst Noesis::Nullable<bool>& GetState() const;\r\n\tvoid SetState( const Noesis::Nullable<bool>& value );\r\n\tbool getExpanded() const;\r\n\tvoid UpdateChecked( Filter& filter );\r\n\r\nprivate:\r\n\tvoid UpdateState();\r\n\tNoesis::String m_name;\r\n\tunsigned int m_stockpileID = 0;\r\n\tQString m_sid;\r\n\tQString m_category;\r\n\r\n\tunsigned char m_active = 0;\r\n\tNoesis::Nullable<bool> m_state;\r\n\r\n\tStockpileProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<ItemItem>* GetItems() const\r\n\t{\r\n\t\treturn m_items;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<ItemItem>> m_items;\r\n\r\n\tNS_DECLARE_REFLECTION( GroupItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass CategoryItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tCategoryItem( unsigned int stockpileID, QString name, QString sid, Filter& filter, StockpileProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tconst Noesis::Nullable<bool>& GetState() const;\r\n\tvoid SetState( const Noesis::Nullable<bool>& value );\r\n\tbool getExpanded() const;\r\n\r\n\tvoid UpdateChecked( Filter& filter );\r\n\r\nprivate:\r\n\tvoid UpdateState();\r\n\tNoesis::String m_name;\r\n\tunsigned int m_stockpileID = 0;\r\n\tQString m_sid;\r\n\r\n\tunsigned char m_active = 0;\r\n\tNoesis::Nullable<bool> m_state;\r\n\r\n\tStockpileProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<GroupItem>* GetGroups() const\r\n\t{\r\n\t\treturn m_groups;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GroupItem>> m_groups;\r\n\r\n\tNS_DECLARE_REFLECTION( CategoryItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n#pragma endregion FilterItems\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SpPriority final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tSpPriority( const char* name );\r\n\r\n\tconst char* GetName() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\r\n\tNS_DECLARE_REFLECTION( SpPriority, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass StockpileModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tStockpileModel();\r\n\r\n\tvoid onUpdateInfo( const GuiStockpileInfo& stockpileInfo );\r\n\tvoid onUpdateContent( const GuiStockpileInfo& stockpileInfo );\r\n\r\nprivate:\r\n\tconst char* GetName() const;\r\n\tvoid SetName( const char* value );\r\n\tbool GetSuspended() const;\r\n\tvoid SetSuspended( bool value );\r\n\tbool GetPullFrom() const;\r\n\tvoid SetPullFrom( bool value );\r\n\tbool GetPullOthers() const;\r\n\tvoid SetPullOthers( bool value );\r\n\r\n\tvoid setBasicOptions();\r\n\r\n\tNoesis::ObservableCollection<SpPriority>* GetPrios() const;\r\n\tvoid SetSelectedPriority( SpPriority* prio );\r\n\tSpPriority* GetSelectedPriority() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<SpPriority>> m_prios;\r\n\tSpPriority* m_selectedPrio;\r\n\r\n\tNoesis::ObservableCollection<CategoryItem>* GetCategories() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<CategoryItem>> m_categories;\r\n\r\n\tNoesis::ObservableCollection<StockedItemSummary>* GetSummary() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<StockedItemSummary>> m_summary;\r\n\r\n\tNoesis::ObservableCollection<GuiLimitItem>* GetLimitItems() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<GuiLimitItem>> m_limitItems;\r\n\r\n\tStockpileProxy* m_proxy = nullptr;\r\n\tbool m_blockSignals = false;\r\n\r\n\tunsigned int m_stockpileID = 0;\r\n\tNoesis::String m_name      = \"-Stockpile-\";\r\n\tbool m_suspended           = false;\r\n\tbool m_pullFrom            = true;\r\n\tbool m_pullOthers          = false;\r\n\r\n\tNS_DECLARE_REFLECTION( StockpileModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/StockpileProxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"StockpileProxy.h\"\r\n\r\n#include \"../../base/db.h\"\r\n#include \"../../base/gamestate.h\"\r\n#include \"../../gfx/sprite.h\"\r\n#include \"../../gfx/spritefactory.h\"\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n#include \"TileInfoModel.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nStockpileProxy::StockpileProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorStockpile(), &AggregatorStockpile::signalUpdateInfo, this, &StockpileProxy::onUpdateInfo, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorStockpile(), &AggregatorStockpile::signalUpdateContent, this, &StockpileProxy::onUpdateContent, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &StockpileProxy::signalSetBasicOptions, Global::eventConnector->aggregatorStockpile(), &AggregatorStockpile::onSetBasicOptions, Qt::QueuedConnection );\r\n\tconnect( this, &StockpileProxy::signalSetActive, Global::eventConnector->aggregatorStockpile(), &AggregatorStockpile::onSetActive, Qt::QueuedConnection );\r\n}\r\n\r\nStockpileProxy::~StockpileProxy()\r\n{\r\n}\r\n\r\nvoid StockpileProxy::setParent( IngnomiaGUI::StockpileModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid StockpileProxy::onUpdateInfo( const GuiStockpileInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onUpdateInfo( info );\r\n\t}\r\n}\r\n\r\nvoid StockpileProxy::onUpdateContent( const GuiStockpileInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onUpdateContent( info );\r\n\t}\r\n}\r\n\r\nvoid StockpileProxy::setBasicOptions( unsigned int stockpileID, QString name, int priority, bool suspended, bool pull, bool allowPull )\r\n{\r\n\temit signalSetBasicOptions( stockpileID, name, priority, suspended, pull, allowPull );\r\n}\r\n\r\nvoid StockpileProxy::setActive( unsigned int stockpileID, bool active, QString category, QString group, QString item, QString material )\r\n{\r\n\temit signalSetActive( stockpileID, active, category, group, item, material );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/StockpileProxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorstockpile.h\"\r\n#include \"StockpileModel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass StockpileProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tStockpileProxy( QObject* parent = nullptr );\r\n\t~StockpileProxy();\r\n\r\n\tvoid setParent( IngnomiaGUI::StockpileModel* parent );\r\n\r\n\tvoid setBasicOptions( unsigned int stockpileID, QString name, int priority, bool suspended, bool pull, bool allowPull );\r\n\r\n\tvoid setActive( unsigned int stockpileID, bool active, QString category, QString group = \"\", QString item = \"\", QString material = \"\" );\r\n\r\nprivate:\r\n\tIngnomiaGUI::StockpileModel* m_parent = nullptr;\r\n\r\nprivate slots:\r\n\tvoid onUpdateInfo( const GuiStockpileInfo& info );\r\n\tvoid onUpdateContent( const GuiStockpileInfo& info );\r\n\r\nsignals:\r\n\tvoid signalSetBasicOptions( unsigned int stockpileID, QString name, int priority, bool suspended, bool pull, bool allowPull );\r\n\tvoid signalSetActive( unsigned int stockpileID, bool active, QString category, QString group, QString item, QString material );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/TileInfo.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"TileInfo.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nTileInfo::TileInfo()\r\n{\r\n\tLoaded() += MakeDelegate( this, &TileInfo::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid TileInfo::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"TileInfo.xaml\" );\r\n}\r\n\r\nbool TileInfo::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid TileInfo::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::TileInfo, \"IngnomiaGUI.TileInfo\" )\r\n"
  },
  {
    "path": "src/gui/xaml/TileInfo.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __TileInfo_H__\r\n#define __TileInfo_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass TileInfo final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tTileInfo();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( TileInfo, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/TileInfoModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"TileInfoModel.h\"\r\n\r\n#include \"../../base/tile.h\"\r\n#include \"ProxyTileInfo.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::TITabItem::TITabItem( QString name, QString sid ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_sid( sid.toStdString().c_str() )\r\n{\r\n}\r\n\r\nbool IngnomiaGUI::TITabItem::GetChecked() const\r\n{\r\n\treturn _active;\r\n}\r\n\r\nvoid IngnomiaGUI::TITabItem::setActive( bool active )\r\n{\r\n\tif ( _active != active )\r\n\t{\r\n\t\t_active = active;\r\n\t\tOnPropertyChanged( \"Checked\" );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nTerrainTabItem::TerrainTabItem( QString name, QString sid, QString action1, QString action2 ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_sid( sid.toStdString().c_str() )\r\n{\r\n\t_action1    = action1.toStdString().c_str();\r\n\t_action2    = action2.toStdString().c_str();\r\n\t_hasAction1 = !action1.isEmpty();\r\n\t_hasAction2 = !action2.isEmpty();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nItemTabItem::ItemTabItem( QString name, unsigned int id ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_id( id ),\r\n\tm_sid( QString::number( id ).toStdString().c_str() )\r\n{\r\n\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nCreatureTabItem::CreatureTabItem( QString name, unsigned int id ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_id( id ),\r\n\tm_sid( QString::number( id ).toStdString().c_str() )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nAutomatonTabItem::AutomatonTabItem( QString name, unsigned int id, bool refuel, QString coreItem, ProxyTileInfo* proxy ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_id( id ),\r\n\tm_sid( QString::number( id ).toStdString().c_str() ),\r\n\tm_refuel( refuel ),\r\n\tm_proxy( proxy )\r\n{\r\n\tm_coreItems = *new ObservableCollection<TITabItem>();\r\n\tm_coreItems->Add( MakePtr<TITabItem>( \"None\", \"\" ) );\r\n\tm_coreItems->Add( MakePtr<TITabItem>( \"Automaton Core MK1\", \"AutomatonCoreMark1\" ) );\r\n\tm_coreItems->Add( MakePtr<TITabItem>( \"Automaton Core MK2\", \"AutomatonCoreMark2\" ) );\r\n\r\n\tif( coreItem == \"AutomatonCoreMark1\" )\r\n\t{\r\n\t\tm_selectedCoreItem = m_coreItems->Get( 1 );\r\n\t}\r\n\telse if( coreItem == \"AutomatonCoreMark2\" )\r\n\t{\r\n\t\tm_selectedCoreItem = m_coreItems->Get( 2 );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_selectedCoreItem = m_coreItems->Get( 0 );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<TITabItem>* AutomatonTabItem::getCoreItems() const\r\n{\r\n\treturn m_coreItems;\r\n}\r\n\r\nvoid AutomatonTabItem::setSelectedCore( TITabItem* ci )\r\n{\r\n\tif( ci && ci != m_selectedCoreItem )\r\n\t{\r\n\t\tm_selectedCoreItem = ci;\r\n\t\tm_proxy->setAutomatonCore( m_id, ci->GetID() );\r\n\t}\r\n}\r\n\t\r\nTITabItem* AutomatonTabItem::getSelectedCore() const\r\n{\r\n\treturn m_selectedCoreItem;\r\n}\r\n\r\nbool AutomatonTabItem::getRefuel() const\r\n{\r\n\treturn m_refuel;\r\n}\r\n\r\nvoid AutomatonTabItem::setRefuel( bool value )\r\n{\r\n\tif( value != m_refuel )\r\n\t{\r\n\t\tm_refuel = value;\r\n\t\tm_proxy->setAutomatonRefuel( m_id, m_refuel );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nTileInfoModel::TileInfoModel()\r\n{\r\n\tm_proxy = new ProxyTileInfo;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_tileIDString = Noesis::String( std::to_string( m_tileID ).c_str() );\r\n\r\n\t_tabItems = *new ObservableCollection<TITabItem>();\r\n\r\n\t_tabItemElements.tt = MakePtr<TITabItem>( \"T\", \"T\" );\r\n\t_tabItems->Add( _tabItemElements.tt );\r\n\t_tabItemElements.tt->setActive( true );\r\n\r\n\t_tabItemElements.tc = MakePtr<TITabItem>( \"C\", \"C\" );\r\n\t_tabItemElements.ti = MakePtr<TITabItem>( \"I\", \"I\" );\r\n\t_tabItemElements.td = MakePtr<TITabItem>( \"D\", \"D\" );\r\n\t_tabItemElements.tj = MakePtr<TITabItem>( \"J\", \"J\" );\r\n\r\n\t_terrainTabItems = *new ObservableCollection<TerrainTabItem>();\r\n\r\n\t_itemTabItems = *new ObservableCollection<ItemTabItem>();\r\n\r\n\t_creatureTabItems = *new ObservableCollection<CreatureTabItem>();\r\n\t_automatonTabItems = *new ObservableCollection<AutomatonTabItem>();\r\n\r\n\t_cmdTab.SetExecuteFunc( MakeDelegate( this, &TileInfoModel::OnCmdTab ) );\r\n\t_cmdTerrain.SetExecuteFunc( MakeDelegate( this, &TileInfoModel::OnCmdTerrain ) );\r\n\t_cmdManage.SetExecuteFunc( MakeDelegate( this, &TileInfoModel::OnCmdManage ) );\r\n\t_miniSPContents   = *new ObservableCollection<TITabItem>();\r\n\t_possibleTennants = *new ObservableCollection<CreatureTabItem>();\r\n\r\n\t_jobTabRequiredItems = *new Noesis::ObservableCollection<NRequiredItem>();\r\n\r\n\t_cmdMechToggleActive.SetExecuteFunc( MakeDelegate( this, &TileInfoModel::OnCmdMechToggleActive ) );\r\n\t_cmdMechToggleInvert.SetExecuteFunc( MakeDelegate( this, &TileInfoModel::OnCmdMechToggleInvert ) );\r\n}\r\n\r\nvoid TileInfoModel::onUpdateTileInfo( const GuiTileInfo& tileInfo )\r\n{\r\n\tm_tileIDString  = Noesis::String( std::to_string( tileInfo.tileID ).c_str() );\r\n\tm_tileID        = tileInfo.tileID;\r\n\tm_designationID = tileInfo.designationID;\r\n\r\n\t// tt is always present\r\n\tuint32_t activeItems = 1;\r\n\r\n\tauto flags        = tileInfo.flags;\r\n\tm_designationFlag = tileInfo.designationFlag;\r\n\t\r\n\t_tabItems->Remove( _tabItemElements.td );\r\n\t_tabItemElements.td->setActive( false );\r\n\r\n\tif ( tileInfo.designationID )\r\n\t{\r\n\t\tm_designationName = tileInfo.designationName.toStdString().c_str();\r\n\r\n\t\tif ( flags & ( TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE ) )\r\n\t\t{\r\n\t\t\tm_proxy->sendManageCommand( m_tileID );\r\n\t\t}\r\n\t\telse if ( flags & TileFlag::TF_STOCKPILE )\r\n\t\t{\r\n\t\t\tm_proxy->requestStockpileItems( m_tileID );\r\n\t\t}\r\n\t\telse if ( flags & TileFlag::TF_WORKSHOP )\r\n\t\t{\r\n\t\t}\r\n\t\telse if ( flags & TileFlag::TF_ROOM )\r\n\t\t{\r\n\t\t\tm_roomType     = tileInfo.roomType;\r\n\t\t\tm_hasRoof      = tileInfo.hasRoof;\r\n\t\t\tm_isEnclosed   = tileInfo.isEnclosed;\r\n\t\t\tm_hasAlarmBell = tileInfo.hasAlarmBell;\r\n\t\t\tm_beds         = tileInfo.beds.toStdString().c_str();\r\n\t\t\tm_alarm        = tileInfo.alarm;\r\n\t\t\tm_roomValue\t   = QString::number( tileInfo.roomValue ).toStdString().c_str();\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\t_mode = TileInfoMode::Terrain;\r\n\t}\r\n\r\n\tm_hasJob = ( flags & ( TileFlag::TF_JOB_FLOOR + TileFlag::TF_JOB_WALL + TileFlag::TF_JOB_BUSY_WALL + TileFlag::TF_JOB_BUSY_FLOOR ) );\r\n\t\r\n\tbool anyChecked = false;\r\n\tfor ( int i = 0; i < _tabItems->Count(); ++i )\r\n\t{\r\n\t\tanyChecked |= _tabItems->Get( i )->GetChecked();\r\n\t}\r\n\tif ( !anyChecked )\r\n\t{\r\n\t\t_tabItems->Get( 0 )->setActive( true );\r\n\t\t_mode = TileInfoMode::Terrain;\r\n\t}\r\n\r\n\tQString action1;\r\n\tQString action2;\r\n\r\n\t_terrainTabItems->Clear();\r\n\tif ( !tileInfo.wall.isEmpty() )\r\n\t{\r\n\t\tif ( tileInfo.jobName.isEmpty() )\r\n\t\t{\r\n\t\t\taction1 = \"Mine\";\r\n\t\t\taction2 = \"Replace\";\r\n\t\t}\r\n\t\t_terrainTabItems->Add( MakePtr<TerrainTabItem>( tileInfo.wall, \"Wall\", action1, action2 ) );\r\n\t}\r\n\taction1.clear();\r\n\taction2.clear();\r\n\tif ( !tileInfo.floor.isEmpty() )\r\n\t{\r\n\t\tif ( tileInfo.plant.isEmpty() && tileInfo.wall.isEmpty() && tileInfo.jobName.isEmpty() )\r\n\t\t{\r\n\t\t\taction1 = \"Remove\";\r\n\t\t\taction2 = \"Replace\";\r\n\t\t}\r\n\t\t_terrainTabItems->Add( MakePtr<TerrainTabItem>( tileInfo.floor, \"Floor\", action1, action2 ) );\r\n\t}\r\n\tif ( !tileInfo.embedded.isEmpty() )\r\n\t{\r\n\t\t_terrainTabItems->Add( MakePtr<TerrainTabItem>( tileInfo.embedded, \"Embedded\" ) );\r\n\t}\r\n\taction1.clear();\r\n\taction2.clear();\r\n\tif ( !tileInfo.plant.isEmpty() )\r\n\t{\r\n\t\t// need to distinguish between plant and tree and check if harvestable\r\n\t\tif ( tileInfo.jobName.isEmpty() )\r\n\t\t{\r\n\t\t\tif ( tileInfo.plantIsHarvestable )\r\n\t\t\t{\r\n\t\t\t\taction1 = \"Harvest\";\r\n\t\t\t}\r\n\t\t\taction2 = \"Destroy\";\r\n\t\t\tif ( tileInfo.plantIsTree )\r\n\t\t\t{\r\n\t\t\t\taction2 = \"Fell\";\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t_terrainTabItems->Add( MakePtr<TerrainTabItem>( tileInfo.plant, \"Plant\", action1, action2 ) );\r\n\t}\r\n\tif ( !tileInfo.water.isEmpty() )\r\n\t\t_terrainTabItems->Add( MakePtr<TerrainTabItem>( tileInfo.water, \"Water\" ) );\r\n\r\n\tswitch ( m_designationFlag )\r\n\t{\r\n\t\tcase TileFlag::TF_WORKSHOP:\r\n\t\t\tm_designationTitle = \"Workshop\";\r\n\t\t\tbreak;\r\n\t\tcase TileFlag::TF_STOCKPILE:\r\n\t\t\tm_designationTitle = \"Stockpile\";\r\n\t\t\tbreak;\r\n\t\tcase TileFlag::TF_GROVE:\r\n\t\t\tm_designationTitle = \"Grove\";\r\n\t\t\tbreak;\r\n\t\tcase TileFlag::TF_FARM:\r\n\t\t\tm_designationTitle = \"Farm\";\r\n\t\t\tbreak;\r\n\t\tcase TileFlag::TF_PASTURE:\r\n\t\t\tm_designationTitle = \"Pasture\";\r\n\t\t\tbreak;\r\n\t\tcase TileFlag::TF_ROOM:\r\n\t\t\tm_designationTitle = \"Room\";\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\r\n\t_itemTabItems->Clear();\r\n\tif ( !tileInfo.items.empty() )\r\n\t{\r\n\t\tfor ( auto git : tileInfo.items )\r\n\t\t{\r\n\t\t\t_itemTabItems->Add( MakePtr<ItemTabItem>( git.text, git.id ) );\r\n\t\t}\r\n\t}\r\n\r\n\t_creatureTabItems->Clear();\r\n\t_automatonTabItems->Clear();\r\n\tif ( !tileInfo.creatures.empty() )\r\n\t{\r\n\t\tfor ( auto gct : tileInfo.creatures )\r\n\t\t{\r\n\t\t\tif( gct.type == CreatureType::AUTOMATON )\r\n\t\t\t{\r\n\t\t\t\t_automatonTabItems->Add( MakePtr<AutomatonTabItem>( gct.text, gct.id, gct.refuel, gct.coreItem, m_proxy ) );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\t_creatureTabItems->Add( MakePtr<CreatureTabItem>( gct.text, gct.id ) );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t_possibleTennants->Clear();\r\n\tm_tennant = nullptr;\r\n\tif ( !tileInfo.possibleTennants.empty() )\r\n\t{\r\n\t\t_possibleTennants->Add( MakePtr<CreatureTabItem>( \"unassigned\", 0 ) );\r\n\t\tfor ( const auto& gnome : tileInfo.possibleTennants )\r\n\t\t{\r\n\t\t\t_possibleTennants->Add( MakePtr<CreatureTabItem>( gnome.text, gnome.id ) );\r\n\t\t\tif ( tileInfo.tennant == gnome.id )\r\n\t\t\t{\r\n\t\t\t\tm_tennant = _possibleTennants->Get( _possibleTennants->Count() - 1 );\r\n\t\t\t}\r\n\t\t}\r\n\t\tif ( !m_tennant )\r\n\t\t{\r\n\t\t\tm_tennant = _possibleTennants->Get( 0 );\r\n\t\t}\r\n\t}\r\n\r\n\t_jobTabRequiredItems->Clear();\r\n\tfor ( auto ri : tileInfo.requiredItems )\r\n\t{\r\n\t\tauto item = MakePtr<NRequiredItem>( ri.text, ri.count );\r\n\r\n\t\t_jobTabRequiredItems->Add( item );\r\n\t}\r\n\r\n\tm_jobName               = tileInfo.jobName.toStdString().c_str();\r\n\tm_jobWorker             = tileInfo.jobWorker.toStdString().c_str();\r\n\tm_jobPriority           = tileInfo.jobPriority.toStdString().c_str();\r\n\tm_requiredSkill         = tileInfo.requiredSkill.toStdString().c_str();\r\n\tm_requiredTool          = tileInfo.requiredTool.toStdString().c_str();\r\n\tm_requiredToolAvailable = tileInfo.requiredToolAvailable.toStdString().c_str();\r\n\tm_workablePosition      = tileInfo.workPositions.toStdString().c_str();\r\n\r\n\tif( tileInfo.mechInfo.itemID != 0 && !tileInfo.mechInfo.gui.isEmpty() )\r\n\t{\r\n\t\tm_mechanismID = tileInfo.mechInfo.itemID;\r\n\t\tm_hasMechanism = true;\r\n\t\tm_mechGui = tileInfo.mechInfo.gui;\r\n\t\tm_mechFuel = ( QString::number( tileInfo.mechInfo.fuel ) + \"/\" +\r\n\t\t\tQString::number( tileInfo.mechInfo.maxFuel ) ).toStdString().c_str();\r\n\t\tm_mechActive = tileInfo.mechInfo.active ? \"Active\" : \"Inactive\";\r\n\t\tm_mechInvert = tileInfo.mechInfo.inverted ? \"Inverted\" : \"Not inverted\";\r\n\r\n\t\tm_mechName = tileInfo.mechInfo.name.toStdString().c_str();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_hasMechanism = false;\r\n\t}\r\n\r\n\r\n\tOnPropertyChanged( \"JobName\" );\r\n\tOnPropertyChanged( \"JobWorker\" );\r\n\tOnPropertyChanged( \"JobPriority\" );\r\n\tOnPropertyChanged( \"RequiredSkill\" );\r\n\tOnPropertyChanged( \"RequiredTool\" );\r\n\tOnPropertyChanged( \"RequiredToolAvailable\" );\r\n\tOnPropertyChanged( \"RequiredItems\" );\r\n\tOnPropertyChanged( \"WorkablePosition\" );\r\n\r\n\tOnPropertyChanged( \"TileID\" );\r\n\tOnPropertyChanged( \"TabItems\" );\r\n\tOnPropertyChanged( \"TerrainTabItems\" );\r\n\tOnPropertyChanged( \"PossibleTennnants\" );\r\n\tOnPropertyChanged( \"Tennant\" );\r\n\tOnPropertyChanged( \"Alarm\" );\r\n\r\n\tOnPropertyChanged( \"VisRoomAssign\" );\r\n\tOnPropertyChanged( \"VisRoomValue\" );\r\n\tOnPropertyChanged( \"VisBeds\" );\r\n\tOnPropertyChanged( \"VisAlarm\" );\r\n\tOnPropertyChanged( \"RoomValue\" );\r\n\tOnPropertyChanged( \"Beds\" );\r\n\tOnPropertyChanged( \"Enclosed\" );\r\n\tOnPropertyChanged( \"Roofed\" );\r\n\r\n\tOnPropertyChanged( \"ShowTerrain\" );\r\n\tOnPropertyChanged( \"ShowItems\" );\r\n\tOnPropertyChanged( \"ShowCreatures\" );\r\n\tOnPropertyChanged( \"ShowAutomatons\" );\r\n\tOnPropertyChanged( \"ShowJob\" );\r\n\tOnPropertyChanged( \"ShowMiniStockpile\" );\r\n\r\n\tOnPropertyChanged( \"ShowDesignation\" );\r\n\tOnPropertyChanged( \"ShowDesignationSimple\" );\r\n\tOnPropertyChanged( \"ShowDesignationRoom\" );\r\n\tOnPropertyChanged( \"DesignationName\" );\r\n\tOnPropertyChanged( \"DesignationTitle\" );\r\n\r\n\tOnPropertyChanged( \"ShowMechanism\" );\r\n\tOnPropertyChanged( \"ShowMechActive\" );\r\n\tOnPropertyChanged( \"ShowMechFuel\" );\r\n\tOnPropertyChanged( \"ShowMechInvert\" );\r\n\tOnPropertyChanged( \"MechActive\" );\r\n\tOnPropertyChanged( \"MechFuel\" );\r\n\tOnPropertyChanged( \"MechInvert\" );\r\n\tOnPropertyChanged( \"MechName\" );\r\n}\r\n\r\nconst char* TileInfoModel::getTileID() const\r\n{\r\n\treturn m_tileIDString.Str();\r\n}\r\n\r\nNoesis::ObservableCollection<IngnomiaGUI::TITabItem>* TileInfoModel::getTabItems() const\r\n{\r\n\treturn _tabItems;\r\n}\r\n\r\nNoesis::ObservableCollection<TerrainTabItem>* TileInfoModel::getTerrainTabItems() const\r\n{\r\n\treturn _terrainTabItems;\r\n}\r\n\r\nNoesis::ObservableCollection<ItemTabItem>* TileInfoModel::getItemTabItems() const\r\n{\r\n\treturn _itemTabItems;\r\n}\r\n\r\nNoesis::ObservableCollection<CreatureTabItem>* TileInfoModel::getCreatureTabItems() const\r\n{\r\n\treturn _creatureTabItems;\r\n}\r\n\r\nNoesis::ObservableCollection<AutomatonTabItem>* TileInfoModel::getAutomatonTabItems() const\r\n{\r\n\treturn _automatonTabItems;\r\n}\r\n\r\nNoesis::ObservableCollection<CreatureTabItem>* TileInfoModel::getPossibleTennants() const\r\n{\r\n\treturn _possibleTennants;\r\n}\r\n\r\nNoesis::ObservableCollection<NRequiredItem>* TileInfoModel::GetJobRequiredItems() const\r\n{\r\n\treturn _jobTabRequiredItems;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* TileInfoModel::GetCmdTab() const\r\n{\r\n\treturn &_cmdTab;\r\n}\r\n\r\nvoid TileInfoModel::OnCmdTab( BaseComponent* param )\r\n{\r\n\tQString tab = param->ToString().Str();\r\n\tif ( tab == \"T\" )\r\n\t\t_mode = TileInfoMode::Terrain;\r\n\t/*\r\n\telse if ( tab == \"I\" )\r\n\t\t_mode = TileInfoMode::Items;\r\n\telse if ( tab == \"C\" )\r\n\t\t_mode = TileInfoMode::Creatures;\r\n\telse if ( tab == \"D\" )\r\n\t{\r\n\t\t// if designation is workshop or stock pile, open window\r\n\t\tswitch ( m_designationFlag )\r\n\t\t{\r\n\t\t\tcase TileFlag::TF_WORKSHOP:\r\n\t\t\t\tm_proxy->sendManageCommand( m_tileID );\r\n\t\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_STOCKPILE:\r\n\t\t\t\tm_proxy->requestStockpileItems( m_tileID );\r\n\t\t\t\t_mode = TileInfoMode::Stockpile;\r\n\t\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_GROVE:\r\n\t\t\tcase TileFlag::TF_FARM:\r\n\t\t\tcase TileFlag::TF_PASTURE:\r\n\t\t\t\t_mode = TileInfoMode::Designation;\r\n\t\t\t\tm_proxy->sendManageCommand( m_tileID );\r\n\t\t\t\tbreak;\r\n\t\t\tcase TileFlag::TF_ROOM:\r\n\t\t\t\t_mode = TileInfoMode::Room;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\telse if ( tab == \"J\" )\r\n\t\t_mode = TileInfoMode::Job;\r\n\r\n\tfor ( int i = 0; i < _tabItems->Count(); ++i )\r\n\t{\r\n\t\t_tabItems->Get( i )->setActive( tab == _tabItems->Get( i )->GetID() );\r\n\t}\r\n\t*/\r\n\tOnPropertyChanged( \"ShowTerrain\" );\r\n\tOnPropertyChanged( \"ShowItems\" );\r\n\tOnPropertyChanged( \"ShowCreatures\" );\r\n\tOnPropertyChanged( \"ShowDesignation\" );\r\n\tOnPropertyChanged( \"ShowDesignationRoom\" );\r\n\tOnPropertyChanged( \"ShowJob\" );\r\n\tOnPropertyChanged( \"ShowMiniStockpile\" );\r\n}\r\n\r\nvoid TileInfoModel::OnCmdTerrain( BaseComponent* param )\r\n{\r\n\tif ( m_tileID )\r\n\t{\r\n\t\tm_proxy->sendTerrainCommand( m_tileID, param->ToString().Str() );\r\n\t}\r\n}\r\n\r\nvoid TileInfoModel::OnCmdManage( BaseComponent* param )\r\n{\r\n\tm_proxy->sendManageCommand( m_tileID );\r\n\r\n\tif ( m_designationFlag & ( TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE ) )\r\n\t{\r\n\t\t_mode = TileInfoMode::Designation;\r\n\t}\r\n\tOnPropertyChanged( \"ShowTerrain\" );\r\n\tOnPropertyChanged( \"ShowDesignation\" );\r\n}\r\n\r\nconst char* TileInfoModel::GetShowTerrain() const\r\n{\r\n\tif ( _mode == TileInfoMode::Terrain )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowItems() const\r\n{\r\n\tif ( _itemTabItems->Count() > 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowCreatures() const\r\n{\r\n\tif ( _creatureTabItems->Count() > 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowAutomatons() const\r\n{\r\n\tif ( _automatonTabItems->Count() > 0 )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowDesignation() const\r\n{\r\n\tif ( _mode == TileInfoMode::Designation )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowDesignationSimple() const\r\n{\r\n\tif ( m_designationFlag & ( TileFlag::TF_GROVE + TileFlag::TF_FARM + TileFlag::TF_PASTURE + TileFlag::TF_WORKSHOP ) )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\n\r\nconst char* TileInfoModel::GetShowDesignationRoom() const\r\n{\r\n\tif ( m_designationFlag & TileFlag::TF_ROOM )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowJob() const\r\n{\r\n\tif ( m_hasJob )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowMiniSP() const\r\n{\r\n\tif ( m_designationFlag & TileFlag::TF_STOCKPILE )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nvoid TileInfoModel::updateMiniStockpile( const GuiStockpileInfo& info )\r\n{\r\n\tm_miniStockpileName = info.name.toStdString().c_str();\r\n\r\n\tm_capacity = ( \"Capacity: \" + QString::number( info.capacity ) ).toStdString().c_str();\r\n\tm_itemCount = ( \"Used: \" + QString::number( info.itemCount ).toStdString() ).c_str();\r\n\tm_reserved = ( \"Reserved: \" + QString::number( info.reserved ).toStdString() ).c_str();\r\n\r\n\t_miniSPContents->Clear();\r\n\r\n\tfor ( auto is : info.summary )\r\n\t{\r\n\t\t_miniSPContents->Add( MakePtr<IngnomiaGUI::TITabItem>( QString::number( is.count ) + \" \" + is.materialName + \" \" + is.itemName, \"\" ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"MiniStockpileName\" );\r\n\tOnPropertyChanged( \"MiniStockpileContents\" );\r\n\tOnPropertyChanged( \"Capacity\" );\r\n\tOnPropertyChanged( \"ItemCount\" );\r\n\tOnPropertyChanged( \"Reserved\" );\r\n}\r\n\r\nNoesis::ObservableCollection<IngnomiaGUI::TITabItem>* TileInfoModel::getMiniSPContents() const\r\n{\r\n\treturn _miniSPContents;\r\n}\r\n\r\nvoid TileInfoModel::SetTennant( CreatureTabItem* tennant )\r\n{\r\n\tif ( tennant && m_tennant != tennant )\r\n\t{\r\n\t\tm_tennant = tennant;\r\n\t\tm_proxy->setTennant( m_designationID, tennant->uid() );\r\n\t}\r\n}\r\n\r\nCreatureTabItem* TileInfoModel::GetTennant() const\r\n{\r\n\treturn m_tennant;\r\n}\r\n\r\nconst char* TileInfoModel::GetVisRoomAssign() const\r\n{\r\n\tif ( m_roomType == RoomType::PersonalRoom )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetVisRoomValue() const\r\n{\r\n\tif ( m_roomType == RoomType::PersonalRoom || m_roomType == RoomType::Dining )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetVisBeds() const\r\n{\r\n\tif ( m_roomType == RoomType::Dorm || m_roomType == RoomType::Hospital )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetVisAlarm() const\r\n{\r\n\tif ( m_roomType == RoomType::Dining && m_hasAlarmBell )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetRoomValue() const\r\n{\r\n\treturn m_roomValue.Str();\r\n}\r\n\r\nconst char* TileInfoModel::GetBeds() const\r\n{\r\n\treturn m_beds.Str();\r\n}\r\n\r\nconst char* TileInfoModel::GetEnclosed() const\r\n{\r\n\tif ( m_isEnclosed )\r\n\t{\r\n\t\treturn \"yes\";\r\n\t}\r\n\treturn \"no\";\r\n}\r\n\r\nconst char* TileInfoModel::GetRoofed() const\r\n{\r\n\tif ( m_hasRoof )\r\n\t{\r\n\t\treturn \"yes\";\r\n\t}\r\n\treturn \"no\";\r\n}\r\n\r\nbool TileInfoModel::GetAlarm() const\r\n{\r\n\treturn m_alarm;\r\n}\r\n\r\nvoid TileInfoModel::SetAlarm( bool value )\r\n{\r\n\tif ( m_alarm != value )\r\n\t{\r\n\t\tm_alarm = value;\r\n\t\tm_proxy->setAlarm( m_designationID, value );\r\n\t}\r\n}\r\n\r\nconst char* TileInfoModel::GetCapacity() const\r\n{\r\n\treturn m_capacity.Str();\r\n}\r\n\t\r\nconst char* TileInfoModel::GetItemCount() const\r\n{\r\n\treturn m_itemCount.Str();\r\n}\r\n\r\nconst char* TileInfoModel::GetReserved() const\r\n{\r\n\treturn m_reserved.Str();\r\n}\r\n\r\n\r\nconst char* TileInfoModel::GetShowMechanism() const\r\n{\r\n\tif ( m_hasMechanism )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\t\r\nconst char* TileInfoModel::GetShowMechActive() const\r\n{\r\n\tif ( m_mechGui.contains( \"Active\" ) )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowMechFuel() const\r\n{\r\n\tif ( m_mechGui.contains( \"Fuel\" ) )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetShowMechInvert() const\r\n{\r\n\tif ( m_mechGui.contains( \"Invert\" ) )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* TileInfoModel::GetMechActive() const\r\n{\r\n\treturn m_mechActive.Str();\r\n}\r\n\r\nconst char* TileInfoModel::GetMechFuel() const\r\n{\r\n\treturn m_mechFuel.Str();\r\n}\r\n\r\nconst char* TileInfoModel::GetMechInvert() const\r\n{\r\n\treturn m_mechInvert.Str();\r\n}\r\n\r\nconst char* TileInfoModel::GetMechName() const\r\n{\r\n\treturn m_mechName.Str();\r\n}\r\n\r\nvoid TileInfoModel::OnCmdMechToggleActive( BaseComponent* param )\r\n{\r\n\tm_proxy->toggleMechActive( m_mechanismID );\r\n}\r\n\r\nvoid TileInfoModel::OnCmdMechToggleInvert( BaseComponent* param )\r\n{\r\n\tm_proxy->toggleMechInvert( m_mechanismID );\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( TileInfoModel, \"IngnomiaGUI.TileInfoModel\" )\r\n{\r\n\tNsProp( \"TileID\", &TileInfoModel::getTileID );\r\n\tNsProp( \"TabItems\", &TileInfoModel::getTabItems );\r\n\tNsProp( \"ShowTerrain\", &TileInfoModel::GetShowTerrain );\r\n\tNsProp( \"ShowItems\", &TileInfoModel::GetShowItems );\r\n\tNsProp( \"ShowCreatures\", &TileInfoModel::GetShowCreatures );\r\n\tNsProp( \"ShowAutomatons\", &TileInfoModel::GetShowAutomatons );\r\n\tNsProp( \"ShowDesignation\", &TileInfoModel::GetShowDesignation );\r\n\tNsProp( \"ShowDesignationSimple\", &TileInfoModel::GetShowDesignationSimple );\r\n\tNsProp( \"ShowDesignationRoom\", &TileInfoModel::GetShowDesignationRoom );\r\n\tNsProp( \"ShowJob\", &TileInfoModel::GetShowJob );\r\n\tNsProp( \"ShowMiniStockpile\", &TileInfoModel::GetShowMiniSP );\r\n\t\r\n\tNsProp( \"CmdTab\", &TileInfoModel::GetCmdTab );\r\n\tNsProp( \"CmdTerrain\", &TileInfoModel::GetCmdTerrain );\r\n\tNsProp( \"CmdManage\", &TileInfoModel::GetCmdManage );\r\n\r\n\tNsProp( \"TerrainTab\", &TileInfoModel::getTerrainTabItems );\r\n\tNsProp( \"ItemTab\", &TileInfoModel::getItemTabItems );\r\n\tNsProp( \"CreatureTab\", &TileInfoModel::getCreatureTabItems );\r\n\tNsProp( \"AutomatonTab\", &TileInfoModel::getAutomatonTabItems );\r\n\r\n\tNsProp( \"JobName\", &TileInfoModel::GetJobName );\r\n\tNsProp( \"JobWorker\", &TileInfoModel::GetJobWorker );\r\n\tNsProp( \"JobPriority\", &TileInfoModel::GetJobPriority );\r\n\tNsProp( \"RequiredSkill\", &TileInfoModel::GetRequiredSkill );\r\n\tNsProp( \"RequiredTool\", &TileInfoModel::GetRequiredTool );\r\n\tNsProp( \"RequiredToolAvailable\", &TileInfoModel::GetRequiredToolAvailable );\r\n\tNsProp( \"RequiredItems\", &TileInfoModel::GetJobRequiredItems );\r\n\tNsProp( \"WorkablePosition\", &TileInfoModel::GetWorkablePosition );\r\n\r\n\tNsProp( \"DesignationName\", &TileInfoModel::GetDesignationName );\r\n\tNsProp( \"DesignationTitle\", &TileInfoModel::GetDesignationTitle );\r\n\r\n\tNsProp( \"MiniStockpileName\", &TileInfoModel::GetMiniSPName );\r\n\tNsProp( \"MiniStockpileContents\", &TileInfoModel::getMiniSPContents );\r\n\tNsProp( \"Capacity\", &TileInfoModel::GetCapacity );\r\n\tNsProp( \"ItemCount\", &TileInfoModel::GetItemCount );\r\n\tNsProp( \"Reserved\", &TileInfoModel::GetReserved );\r\n\r\n\tNsProp( \"PossibleTennants\", &TileInfoModel::getPossibleTennants );\r\n\tNsProp( \"Tennant\", &TileInfoModel::GetTennant, &TileInfoModel::SetTennant );\r\n\tNsProp( \"VisRoomAssign\", &TileInfoModel::GetVisRoomAssign );\r\n\tNsProp( \"VisRoomValue\", &TileInfoModel::GetVisRoomValue );\r\n\tNsProp( \"VisBeds\", &TileInfoModel::GetVisBeds );\r\n\tNsProp( \"VisAlarm\", &TileInfoModel::GetVisAlarm );\r\n\tNsProp( \"RoomValue\", &TileInfoModel::GetRoomValue );\r\n\tNsProp( \"Beds\", &TileInfoModel::GetBeds );\r\n\tNsProp( \"Enclosed\", &TileInfoModel::GetEnclosed );\r\n\tNsProp( \"Roofed\", &TileInfoModel::GetRoofed );\r\n\tNsProp( \"Alarm\", &TileInfoModel::GetAlarm, &TileInfoModel::SetAlarm );\r\n\r\n\tNsProp( \"ShowMechanism\", &TileInfoModel::GetShowMechanism );\r\n\tNsProp( \"ShowMechActive\", &TileInfoModel::GetShowMechActive );\r\n\tNsProp( \"ShowMechFuel\", &TileInfoModel::GetShowMechFuel );\r\n\tNsProp( \"ShowMechInvert\", &TileInfoModel::GetShowMechInvert );\r\n\tNsProp( \"MechActive\", &TileInfoModel::GetMechActive );\r\n\tNsProp( \"MechFuel\", &TileInfoModel::GetMechFuel );\r\n\tNsProp( \"MechInvert\", &TileInfoModel::GetMechInvert );\r\n\tNsProp( \"MechName\", &TileInfoModel::GetMechName );\r\n\tNsProp( \"CmdMechToggleActive\", &TileInfoModel::GetCmdMechToggleActive );\r\n\tNsProp( \"CmdMechToggleInvert\", &TileInfoModel::GetCmdMechToggleInvert );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::TITabItem )\r\n{\r\n\tNsProp( \"Name\", &TITabItem::GetName );\r\n\tNsProp( \"ID\", &TITabItem::GetID );\r\n\tNsProp( \"Checked\", &TITabItem::GetChecked, &TITabItem::SetChecked );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( TerrainTabItem )\r\n{\r\n\tNsProp( \"Name\", &TerrainTabItem::GetName );\r\n\tNsProp( \"ID\", &TerrainTabItem::GetID );\r\n\tNsProp( \"Action1Text\", &TerrainTabItem::GetAction1 );\r\n\tNsProp( \"Action2Text\", &TerrainTabItem::GetAction2 );\r\n\tNsProp( \"Action1Visible\", &TerrainTabItem::Action1Visible );\r\n\tNsProp( \"Action2Visible\", &TerrainTabItem::Action2Visible );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( ItemTabItem )\r\n{\r\n\tNsProp( \"Name\", &ItemTabItem::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( CreatureTabItem )\r\n{\r\n\tNsProp( \"Name\", &CreatureTabItem::GetName );\r\n\tNsProp( \"ID\", &CreatureTabItem::GetID );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( AutomatonTabItem )\r\n{\r\n\tNsProp( \"Name\", &AutomatonTabItem::GetName );\r\n\tNsProp( \"ID\", &AutomatonTabItem::GetID );\r\n\tNsProp( \"Cores\", &AutomatonTabItem::getCoreItems );\r\n\tNsProp( \"SelectedCore\", &AutomatonTabItem::getSelectedCore, &AutomatonTabItem::setSelectedCore );\r\n\tNsProp( \"Refuel\", &AutomatonTabItem::getRefuel, &AutomatonTabItem::setRefuel );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/TileInfoModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __TileInfoModel_H__\r\n#define __TileInfoModel_H__\r\n\r\n#include \"../../base/position.h\"\r\n#include \"../aggregatortileinfo.h\"\r\n#include \"GameModel.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QString>\r\n\r\nclass ProxyTileInfo;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass TITabItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tTITabItem( QString name, QString sid );\r\n\r\n\tconst char* GetName() const { return m_name.Str(); }\r\n\tconst char* GetID() const { return m_sid.Str(); }\r\n\tbool GetChecked() const;\r\n\tvoid SetChecked( bool )\r\n\t{\r\n\t}\r\n\r\n\tvoid setActive( bool active );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\tbool _active = false;\r\n\r\n\tNS_DECLARE_REFLECTION( TITabItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass TerrainTabItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tTerrainTabItem( QString name, QString sid, QString action1 = \"\", QString action2 = \"\" );\r\n\r\n\tconst char* GetName() const { return m_name.Str(); }\r\n\tconst char* GetID() const { return m_sid.Str(); }\r\n\tconst char* GetAction1() const\r\n\t{\r\n\t\treturn _action1.Str();\r\n\t}\r\n\tconst char* GetAction2() const\r\n\t{\r\n\t\treturn _action2.Str();\r\n\t}\r\n\tNoesis::Visibility Action1Visible() const\r\n\t{\r\n\t\treturn _hasAction1 ? Noesis::Visibility_Visible : Noesis::Visibility_Hidden;\r\n\t}\r\n\tNoesis::Visibility Action2Visible() const\r\n\t{\r\n\t\treturn _hasAction2 ? Noesis::Visibility_Visible : Noesis::Visibility_Hidden;\r\n\t}\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\tNoesis::String _action1;\r\n\tNoesis::String _action2;\r\n\tbool _hasAction1;\r\n\tbool _hasAction2;\r\n\r\n\tNS_DECLARE_REFLECTION( TerrainTabItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass ItemTabItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tItemTabItem( QString name, unsigned int id );\r\n\r\n\tconst char* GetName() const { return m_name.Str(); }\r\n\tconst char* GetID() const { return m_sid.Str(); }\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tunsigned int m_id;\r\n\tNoesis::String m_sid;\r\n\r\n\tNS_DECLARE_REFLECTION( ItemTabItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass CreatureTabItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tCreatureTabItem( QString name, unsigned int id );\r\n\r\n\tconst char* GetName() const { return m_name.Str(); }\r\n\tconst char* GetID() const { return m_sid.Str(); }\r\n\r\n\tunsigned int uid()\r\n\t{\r\n\t\treturn m_id;\r\n\t}\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tunsigned int m_id;\r\n\tNoesis::String m_sid;\r\n\r\n\tNS_DECLARE_REFLECTION( CreatureTabItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass AutomatonTabItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tAutomatonTabItem( QString name, unsigned int id, bool refuel, QString coreItem, ProxyTileInfo* proxy );\r\n\r\n\tconst char* GetName() const { return m_name.Str(); }\r\n\tconst char* GetID() const { return m_sid.Str(); }\r\n\tunsigned int uid() { return m_id; }\r\n\r\n\tNoesis::ObservableCollection<TITabItem>* getCoreItems() const;\r\n\r\n\tvoid setSelectedCore( TITabItem* mat );\r\n\tTITabItem* getSelectedCore() const;\r\n\r\n\tbool getRefuel() const;\r\n\tvoid setRefuel( bool value );\r\n\r\nprivate:\r\n\tProxyTileInfo* m_proxy = nullptr;\r\n\r\n\tNoesis::String m_name;\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_sid;\r\n\tbool m_refuel = false;\r\n\tTITabItem* m_selectedCoreItem = nullptr;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<TITabItem>> m_coreItems;\r\n\r\n\t\r\n\r\n\tNS_DECLARE_REFLECTION( AutomatonTabItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nenum class TileInfoMode\r\n{\r\n\tTerrain,\r\n\tItems,\r\n\tCreatures,\r\n\tDesignation,\r\n\tJob,\r\n\tStockpile,\r\n\tRoom\r\n\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass TileInfoModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tTileInfoModel();\r\n\r\n\tvoid onUpdateTileInfo( const GuiTileInfo& tileInfo );\r\n\tvoid updateMiniStockpile( const GuiStockpileInfo& info );\r\n\r\nprivate:\r\n\tconst char* getTileID() const;\r\n\r\n\tNoesis::ObservableCollection<TITabItem>* getTabItems() const;\r\n\tNoesis::ObservableCollection<TerrainTabItem>* getTerrainTabItems() const;\r\n\tNoesis::ObservableCollection<ItemTabItem>* getItemTabItems() const;\r\n\tNoesis::ObservableCollection<CreatureTabItem>* getCreatureTabItems() const;\r\n\tNoesis::ObservableCollection<AutomatonTabItem>* getAutomatonTabItems() const;\r\n\tNoesis::ObservableCollection<TITabItem>* getMiniSPContents() const;\r\n\tNoesis::ObservableCollection<CreatureTabItem>* getPossibleTennants() const;\r\n\r\n\tconst char* GetShowTerrain() const;\r\n\tconst char* GetShowItems() const;\r\n\tconst char* GetShowCreatures() const;\r\n\tconst char* GetShowAutomatons() const;\r\n\tconst char* GetShowDesignation() const;\r\n\tconst char* GetShowDesignationSimple() const;\r\n\tconst char* GetShowDesignationRoom() const;\r\n\tconst char* GetShowJob() const;\r\n\tconst char* GetShowMiniSP() const;\r\n\t\r\n\tconst char* GetJobName() const\r\n\t{\r\n\t\treturn m_jobName.Str();\r\n\t}\r\n\tconst char* GetJobWorker() const\r\n\t{\r\n\t\treturn m_jobWorker.Str();\r\n\t}\r\n\tconst char* GetJobPriority() const\r\n\t{\r\n\t\treturn m_jobPriority.Str();\r\n\t}\r\n\tconst char* GetRequiredSkill() const\r\n\t{\r\n\t\treturn m_requiredSkill.Str();\r\n\t}\r\n\tconst char* GetRequiredTool() const\r\n\t{\r\n\t\treturn m_requiredTool.Str();\r\n\t}\r\n\tconst char* GetRequiredToolAvailable() const\r\n\t{\r\n\t\treturn m_requiredToolAvailable.Str();\r\n\t}\r\n\tNoesis::ObservableCollection<NRequiredItem>* GetJobRequiredItems() const;\r\n\tconst char* GetWorkablePosition() const\r\n\t{\r\n\t\treturn m_workablePosition.Str();\r\n\t}\r\n\r\n\tconst char* GetDesignationName() const\r\n\t{\r\n\t\treturn m_designationName.Str();\r\n\t}\r\n\r\n\tconst char* GetDesignationTitle() const\r\n\t{\r\n\t\treturn m_designationTitle.Str();\r\n\t}\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdTerrain() const\r\n\t{\r\n\t\treturn &_cmdTerrain;\r\n\t}\r\n\tvoid OnCmdTerrain( BaseComponent* param );\r\n\tNoesisApp::DelegateCommand _cmdTerrain;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdManage() const\r\n\t{\r\n\t\treturn &_cmdManage;\r\n\t}\r\n\tvoid OnCmdManage( BaseComponent* param );\r\n\tNoesisApp::DelegateCommand _cmdManage;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdTab() const;\r\n\tvoid OnCmdTab( BaseComponent* param );\r\n\tNoesisApp::DelegateCommand _cmdTab;\r\n\r\n\tProxyTileInfo* m_proxy = nullptr;\r\n\r\n\tunsigned int m_tileID = 0;\r\n\tNoesis::String m_tileIDString;\r\n\r\n\t// job related fields\r\n\tNoesis::String m_jobName;\r\n\tNoesis::String m_jobWorker;\r\n\tNoesis::String m_jobPriority;\r\n\tNoesis::String m_requiredSkill;\r\n\tNoesis::String m_requiredTool;\r\n\tNoesis::String m_requiredToolAvailable;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<NRequiredItem>> _jobTabRequiredItems;\r\n\tNoesis::String m_workablePosition;\r\n\r\n\tunsigned int m_designationID = 0;\r\n\tNoesis::String m_designationName;\r\n\tNoesis::String m_designationTitle;\r\n\tTileFlag m_designationFlag = TileFlag::TF_NONE;\r\n\tRoomType m_roomType        = RoomType::NotSet;\r\n\tbool m_hasRoof             = false;\r\n\tbool m_isEnclosed          = false;\r\n\tbool m_hasAlarmBell        = false;\r\n\tNoesis::String m_beds;\r\n\tbool m_alarm = false;\r\n\tNoesis::String m_roomValue;\r\n\r\n\tbool m_hasJob\t\t\t   = false;\r\n\r\n\tunsigned int m_mechanismID = 0;\r\n\tbool m_hasMechanism\t\t   = false;\r\n\tQString m_mechGui;\r\n\tNoesis::String m_mechActive;\r\n\tNoesis::String m_mechInvert;\r\n\tNoesis::String m_mechFuel;\r\n\tNoesis::String m_mechName;\r\n\t\r\n\r\n\r\n\tNoesis::String m_capacity;\r\n\tNoesis::String m_itemCount;\r\n\tNoesis::String m_reserved;\r\n\r\n\tTileInfoMode _mode = TileInfoMode::Terrain;\r\n\r\n\tstruct\r\n\t{\r\n\t\tNoesis::Ptr<TITabItem> tt;\r\n\t\tNoesis::Ptr<TITabItem> tc;\r\n\t\tNoesis::Ptr<TITabItem> ti;\r\n\t\tNoesis::Ptr<TITabItem> td;\r\n\t\tNoesis::Ptr<TITabItem> tj;\r\n\t} _tabItemElements;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<TITabItem>> _tabItems; //left item bar depending on what is present on tile\r\n\tNoesis::Ptr<Noesis::ObservableCollection<TerrainTabItem>> _terrainTabItems;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<ItemTabItem>> _itemTabItems;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<CreatureTabItem>> _creatureTabItems;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AutomatonTabItem>> _automatonTabItems;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<CreatureTabItem>> _possibleTennants;\r\n\tvoid SetTennant( CreatureTabItem* tennant );\r\n\tCreatureTabItem* GetTennant() const;\r\n\tCreatureTabItem* m_tennant = nullptr;\r\n\r\n\tNoesis::String m_miniStockpileName;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<TITabItem>> _miniSPContents;\r\n\tconst char* GetMiniSPName() const\r\n\t{\r\n\t\treturn m_miniStockpileName.Str();\r\n\t}\r\n\r\n\tconst char* GetVisRoomAssign() const;\r\n\tconst char* GetVisRoomValue() const;\r\n\tconst char* GetVisBeds() const;\r\n\tconst char* GetVisAlarm() const;\r\n\tconst char* GetRoomValue() const;\r\n\tconst char* GetBeds() const;\r\n\tconst char* GetEnclosed() const;\r\n\tconst char* GetRoofed() const;\r\n\r\n\tconst char* GetCapacity() const;\r\n\tconst char* GetItemCount() const;\r\n\tconst char* GetReserved() const;\r\n\r\n\tbool GetAlarm() const;\r\n\tvoid SetAlarm( bool value );\r\n\r\n\tconst char* GetShowMechanism() const;\r\n\tconst char* GetShowMechActive() const;\r\n\tconst char* GetShowMechFuel() const;\r\n\tconst char* GetShowMechInvert() const;\r\n\tconst char* GetMechActive() const;\r\n\tconst char* GetMechFuel() const;\r\n\tconst char* GetMechInvert() const;\r\n\tconst char* GetMechName() const;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdMechToggleActive() const\r\n\t{\r\n\t\treturn &_cmdMechToggleActive;\r\n\t}\r\n\tvoid OnCmdMechToggleActive( BaseComponent* param );\r\n\tNoesisApp::DelegateCommand _cmdMechToggleActive;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdMechToggleInvert() const\r\n\t{\r\n\t\treturn &_cmdMechToggleInvert;\r\n\t}\r\n\tvoid OnCmdMechToggleInvert( BaseComponent* param );\r\n\tNoesisApp::DelegateCommand _cmdMechToggleInvert;\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( TileInfoModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/ViewModel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"ViewModel.h\"\r\n#include \"ProxyMainView.h\"\r\n\r\n#include \"../eventconnector.h\"\r\n#include \"../strings.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\n#include <functional>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nViewModel::ViewModel()\r\n{\r\n\tm_proxy = new ProxyMainView;\r\n\tm_proxy->setParent( this );\r\n\r\n\t_start.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnStart ) );\r\n\t_settings.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnSettings ) );\r\n\t_newGame.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnNewGame ) );\r\n\t_setupGame.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnSetupGame ) );\r\n\t_loadGame.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnLoadGame ) );\r\n\t_saveGame.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnSaveGame ) );\r\n\t_continueGame.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnContinueGame ) );\r\n\t_exit.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnExit ) );\r\n\t_back.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnBack ) );\r\n\t_backToMain.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnBackToMain ) );\r\n\t_resume.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnResume ) );\r\n\t_fadeInCompleted.SetExecuteFunc( MakeDelegate( this, &ViewModel::OnFadeInCompleted ) );\r\n\r\n\t_state        = State::Main;\r\n\t_showMainMenu = true;\r\n\t_showGameGUI  = false;\r\n\t_ingame       = false;\r\n\tm_scale       = 1.0f; \r\n\r\n\tm_version = \"0.0.0.0\";\r\n\r\n\tm_proxy->requestUIScale();\r\n\tm_proxy->requestVersion();\r\n}\r\n\r\nvoid ViewModel::setWindowSize( int w, int h )\r\n{\r\n\t_realWidth          = w;\r\n\t_realHeight         = h;\r\n\t_windowWidth        = _realWidth / m_scale;\r\n\t_windowHeight       = _realHeight / m_scale;\r\n\t_windowWidthString  = QString::number( _windowWidth ).toStdString().c_str();\r\n\t_windowHeightString = QString::number( _windowHeight ).toStdString().c_str();\r\n\tOnPropertyChanged( \"WindowWidth\" );\r\n\tOnPropertyChanged( \"WindowHeight\" );\r\n}\r\n\r\nvoid ViewModel::updateVersion( QString version )\r\n{\r\n\tm_version = version.toStdString().c_str();\t\r\n\tOnPropertyChanged( \"Version\" );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetStart() const\r\n{\r\n\treturn &_start;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetSettings() const\r\n{\r\n\treturn &_settings;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetNewGame() const\r\n{\r\n\treturn &_newGame;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetContinueGame() const\r\n{\r\n\treturn &_continueGame;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetSetupGame() const\r\n{\r\n\treturn &_setupGame;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetLoadGame() const\r\n{\r\n\treturn &_loadGame;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetSaveGame() const\r\n{\r\n\treturn &_saveGame;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetExit() const\r\n{\r\n\treturn &_exit;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetBack() const\r\n{\r\n\treturn &_back;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetBackToMain() const\r\n{\r\n\treturn &_backToMain;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetResume() const\r\n{\r\n\treturn &_resume;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst DelegateCommand* ViewModel::GetFadeInCompleted() const\r\n{\r\n\treturn &_fadeInCompleted;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst NewGameModel* ViewModel::getNewGameModel() const\r\n{\r\n\treturn &_newGameModel;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nconst char* ViewModel::GetPlatform() const\r\n{\r\n#if defined( NS_PLATFORM_XBOX_ONE ) || defined( NS_PLATFORM_NX )\r\n\treturn \"XBOX\";\r\n#elif defined( NS_PLATFORM_PS4 )\r\n\treturn \"PS4\";\r\n#else\r\n\treturn \"PC\";\r\n#endif\r\n}\r\n\r\nconst char* ViewModel::GetShowMainMenu() const\r\n{\r\n\tif ( _showMainMenu )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* ViewModel::GetShowGameGUI() const\r\n{\r\n\tif ( _showGameGUI )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* ViewModel::GetWindowWidth() const\r\n{\r\n\treturn _windowWidthString.Str();\r\n}\r\n\r\nconst char* ViewModel::GetWindowHeight() const\r\n{\r\n\treturn _windowHeightString.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnStart( BaseComponent* )\r\n{\r\n\tSetState( State::Start );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnSettings( BaseComponent* )\r\n{\r\n\tNS_LOG_INFO( \"ViewModel OnSettings\" );\r\n\tSetState( State::Settings );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnNewGame( BaseComponent* )\r\n{\r\n\tNS_LOG_INFO( \"ViewModel OnNewGame\" );\r\n\tSetState( State::Wait );\r\n\tm_proxy->startNewGame();\r\n}\r\n\r\nvoid ViewModel::OnContinueGame( BaseComponent* param )\r\n{\r\n\tusing namespace std::placeholders;\r\n\r\n\tif ( !param )\r\n\t{\r\n\t\tSetState( State::Wait );\r\n\t\tm_proxy->continueLastGame();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSetState( State::Wait );\r\n\t\tm_proxy->loadGame( param->ToString().Str() );\r\n\t}\r\n\tNS_LOG_INFO( \"ViewModel OnContinueGame\" );\r\n\t//SetState( State::Wait );\r\n\t//Global::gameManager->startNewGame( std::bind( &ViewModel::OnContinueGameFinished, this ) );\r\n}\r\n\r\nvoid ViewModel::OnContinueGameFinished( bool gameLoaded )\r\n{\r\n\tif ( gameLoaded )\r\n\t{\r\n\t\tOnResume( nullptr );\r\n\t}\r\n\telse\r\n\t{\r\n\t\tSetState( State::Main );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnSetupGame( BaseComponent* )\r\n{\r\n\tNS_LOG_INFO( \"ViewModel OnNewGame\" );\r\n\tSetState( State::NewGame );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnLoadGame( BaseComponent* )\r\n{\r\n\tNS_LOG_INFO( \"ViewModel OnLoadGame\" );\r\n\tm_proxy->requestLoadScreenUpdate();\r\n\tSetState( State::LoadGame );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnSaveGame( BaseComponent* )\r\n{\r\n\tNS_LOG_INFO( \"ViewModel OnSaveGame\" );\r\n\r\n\tm_proxy->saveGame();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnExit( BaseComponent* )\r\n{\r\n\tNS_LOG_INFO( \"Exiting game\" );\r\n\t//NoesisApp::Application::Current()->Shutdown();\r\n\tGlobal::eventConnector->onExit();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnBackToMain( BaseComponent* )\r\n{\r\n\t_showMainMenu = true;\r\n\t_ingame       = false;\r\n\tOnPropertyChanged( \"ShowMainMenu\" );\r\n\t_showGameGUI = false;\r\n\tOnPropertyChanged( \"ShowGameGui\" );\r\n\tm_proxy->setShowMainMenu( true );\r\n\tm_proxy->endGame();\r\n\tSetState( State::Main );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnBack( BaseComponent* )\r\n{\r\n\tswitch ( _state )\r\n\t{\r\n\t\tcase State::Main:\r\n\t\t\tbreak;\r\n\t\tcase State::GameRunning:\r\n\t\t\t_showMainMenu = true;\r\n\t\t\t_showGameGUI = false;\r\n\t\t\t_ingame = true;\r\n\t\t\tSetState( State::Ingame );\r\n\t\t\tm_proxy->setShowMainMenu( true );\r\n\t\t\tbreak;\r\n\t\tcase State::Settings:\r\n\t\tcase State::LoadGame:\r\n\t\tcase State::NewGame:\r\n\t\t\tif ( _ingame )\r\n\t\t\t{\r\n\t\t\t\tSetState( State::Ingame );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tSetState( State::Main );\r\n\t\t\t}\r\n\t\t\t_showMainMenu = true;\r\n\t\t\t_showGameGUI  = false;\r\n\t\t\tm_proxy->setShowMainMenu( true );\r\n\t\t\tbreak;\r\n\t\tcase State::Start:\r\n\t\tcase State::Ingame:\r\n\t\t{\r\n\t\t\t_showMainMenu = false;\r\n\t\t\t_ingame       = false;\r\n\t\t\t_showGameGUI = true;\r\n\t\t\tm_proxy->setShowMainMenu( false );\r\n\t\t\tSetState( State::GameRunning );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tdefault:\r\n\t\t\tbreak;\r\n\t}\r\n\tOnPropertyChanged( \"ShowMainMenu\" );\r\n\tOnPropertyChanged( \"ShowGameGui\" );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnResume( BaseComponent* )\r\n{\r\n\tSetState( State::GameRunning );\r\n\t_showMainMenu = false;\r\n\t_showGameGUI  = true;\r\n\tOnPropertyChanged( \"ShowMainMenu\" );\r\n\tOnPropertyChanged( \"ShowGameGui\" );\r\n\tm_proxy->setShowMainMenu( false );\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::OnFadeInCompleted( BaseComponent* param )\r\n{\r\n\tUIElement* target = (UIElement*)param;\r\n\ttarget->Focus();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nState ViewModel::GetState() const\r\n{\r\n\treturn _state;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid ViewModel::SetState( State value )\r\n{\r\n\tif ( _state != value )\r\n\t{\r\n\t\t_state = value;\r\n\t\tOnPropertyChanged( \"State\" );\r\n\t}\r\n}\r\n\r\nvoid ViewModel::setUIScale( float value )\r\n{\r\n\tm_scale = value;\r\n\t// Trigger layout update\r\n\tsetWindowSize( _realWidth, _realHeight );\r\n}\r\n\r\nconst char* ViewModel::GetVersion() const\r\n{\r\n\treturn m_version.Str();;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::ViewModel, \"IngnomiaGUI.ViewModel\" )\r\n{\r\n\t// menu properties\r\n\tNsProp( \"Start\", &ViewModel::GetStart );\r\n\tNsProp( \"Settings\", &ViewModel::GetSettings );\r\n\tNsProp( \"NewGame\", &ViewModel::GetNewGame );\r\n\tNsProp( \"ContinueGame\", &ViewModel::GetContinueGame );\r\n\tNsProp( \"SetupGame\", &ViewModel::GetSetupGame );\r\n\tNsProp( \"LoadGame\", &ViewModel::GetLoadGame );\r\n\tNsProp( \"SaveGame\", &ViewModel::GetSaveGame );\r\n\tNsProp( \"Exit\", &ViewModel::GetExit );\r\n\tNsProp( \"Back\", &ViewModel::GetBack );\r\n\tNsProp( \"BackToMain\", &ViewModel::GetBackToMain );\r\n\tNsProp( \"Resume\", &ViewModel::GetResume );\r\n\tNsProp( \"FadeInCompleted\", &ViewModel::GetFadeInCompleted );\r\n\tNsProp( \"State\", &ViewModel::GetState, &ViewModel::SetState );\r\n\tNsProp( \"Platform\", &ViewModel::GetPlatform );\r\n\tNsProp( \"ShowMainMenu\", &ViewModel::GetShowMainMenu );\r\n\tNsProp( \"ShowGameGUI\", &ViewModel::GetShowGameGUI );\r\n\tNsProp( \"WindowWidth\", &ViewModel::GetWindowWidth );\r\n\tNsProp( \"WindowHeight\", &ViewModel::GetWindowHeight );\r\n\tNsProp( \"Version\", &ViewModel::GetVersion );\r\n\r\n\tNsProp( \"NewGameModel\", &ViewModel::getNewGameModel );\r\n\r\n\t// New Game properties\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION_ENUM( IngnomiaGUI::State, \"IngnomiaGUI.State\" )\r\n{\r\n\tNsVal( \"Main\", State::Main );\r\n\tNsVal( \"Start\", State::Start );\r\n\tNsVal( \"Settings\", State::Settings );\r\n\tNsVal( \"NewGame\", State::NewGame );\r\n\tNsVal( \"LoadGame\", State::LoadGame );\r\n\tNsVal( \"Wait\", State::Wait );\r\n\tNsVal( \"GameRunning\", State::GameRunning );\r\n\tNsVal( \"Ingame\", State::Ingame );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/ViewModel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __MENU3D_VIEWMODEL_H__\r\n#define __MENU3D_VIEWMODEL_H__\r\n\r\n#include \"NewGameModel.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\n#include <QString>\r\n\r\nclass ProxyMainView;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\nenum class State\r\n{\r\n\tMain,\r\n\tStart,\r\n\tSettings,\r\n\tNewGame,\r\n\tLoadGame,\r\n\tWait,\r\n\tGameRunning,\r\n\tIngame\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass ViewModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tViewModel();\r\n\r\n\tvoid setWindowSize( int w, int h );\r\n\r\n\tvoid OnBack( BaseComponent* param );\r\n\r\n\tvoid setUIScale( float value );\r\n\tvoid updateVersion( QString version );\r\n\r\n\tvoid OnResume( BaseComponent* param = nullptr );\r\n\tvoid OnContinueGameFinished( bool gameLoaded );\r\n\r\nprivate:\r\n\tconst NoesisApp::DelegateCommand* GetStart() const;\r\n\tconst NoesisApp::DelegateCommand* GetSettings() const;\r\n\tconst NoesisApp::DelegateCommand* GetNewGame() const;\r\n\tconst NoesisApp::DelegateCommand* GetContinueGame() const;\r\n\tconst NoesisApp::DelegateCommand* GetSetupGame() const;\r\n\tconst NoesisApp::DelegateCommand* GetLoadGame() const;\r\n\tconst NoesisApp::DelegateCommand* GetSaveGame() const;\r\n\tconst NoesisApp::DelegateCommand* GetExit() const;\r\n\tconst NoesisApp::DelegateCommand* GetBack() const;\r\n\tconst NoesisApp::DelegateCommand* GetBackToMain() const;\r\n\tconst NoesisApp::DelegateCommand* GetResume() const;\r\n\tconst NoesisApp::DelegateCommand* GetFadeInCompleted() const;\r\n\r\n\tconst char* GetPlatform() const;\r\n\tconst char* GetShowMainMenu() const;\r\n\tconst char* GetShowGameGUI() const;\r\n\tconst char* GetWindowWidth() const;\r\n\tconst char* GetWindowHeight() const;\r\n\r\n\tconst char* GetVersion() const;\r\n\r\n\tvoid OnStart( BaseComponent* param );\r\n\tvoid OnSettings( BaseComponent* param );\r\n\tvoid OnNewGame( BaseComponent* param );\r\n\tvoid OnContinueGame( BaseComponent* param );\r\n\tvoid OnSetupGame( BaseComponent* param );\r\n\tvoid OnLoadGame( BaseComponent* param );\r\n\tvoid OnSaveGame( BaseComponent* param );\r\n\tvoid OnExit( BaseComponent* param );\r\n\tvoid OnBackToMain( BaseComponent* param );\r\n\tvoid OnFadeInCompleted( BaseComponent* params );\r\n\r\n\tState GetState() const;\r\n\tvoid SetState( State value );\r\n\r\n\tconst NewGameModel* getNewGameModel() const;\r\n\r\nprivate:\r\n\tNoesisApp::DelegateCommand _start;\r\n\tNoesisApp::DelegateCommand _settings;\r\n\tNoesisApp::DelegateCommand _newGame;\r\n\tNoesisApp::DelegateCommand _setupGame;\r\n\tNoesisApp::DelegateCommand _loadGame;\r\n\tNoesisApp::DelegateCommand _saveGame;\r\n\tNoesisApp::DelegateCommand _continueGame;\r\n\tNoesisApp::DelegateCommand _exit;\r\n\tNoesisApp::DelegateCommand _back;\r\n\tNoesisApp::DelegateCommand _backToMain;\r\n\tNoesisApp::DelegateCommand _resume;\r\n\tNoesisApp::DelegateCommand _fadeInCompleted;\r\n\r\n\tState _state;\r\n\tNewGameModel _newGameModel;\r\n\r\n\tbool _showMainMenu;\r\n\tbool _showGameGUI;\r\n\tbool _ingame;\r\n\tint _windowWidth;\r\n\tint _windowHeight;\r\n\tint _realWidth;\r\n\tint _realHeight;\r\n\tfloat m_scale = 1.0;\r\n\tNoesis::String _windowWidthString;\r\n\tNoesis::String _windowHeightString;\r\n\tNoesis::String m_version;\r\n\r\n\tProxyMainView* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( ViewModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\nNS_DECLARE_REFLECTION_ENUM( IngnomiaGUI::State )\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/WaitPage.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"WaitPage.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWaitPage::WaitPage()\r\n{\r\n\tLoaded() += MakeDelegate( this, &WaitPage::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid WaitPage::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"WaitPage.xaml\" );\r\n}\r\n\r\nbool WaitPage::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid WaitPage::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::WaitPage, \"IngnomiaGUI.WaitPage\" )\r\n"
  },
  {
    "path": "src/gui/xaml/WaitPage.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __WaitPage_H__\r\n#define __WaitPage_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WaitPage final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tWaitPage();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( WaitPage, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/agriculture.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"agriculture.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAgriculture::Agriculture()\r\n{\r\n\tLoaded() += MakeDelegate( this, &Agriculture::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid Agriculture::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"Agriculture.xaml\" );\r\n}\r\n\r\nbool Agriculture::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid Agriculture::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::Agriculture, \"IngnomiaGUI.Agriculture\" )\r\n"
  },
  {
    "path": "src/gui/xaml/agriculture.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __AgricultureGui_H__\r\n#define __AgricultureGui_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass Agriculture final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tAgriculture();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( Agriculture, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/agriculturemodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"agriculturemodel.h\"\r\n\r\n#include \"../../base/util.h\"\r\n#include \"agricultureproxy.h\"\r\n#include \"../strings.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n#pragma region AcPriority\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAcPriority::AcPriority( const char* name ) :\r\n\tm_name( name )\r\n{\r\n}\r\n\r\nconst char* AcPriority::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n#pragma endregion AcPriority\r\n\r\n#pragma region Trees\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nTreeSelectEntry::TreeSelectEntry( const GuiPlant& tree )\r\n{\r\n\tm_name = tree.name.toStdString().c_str();\r\n\tm_sid  = tree.plantID.toStdString().c_str();\r\n\r\n\tstd::vector<unsigned char> buffer;\r\n\tGlobal::util->createBufferForNoesisImage( tree.sprite, buffer );\r\n\tm_bitmapSource = BitmapImage::Create( tree.sprite.width(), tree.sprite.height(), 96, 96, buffer.data(), tree.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n}\r\n\r\nconst char* TreeSelectEntry::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* TreeSelectEntry::GetSID() const\r\n{\r\n\treturn m_sid.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nTreeSelectRow::TreeSelectRow( QList<GuiPlant> Trees )\r\n{\r\n\tm_entries = *new ObservableCollection<TreeSelectEntry>();\r\n\r\n\tfor ( auto Tree : Trees )\r\n\t{\r\n\t\tm_entries->Add( MakePtr<TreeSelectEntry>( Tree ) );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<TreeSelectEntry>* TreeSelectRow::GetTrees() const\r\n{\r\n\treturn m_entries;\r\n}\r\n#pragma endregion Trees\r\n\r\n#pragma region Animals\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAnimalSelectEntry::AnimalSelectEntry( const GuiAnimal& animal )\r\n{\r\n\tm_name = animal.name.toStdString().c_str();\r\n\tm_sid  = animal.animalID.toStdString().c_str();\r\n\r\n\tstd::vector<unsigned char> buffer;\r\n\tGlobal::util->createBufferForNoesisImage( animal.sprite, buffer );\r\n\r\n\tm_bitmapSource = BitmapImage::Create( animal.sprite.width(), animal.sprite.height(), 96, 96, buffer.data(), animal.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n}\r\n\r\nconst char* AnimalSelectEntry::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* AnimalSelectEntry::GetSID() const\r\n{\r\n\treturn m_sid.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAnimalSelectRow::AnimalSelectRow( QList<GuiAnimal> animals )\r\n{\r\n\tm_entries = *new ObservableCollection<AnimalSelectEntry>();\r\n\r\n\tfor ( auto animal : animals )\r\n\t{\r\n\t\tm_entries->Add( MakePtr<AnimalSelectEntry>( animal ) );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<AnimalSelectEntry>* AnimalSelectRow::GetAnimals() const\r\n{\r\n\treturn m_entries;\r\n}\r\n#pragma endregion Animals\r\n\r\n#pragma region Plants\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nPlantSelectEntry::PlantSelectEntry( const GuiPlant& plant )\r\n{\r\n\tm_name = plant.name.toStdString().c_str();\r\n\tm_sid  = plant.plantID.toStdString().c_str();\r\n\r\n\tstd::vector<unsigned char> buffer;\r\n\tGlobal::util->createBufferForNoesisImage( plant.sprite, buffer );\r\n\tm_bitmapSource = BitmapImage::Create( plant.sprite.width(), plant.sprite.height(), 96, 96, buffer.data(), plant.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n}\r\n\r\nconst char* PlantSelectEntry::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* PlantSelectEntry::GetSID() const\r\n{\r\n\treturn m_sid.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nPlantSelectRow::PlantSelectRow( QList<GuiPlant> plants )\r\n{\r\n\tm_entries = *new ObservableCollection<PlantSelectEntry>();\r\n\r\n\tfor ( auto plant : plants )\r\n\t{\r\n\t\tm_entries->Add( MakePtr<PlantSelectEntry>( plant ) );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<PlantSelectEntry>* PlantSelectRow::GetPlants() const\r\n{\r\n\treturn m_entries;\r\n}\r\n#pragma endregion Plants\r\n\r\n\r\n#pragma region Pasture\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nPastureAnimalEntry::PastureAnimalEntry( const GuiPastureAnimal& animal, AgricultureProxy* proxy ) :\r\n\tm_proxy( proxy )\r\n{\r\n\t\r\n\tm_sid       = animal.animalID.toStdString().c_str();\r\n\tm_id        = animal.id;\r\n\tm_toButcher = animal.toButcher;\r\n\tm_isYoung = animal.isYoung;\r\n\tm_gender = animal.gender;\r\n\r\n\tQString qName;\r\n\tif( m_gender == Gender::MALE )\r\n\t{\r\n\t\tqName += \"Male \";\r\n\t}\r\n\telse if( m_gender == Gender::FEMALE )\r\n\t{\r\n\t\tqName += \"Female \";\r\n\t}\r\n\tqName += animal.name;\r\n\tif( m_isYoung )\r\n\t{\r\n\t\tqName += \" (young)\";\r\n\t}\r\n\tm_name      = qName.toStdString().c_str();\r\n}\r\n\r\nconst char* PastureAnimalEntry::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nbool PastureAnimalEntry::GetButchering() const\r\n{\r\n\treturn m_toButcher;\r\n}\r\n\r\nvoid PastureAnimalEntry::SetButchering( bool value )\r\n{\r\n\tif ( m_toButcher != value )\r\n\t{\r\n\t\tm_toButcher = value;\r\n\t\tif( m_proxy )\r\n\t\t{\r\n\t\t\tm_proxy->setButchering( m_id, value );\r\n\t\t}\r\n\t}\r\n}\r\n#pragma endregion Pasture\r\n\r\n#pragma region PastureFood\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nFoodSelectEntry::FoodSelectEntry( const GuiPastureFoodItem& food, AgricultureProxy* proxy ) :\r\n\tm_proxy( proxy )\r\n{\r\n\tm_name = food.name.toStdString().c_str();\r\n\t\r\n\tm_itemSID  = food.itemSID;\r\n\tm_materialSID = food.materialSID;\r\n\tm_checked = food.checked;\r\n\r\n\tstd::vector<unsigned char> buffer;\r\n\tGlobal::util->createBufferForNoesisImage( food.sprite, buffer );\r\n\tm_bitmapSource = BitmapImage::Create( food.sprite.width(), food.sprite.height(), 96, 96, buffer.data(), food.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n}\r\n\r\nconst char* FoodSelectEntry::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nbool FoodSelectEntry::getChecked() const\r\n{\r\n\treturn m_checked;\r\n}\r\n\t\r\nvoid FoodSelectEntry::setChecked( bool value )\r\n{\r\n\tif( m_checked != value )\r\n\t{\r\n\t\tm_checked = value;\r\n\t\tm_proxy->setFoodItemChecked( m_itemSID, m_materialSID, m_checked );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nFoodSelectRow::FoodSelectRow( QList<GuiPastureFoodItem> foods, AgricultureProxy* proxy )\r\n{\r\n\tm_entries = *new ObservableCollection<FoodSelectEntry>();\r\n\r\n\tfor ( auto food : foods )\r\n\t{\r\n\t\tm_entries->Add( MakePtr<FoodSelectEntry>( food, proxy ) );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<FoodSelectEntry>* FoodSelectRow::GetFoods() const\r\n{\r\n\treturn m_entries;\r\n}\r\n#pragma endregion PastureFood\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAgricultureModel::AgricultureModel()\r\n{\r\n\tm_proxy = new AgricultureProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_prios = *new ObservableCollection<AcPriority>();\r\n\tfor ( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tm_prios->Add( MakePtr<AcPriority>( ( QString( \"Priority \" ) + QString::number( i + 1 ) ).toStdString().c_str() ) );\r\n\t}\r\n\tm_selectedPrio = m_prios->Get( 0 );\r\n\r\n\tm_plantRows      = *new ObservableCollection<PlantSelectRow>();\r\n\tm_animalRows     = *new ObservableCollection<AnimalSelectRow>();\r\n\tm_treeRows       = *new ObservableCollection<TreeSelectRow>();\r\n\tm_pastureAnimals = *new ObservableCollection<PastureAnimalEntry>();\r\n\tm_foodRows       = *new ObservableCollection<FoodSelectRow>();\r\n\r\n\tm_cmdSelectProduct.SetExecuteFunc( MakeDelegate( this, &AgricultureModel::onCmdSelectProduct ) );\r\n\tm_selectProduct.SetExecuteFunc( MakeDelegate( this, &AgricultureModel::onSelectProduct ) );\r\n\tm_manageAnimalsCmd.SetExecuteFunc( MakeDelegate( this, &AgricultureModel::onManageAnimals ) );\r\n\tm_manageAnimalsBackCmd.SetExecuteFunc( MakeDelegate( this, &AgricultureModel::onManageAnimalsBack ) );\r\n\tm_showPastureFoodCmd.SetExecuteFunc( MakeDelegate( this, &AgricultureModel::onShowPastureFood ) );\r\n}\r\n\r\nvoid AgricultureModel::updateGlobalPlantInfo( const QList<GuiPlant>& info )\r\n{\r\n\tm_plantRows->Clear();\r\n\tint plantDone = 0;\r\n\twhile ( plantDone < info.size() )\r\n\t{\r\n\t\tQList<GuiPlant> plantRow;\r\n\t\twhile ( plantRow.size() < 8 && plantDone < info.size() )\r\n\t\t{\r\n\t\t\tplantRow.append( info[plantDone] );\r\n\t\t\t++plantDone;\r\n\t\t}\r\n\t\tm_plantRows->Add( MakePtr<PlantSelectRow>( plantRow ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"PlantRows\" );\r\n}\r\n\r\nvoid AgricultureModel::updateGlobalAnimalInfo( const QList<GuiAnimal>& info )\r\n{\r\n\tm_animalRows->Clear();\r\n\tint animalDone = 0;\r\n\twhile ( animalDone < info.size() )\r\n\t{\r\n\t\tQList<GuiAnimal> animalRow;\r\n\t\twhile ( animalRow.size() < 8 && animalDone < info.size() )\r\n\t\t{\r\n\t\t\tanimalRow.append( info[animalDone] );\r\n\t\t\t++animalDone;\r\n\t\t}\r\n\t\tm_animalRows->Add( MakePtr<AnimalSelectRow>( animalRow ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"AnimalRows\" );\r\n}\r\n\r\nvoid AgricultureModel::updateGlobalTreeInfo( const QList<GuiPlant>& info )\r\n{\r\n\tm_treeRows->Clear();\r\n\tint plantDone = 0;\r\n\twhile ( plantDone < info.size() )\r\n\t{\r\n\t\tQList<GuiPlant> treeRow;\r\n\t\twhile ( treeRow.size() < 8 && plantDone < info.size() )\r\n\t\t{\r\n\t\t\ttreeRow.append( info[plantDone] );\r\n\t\t\t++plantDone;\r\n\t\t}\r\n\t\tm_treeRows->Add( MakePtr<TreeSelectRow>( treeRow ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"TreeRows\" );\r\n}\r\n\r\nvoid AgricultureModel::updateStandardInfo( unsigned int ID, AgriType type, QString name, QString product, int priority, int maxPriority, bool suspended )\r\n{\r\n\tm_blockSignals = true;\r\n\tbool isSame = ( m_id == ID );\r\n\tm_id        = ID;\r\n\tm_type      = type;\r\n\r\n\tif ( m_name != name.toStdString().c_str() )\r\n\t{\r\n\t\tm_name = name.toStdString().c_str();\r\n\t\tOnPropertyChanged( \"Name\" );\r\n\t}\r\n\tif ( m_suspended != suspended )\r\n\t{\r\n\t\tm_suspended = suspended;\r\n\t\tOnPropertyChanged( \"Suspended\" );\r\n\t}\r\n\r\n\tif ( m_prios->Count() != maxPriority )\r\n\t{\r\n\t\tm_prios->Clear();\r\n\t\tfor ( int i = 0; i < maxPriority; ++i )\r\n\t\t{\r\n\t\t\tm_prios->Add( MakePtr<AcPriority>( ( QString( \"Priority \" ) + QString::number( i + 1 ) ).toStdString().c_str() ) );\r\n\t\t}\r\n\t\tOnPropertyChanged( \"Priorities\" );\r\n\t}\r\n\tauto newPrio = m_prios->Get( qMin( qMax( 0, priority ), m_prios->Count() ) );\r\n\tif ( m_selectedPrio != newPrio )\r\n\t{\r\n\t\tm_selectedPrio = newPrio;\r\n\t\tOnPropertyChanged( \"SelectedPrio\" );\r\n\t}\r\n\r\n\tif ( m_productID != product || product.isEmpty() )\r\n\t{\r\n\t\tm_productID = product;\r\n\r\n\t\tif ( !m_productID.isEmpty() )\r\n\t\t{\r\n\t\t\tm_title = ( name + \" (\" + S::s( \"$MaterialName_\" + m_productID ) + \")\" ).toStdString().c_str();\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_title = m_name;\r\n\t\t}\r\n\t\tOnPropertyChanged( \"Title\" );\r\n\t}\r\n\tif ( !isSame )\r\n\t{\r\n\t\tm_manageWindow = false;\r\n\t\tm_productSelect = false;\r\n\r\n\t\tm_pastureAnimals->Clear();\r\n\t\tOnPropertyChanged( \"PastureAnimals\" );\r\n\r\n\t\tOnPropertyChanged( \"ShowFarm\" );\r\n\t\tOnPropertyChanged( \"ShowPasture\" );\r\n\t\tOnPropertyChanged( \"ShowGrove\" );\r\n\r\n\t\tOnPropertyChanged( \"ShowPlantSelect\" );\r\n\t\tOnPropertyChanged( \"ShowAnimalSelect\" );\r\n\t\tOnPropertyChanged( \"ShowTreeSelect\" );\r\n\t\tOnPropertyChanged( \"ShowPastureFoodSelect\" );\r\n\r\n\t\tOnPropertyChanged( \"ShowManageWindow\" );\r\n\t}\r\n\tm_blockSignals = false;\r\n}\r\n\r\nvoid AgricultureModel::updateFarmInfo( const GuiFarmInfo& info )\r\n{\r\n\tupdateStandardInfo( info.ID, AgriType::Farm, info.name, info.plantType, info.priority, info.maxPriority, info.suspended );\r\n\r\n\tif ( m_harvest != info.harvest )\r\n\t{\r\n\t\tm_harvest = info.harvest;\r\n\t\tOnPropertyChanged( \"Harvest\" );\r\n\t}\r\n\r\n\tm_tilled  = ( QString::number( info.tilled ) + \"/\" + QString::number( info.numPlots ) ).toStdString().c_str();\r\n\tm_planted = ( QString::number( info.planted ) + \"/\" + QString::number( info.numPlots ) ).toStdString().c_str();\r\n\tm_ready   = ( QString::number( info.cropReady ) + \"/\" + QString::number( info.numPlots ) ).toStdString().c_str();\r\n\r\n\tOnPropertyChanged( \"Tilled\" );\r\n\tOnPropertyChanged( \"Planted\" );\r\n\tOnPropertyChanged( \"HarvestReady\" );\r\n\r\n\tm_bitmapSource = nullptr;\r\n\tif ( !info.product.plantID.isEmpty() )\r\n\t{\r\n\t\tstd::vector<unsigned char> buffer;\r\n\t\tGlobal::util->createBufferForNoesisImage( info.product.sprite, buffer );\r\n\t\tm_bitmapSource = BitmapImage::Create( info.product.sprite.width(), info.product.sprite.height(), 96, 96, buffer.data(), info.product.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n\r\n\t\tm_title = ( QString( m_name.Str() ) + \" (\" + S::s( \"$MaterialName_\" + info.product.plantID ) + \")\" ).toStdString().c_str();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_title = m_name;\r\n\t}\r\n\tOnPropertyChanged( \"Image\" );\r\n\tOnPropertyChanged( \"Title\" );\r\n\r\n\tm_numSeeds  = QString::number( info.product.seedCount ).toStdString().c_str();\r\n\tm_numItems  = QString::number( info.product.itemCount ).toStdString().c_str();\r\n\tm_numPlants = QString::number( info.product.plantCount ).toStdString().c_str();\r\n\r\n\tOnPropertyChanged( \"NumSeeds\" );\r\n\tOnPropertyChanged( \"NumItems\" );\r\n\tOnPropertyChanged( \"NumPlants\" );\r\n}\r\n\r\nvoid AgricultureModel::updatePastureInfo( const GuiPastureInfo& info )\r\n{\r\n\tupdateStandardInfo( info.ID, AgriType::Pasture, info.name, info.animalType, info.priority, info.maxPriority, info.suspended );\r\n\r\n\tif ( m_harvest != info.harvest )\r\n\t{\r\n\t\tm_harvest = info.harvest;\r\n\t\tOnPropertyChanged( \"Harvest\" );\r\n\t}\r\n\tif ( m_harvestHay != info.harvestHay )\r\n\t{\r\n\t\tm_harvestHay = info.harvestHay;\r\n\t\tOnPropertyChanged( \"HarvestHay\" );\r\n\t}\r\n\r\n\tm_maxAnimals = info.maxNumber;\r\n\tm_numAnimals = ( QString::number( info.numMale + info.numFemale ) + \"/\" + QString::number( info.maxNumber ) ).toStdString().c_str();\r\n\tm_numMale    = ( QString::number( info.numMale ) + \"/\" ).toStdString().c_str();\r\n\tm_numFemale  = ( QString::number( info.numFemale ) + \"/\" ).toStdString().c_str();\r\n\tm_maxMale    = ( QString::number( info.maxMale ) ).toStdString().c_str();\r\n\tm_maxFemale  = ( QString::number( info.maxFemale ) ).toStdString().c_str();\r\n\tm_foodStatus = ( QString::number( info.foodCurrent ) + \"/\" + QString::number( info.foodMax ) ).toStdString().c_str();\r\n\tm_hayStatus  = ( QString::number( info.hayCurrent ) + \"/\" ).toStdString().c_str();\r\n\tm_maxHay     = ( QString::number( info.hayMax ) ).toStdString().c_str();\r\n\r\n\r\n\tm_pastureAnimals->Clear();\r\n\r\n\tfor ( const auto& pa : info.animals )\r\n\t{\r\n\t\tm_pastureAnimals->Add( MakePtr<PastureAnimalEntry>( pa, m_proxy ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"NumAnimals\" );\r\n\tOnPropertyChanged( \"NumMale\" );\r\n\tOnPropertyChanged( \"NumFemale\" );\r\n\tOnPropertyChanged( \"MaxMale\" );\r\n\tOnPropertyChanged( \"MaxFemale\" );\r\n\tOnPropertyChanged( \"VisManageAnimals\" );\r\n\tOnPropertyChanged( \"PastureAnimals\" );\r\n\tOnPropertyChanged( \"ShowManageWindow\" );\r\n\tOnPropertyChanged( \"MaxHay\" );\r\n\tOnPropertyChanged( \"HayStatus\" );\r\n\tOnPropertyChanged( \"FoodStatus\" );\r\n\r\n\tm_bitmapSource = nullptr;\r\n\tif ( !info.product.animalID.isEmpty() )\r\n\t{\r\n\t\tstd::vector<unsigned char> buffer;\r\n\t\tGlobal::util->createBufferForNoesisImage( info.product.sprite, buffer );\r\n\t\tm_bitmapSource = BitmapImage::Create( info.product.sprite.width(), info.product.sprite.height(), 96, 96, buffer.data(), info.product.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n\r\n\t\tm_title = ( QString( m_name.Str() ) + \" (\" + S::s( \"$CreatureName_\" + info.product.animalID ) + \")\" ).toStdString().c_str();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_title = m_name;\r\n\t}\r\n\tOnPropertyChanged( \"Image\" );\r\n\tOnPropertyChanged( \"Title\" );\r\n\r\n\tm_foodRows->Clear();\r\n\tif( !info.food.isEmpty() )\r\n\t{\t\r\n\t\tint foodDone = 0;\r\n\t\twhile ( foodDone < info.food.size() )\r\n\t\t{\r\n\t\t\tQList<GuiPastureFoodItem> foodRow;\r\n\t\t\twhile ( foodRow.size() < 8 && foodDone < info.food.size() )\r\n\t\t\t{\r\n\t\t\t\tfoodRow.append( info.food[foodDone] );\r\n\t\t\t\t++foodDone;\r\n\t\t\t}\r\n\t\t\tm_foodRows->Add( MakePtr<FoodSelectRow>( foodRow, m_proxy ) );\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"FoodRows\" );\r\n}\r\n\r\nvoid AgricultureModel::updateGroveInfo( const GuiGroveInfo& info )\r\n{\r\n\tupdateStandardInfo( info.ID, AgriType::Grove, info.name, info.treeType, info.priority, info.maxPriority, info.suspended );\r\n\r\n\tm_plantTrees = info.plantTrees;\r\n\tm_fellTrees  = info.fellTrees;\r\n\tm_pickFruits = info.pickFruits;\r\n\tm_numPlants  = ( \"Planted trees: \" + QString::number( info.planted ) ).toStdString().c_str();\r\n\tm_numPlots   = ( \"Num plots: \" + QString::number( info.numPlots ) ).toStdString().c_str();\r\n\r\n\tOnPropertyChanged( \"PlantTrees\" );\r\n\tOnPropertyChanged( \"FellTrees\" );\r\n\tOnPropertyChanged( \"PickFruits\" );\r\n\tOnPropertyChanged( \"NumPlants\" );\r\n\tOnPropertyChanged( \"NumPlots\" );\r\n\r\n\tm_bitmapSource = nullptr;\r\n\tif ( !info.product.plantID.isEmpty() )\r\n\t{\r\n\t\tstd::vector<unsigned char> buffer;\r\n\t\tGlobal::util->createBufferForNoesisImage( info.product.sprite, buffer );\r\n\r\n\t\tm_bitmapSource = BitmapImage::Create( info.product.sprite.width(), info.product.sprite.height(), 96, 96, buffer.data(), info.product.sprite.width() * 4, BitmapSource::Format::Format_RGBA8 );\r\n\r\n\t\tm_title = ( QString( m_name.Str() ) + \" (\" + S::s( \"$ItemName_\" + info.product.plantID ) + \")\" ).toStdString().c_str();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_title = m_name;\r\n\t}\r\n\tOnPropertyChanged( \"Image\" );\r\n\tOnPropertyChanged( \"Title\" );\r\n}\r\n\r\nvoid AgricultureModel::setBasicOptions()\r\n{\r\n\tif( !m_blockSignals )\r\n\t{\r\n\t\tm_proxy->setBasicOptions( m_id, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended );\r\n\t}\r\n}\r\n\r\nconst char* AgricultureModel::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetTitle() const\r\n{\r\n\treturn m_title.Str();\r\n}\r\n\r\nvoid AgricultureModel::SetName( const char* value )\r\n{\r\n\tm_name = value;\r\n\tsetBasicOptions();\r\n\tOnPropertyChanged( \"Name\" );\r\n}\r\n\r\nbool AgricultureModel::GetSuspended() const\r\n{\r\n\treturn m_suspended;\r\n}\r\n\r\nvoid AgricultureModel::SetSuspended( bool value )\r\n{\r\n\tif ( m_suspended != value )\r\n\t{\r\n\t\tm_suspended = value;\r\n\t\tsetBasicOptions();\r\n\t\tOnPropertyChanged( \"Suspended\" );\r\n\t}\r\n}\r\n\r\nbool AgricultureModel::GetHarvest() const\r\n{\r\n\treturn m_harvest;\r\n}\r\n\r\nvoid AgricultureModel::SetHarvest( bool value )\r\n{\r\n\tif ( m_harvest != value )\r\n\t{\r\n\t\tm_harvest = value;\r\n\t\tm_proxy->setHarvestOptions( m_id, m_harvest, m_harvestHay, m_tameWild );\r\n\t\tOnPropertyChanged( \"Harvest\" );\r\n\t}\r\n}\r\n\r\nbool AgricultureModel::GetTame() const\r\n{\r\n\treturn m_tameWild;\r\n}\r\n\r\nvoid AgricultureModel::SetTame( bool value )\r\n{\r\n\tif ( m_tameWild != value )\r\n\t{\r\n\t\tm_tameWild = value;\r\n\t\tm_proxy->setHarvestOptions( m_id, m_harvest, m_harvestHay, m_tameWild );\r\n\t\tOnPropertyChanged( \"Tame\" );\r\n\t}\r\n}\r\n\r\nbool AgricultureModel::GetHarvestHay() const\r\n{\r\n\treturn m_harvestHay;\r\n}\r\n\r\nvoid AgricultureModel::SetHarvestHay( bool value )\r\n{\r\n\tif ( m_harvestHay != value )\r\n\t{\r\n\t\tm_harvestHay = value;\r\n\t\tm_proxy->setHarvestOptions( m_id, m_harvest, m_harvestHay, m_tameWild );\r\n\t\tOnPropertyChanged( \"HarvestHay\" );\r\n\t}\r\n}\r\n\r\nbool AgricultureModel::GetPlantTrees() const\r\n{\r\n\treturn m_plantTrees;\r\n}\r\n\r\nvoid AgricultureModel::SetPlantTrees( bool value )\r\n{\r\n\tif ( m_plantTrees != value )\r\n\t{\r\n\t\tm_plantTrees = value;\r\n\t\tm_proxy->setGroveOptions( m_id, m_pickFruits, m_plantTrees, m_fellTrees );\r\n\t\tOnPropertyChanged( \"PlantTrees\" );\r\n\t}\r\n}\r\n\r\nbool AgricultureModel::GetFellTrees() const\r\n{\r\n\treturn m_fellTrees;\r\n}\r\n\r\nvoid AgricultureModel::SetFellTrees( bool value )\r\n{\r\n\tif ( m_fellTrees != value )\r\n\t{\r\n\t\tm_fellTrees = value;\r\n\t\tm_proxy->setGroveOptions( m_id, m_pickFruits, m_plantTrees, m_fellTrees );\r\n\t\tOnPropertyChanged( \"FellTrees\" );\r\n\t}\r\n}\r\n\r\nbool AgricultureModel::GetPickFruits() const\r\n{\r\n\treturn m_pickFruits;\r\n}\r\n\r\nvoid AgricultureModel::SetPickFruits( bool value )\r\n{\r\n\tif ( m_pickFruits != value )\r\n\t{\r\n\t\tm_pickFruits = value;\r\n\t\tm_proxy->setGroveOptions( m_id, m_pickFruits, m_plantTrees, m_fellTrees );\r\n\t\tOnPropertyChanged( \"PickFruits\" );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<AcPriority>* AgricultureModel::GetPrios() const\r\n{\r\n\treturn m_prios;\r\n}\r\n\r\nvoid AgricultureModel::SetSelectedPriority( AcPriority* prio )\r\n{\r\n\tif ( m_selectedPrio && prio && m_selectedPrio != prio )\r\n\t{\r\n\t\tm_selectedPrio = prio;\r\n\t\tsetBasicOptions();\r\n\t\tOnPropertyChanged( \"SelectedPrio\" );\r\n\t}\r\n}\r\n\r\nAcPriority* AgricultureModel::GetSelectedPriority() const\r\n{\r\n\treturn m_selectedPrio;\r\n}\r\n\r\nconst char* AgricultureModel::GetShowFarm() const\r\n{\r\n\tif ( m_type == AgriType::Farm && !m_productSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* AgricultureModel::GetShowPasture() const\r\n{\r\n\tif ( m_type == AgriType::Pasture && !m_productSelect && !m_manageWindow && !m_pastureFoodSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* AgricultureModel::GetShowGrove() const\r\n{\r\n\tif ( m_type == AgriType::Grove && !m_productSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* AgricultureModel::GetShowPlantSelect() const\r\n{\r\n\tif ( m_type == AgriType::Farm && m_productSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* AgricultureModel::GetShowAnimalSelect() const\r\n{\r\n\tif ( m_type == AgriType::Pasture && m_productSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* AgricultureModel::GetShowTreeSelect() const\r\n{\r\n\tif ( m_type == AgriType::Grove && m_productSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* AgricultureModel::GetShowPastureFoodSelect() const\r\n{\r\n\tif ( m_type == AgriType::Pasture && m_pastureFoodSelect )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid AgricultureModel::onCmdSelectProduct( BaseComponent* param )\r\n{\r\n\tQString qParam( param->ToString().Str() );\r\n\tm_productSelect = ( qParam == \"Open\" );\r\n\tOnPropertyChanged( \"ShowFarm\" );\r\n\tOnPropertyChanged( \"ShowPasture\" );\r\n\tOnPropertyChanged( \"ShowGrove\" );\r\n\tOnPropertyChanged( \"ShowPlantSelect\" );\r\n\tOnPropertyChanged( \"ShowAnimalSelect\" );\r\n\tOnPropertyChanged( \"ShowTreeSelect\" );\r\n\r\n\tswitch ( m_type )\r\n\t{\r\n\t\tcase AgriType::Farm:\r\n\t\t\tif ( m_plantRows->Count() == 0 )\r\n\t\t\t{\r\n\t\t\t\tm_proxy->requestGlobalPlantInfo();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase AgriType::Pasture:\r\n\t\t\tif ( m_animalRows->Count() == 0 )\r\n\t\t\t{\r\n\t\t\t\tm_proxy->requestGlobalAnimalInfo();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tcase AgriType::Grove:\r\n\t\t\tif ( m_treeRows->Count() == 0 )\r\n\t\t\t{\r\n\t\t\t\tm_proxy->requestGlobalTreeInfo();\r\n\t\t\t}\r\n\t\t\tbreak;\r\n\t\tdefault:\r\n\r\n\t\t\tbreak;\r\n\t}\r\n}\r\n\r\nvoid AgricultureModel::onSelectProduct( BaseComponent* param )\r\n{\r\n\tm_productSelect = false;\r\n\tm_proxy->selectProduct( m_id, param->ToString().Str() );\r\n\tOnPropertyChanged( \"ShowFarm\" );\r\n\tOnPropertyChanged( \"ShowPasture\" );\r\n\tOnPropertyChanged( \"ShowGrove\" );\r\n\tOnPropertyChanged( \"ShowPlantSelect\" );\r\n\tOnPropertyChanged( \"ShowAnimalSelect\" );\r\n\tOnPropertyChanged( \"ShowTreeSelect\" );\r\n}\r\n\r\nconst char* AgricultureModel::GetTilled() const\r\n{\r\n\treturn m_tilled.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetPlanted() const\r\n{\r\n\treturn m_planted.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetHarvestReady() const\r\n{\r\n\treturn m_ready.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumSeeds() const\r\n{\r\n\treturn m_numSeeds.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumItems() const\r\n{\r\n\treturn m_numItems.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumPlots() const\r\n{\r\n\treturn m_numPlots.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumPlants() const\r\n{\r\n\treturn m_numPlants.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumAnimals() const\r\n{\r\n\treturn m_numAnimals.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumMale() const\r\n{\r\n\treturn m_numMale.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetNumFemale() const\r\n{\r\n\treturn m_numFemale.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetMaxMale() const\r\n{\r\n\treturn m_maxMale.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetMaxFemale() const\r\n{\r\n\treturn m_maxFemale.Str();\r\n}\r\n\r\nvoid AgricultureModel::SetMaxMale( const char* value )\r\n{\r\n\tbool ok;\r\n\tQString ns( value );\r\n\tint max = ns.toInt( &ok );\r\n\tif ( ok )\r\n\t{\r\n\t\tif ( max <= m_maxAnimals && max >= 0 )\r\n\t\t{\r\n\t\t\tm_maxMale = ( QString::number( max ) ).toStdString().c_str();\r\n\t\t\tm_proxy->setMaxMale( m_id, max );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_maxMale = ( QString::number( m_maxAnimals ) ).toStdString().c_str();\r\n\t\t\tOnPropertyChanged( \"MaxMale\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_maxMale = ( QString::number( m_maxAnimals ) ).toStdString().c_str();\r\n\t\tOnPropertyChanged( \"MaxMale\" );\r\n\t}\r\n}\r\n\r\nvoid AgricultureModel::SetMaxFemale( const char* value )\r\n{\r\n\tbool ok;\r\n\tQString ns( value );\r\n\tint max = ns.toInt( &ok );\r\n\tif ( ok )\r\n\t{\r\n\t\tif ( max <= m_maxAnimals && max >= 0 )\r\n\t\t{\r\n\t\t\tm_maxFemale = ( QString::number( max ) ).toStdString().c_str();\r\n\t\t\tm_proxy->signalSetMaxFemale( m_id, max );\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tm_maxFemale = ( QString::number( m_maxAnimals ) ).toStdString().c_str();\r\n\t\t\tOnPropertyChanged( \"MaxFemale\" );\r\n\t\t}\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_maxFemale = ( QString::number( m_maxAnimals ) ).toStdString().c_str();\r\n\t\tOnPropertyChanged( \"MaxFemale\" );\r\n\t}\r\n}\r\n\r\nconst char* AgricultureModel::GetManageAnimalsVisible() const\r\n{\r\n\tif ( m_maxAnimals > 0 ) //has an animal type set\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn \"Hidden\";\r\n\t}\r\n}\r\n\r\nvoid AgricultureModel::onManageAnimals( BaseComponent* param )\r\n{\r\n\tm_proxy->requestPastureAnimalInfo();\r\n\r\n\tm_manageWindow  = true;\r\n\tm_productSelect = false;\r\n\tm_pastureFoodSelect = false;\r\n\tOnPropertyChanged( \"ShowManageWindow\" );\r\n\tOnPropertyChanged( \"ShowPasture\" );\r\n}\r\n\r\nvoid AgricultureModel::onManageAnimalsBack( BaseComponent* param )\r\n{\r\n\tm_manageWindow  = false;\r\n\tm_productSelect = false;\r\n\tm_pastureFoodSelect = false;\r\n\tOnPropertyChanged( \"ShowManageWindow\" );\r\n\tOnPropertyChanged( \"ShowPasture\" );\r\n}\r\n\r\nconst char* AgricultureModel::GetManageWindowVis() const\r\n{\r\n\tif ( m_type == AgriType::Pasture && m_manageWindow )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid AgricultureModel::onShowPastureFood( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qParam = param->ToString().Str();\r\n\t\tif( qParam == \"Back\" )\r\n\t\t{\r\n\t\t\tm_pastureFoodSelect = false;\r\n\t\t}\r\n\t\telse if( qParam == \"Show\" )\r\n\t\t{\r\n\t\t\tm_proxy->requestPastureFoodInfo();\r\n\t\t\tm_pastureFoodSelect = true;\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"ShowPastureFoodSelect\" );\r\n\tOnPropertyChanged( \"ShowPasture\" );\r\n}\r\n\r\nconst char* AgricultureModel::GetFoodStatus() const\r\n{\r\n\treturn m_foodStatus.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetHayStatus() const\r\n{\r\n\treturn m_hayStatus.Str();\r\n}\r\n\r\nconst char* AgricultureModel::GetMaxHay() const\r\n{\r\n\treturn m_maxHay.Str();\r\n}\r\n\r\nvoid AgricultureModel::SetMaxHay( const char* value )\r\n{\r\n\tif( value )\r\n\t{\r\n\t\tQString qValue = value;\r\n\t\tbool ok;\r\n\t\tint val = qValue.toInt( &ok );\r\n\t\tif( ok )\r\n\t\t{\r\n\t\t\tm_maxHay = value;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( AgricultureModel, \"IngnomiaGUI.AgricultureModel\" )\r\n{\r\n\tNsProp( \"Name\", &AgricultureModel::GetName, &AgricultureModel::SetName );\r\n\tNsProp( \"Title\", &AgricultureModel::GetTitle );\r\n\tNsProp( \"Suspended\", &AgricultureModel::GetSuspended, &AgricultureModel::SetSuspended );\r\n\tNsProp( \"Harvest\", &AgricultureModel::GetHarvest, &AgricultureModel::SetHarvest );\r\n\tNsProp( \"Priorities\", &AgricultureModel::GetPrios );\r\n\tNsProp( \"SelectedPrio\", &AgricultureModel::GetSelectedPriority, &AgricultureModel::SetSelectedPriority );\r\n\r\n\tNsProp( \"ShowFarm\", &AgricultureModel::GetShowFarm );\r\n\tNsProp( \"ShowPasture\", &AgricultureModel::GetShowPasture );\r\n\tNsProp( \"ShowGrove\", &AgricultureModel::GetShowGrove );\r\n\tNsProp( \"ShowPlantSelect\", &AgricultureModel::GetShowPlantSelect );\r\n\tNsProp( \"ShowAnimalSelect\", &AgricultureModel::GetShowAnimalSelect );\r\n\tNsProp( \"ShowTreeSelect\", &AgricultureModel::GetShowTreeSelect );\r\n\tNsProp( \"ShowManageWindow\", &AgricultureModel::GetManageWindowVis );\r\n\tNsProp( \"ShowPastureFoodSelect\", &AgricultureModel::GetShowPastureFoodSelect );\r\n\tNsProp( \"CmdShowPastureFood\", &AgricultureModel::GetShowPastureFoodCmd );\r\n\r\n\tNsProp( \"PlantRows\", &AgricultureModel::GetPlants );\r\n\tNsProp( \"AnimalRows\", &AgricultureModel::GetAnimals );\r\n\tNsProp( \"PastureAnimals\", &AgricultureModel::GetPastureAnimals );\r\n\tNsProp( \"TreeRows\", &AgricultureModel::GetTrees );\r\n\tNsProp( \"FoodRows\", &AgricultureModel::GetFoods );\r\n\r\n\tNsProp( \"ProductSelection\", &AgricultureModel::GetCmdSelectProduct );\r\n\tNsProp( \"SelectProduct\", &AgricultureModel::GetSelectProduct );\r\n\r\n\tNsProp( \"NumPlots\", &AgricultureModel::GetNumPlots );\r\n\r\n\tNsProp( \"Tilled\", &AgricultureModel::GetTilled );\r\n\tNsProp( \"Planted\", &AgricultureModel::GetPlanted );\r\n\tNsProp( \"HarvestReady\", &AgricultureModel::GetHarvestReady );\r\n\r\n\tNsProp( \"NumSeeds\", &AgricultureModel::GetNumSeeds );\r\n\tNsProp( \"NumItems\", &AgricultureModel::GetNumItems );\r\n\tNsProp( \"NumPlants\", &AgricultureModel::GetNumPlants );\r\n\r\n\tNsProp( \"NumAnimals\", &AgricultureModel::GetNumAnimals );\r\n\tNsProp( \"NumMale\", &AgricultureModel::GetNumMale );\r\n\tNsProp( \"NumFemale\", &AgricultureModel::GetNumFemale );\r\n\tNsProp( \"MaxMale\", &AgricultureModel::GetMaxMale, &AgricultureModel::SetMaxMale );\r\n\tNsProp( \"MaxFemale\", &AgricultureModel::GetMaxFemale, &AgricultureModel::SetMaxFemale );\r\n\tNsProp( \"VisManageAnimals\", &AgricultureModel::GetManageAnimalsVisible );\r\n\tNsProp( \"ManageAnimals\", &AgricultureModel::GetManageAnimals );\r\n\tNsProp( \"ManageAnimalsBack\", &AgricultureModel::GetManageAnimalsBack );\r\n\tNsProp( \"HarvestHay\", &AgricultureModel::GetHarvestHay, &AgricultureModel::SetHarvestHay );\r\n\tNsProp( \"Tame\", &AgricultureModel::GetTame, &AgricultureModel::SetTame );\r\n\r\n\tNsProp( \"FoodStatus\", &AgricultureModel::GetFoodStatus );\r\n\tNsProp( \"HayStatus\", &AgricultureModel::GetHayStatus );\r\n\tNsProp( \"MaxHay\", &AgricultureModel::GetMaxHay, &AgricultureModel::SetMaxHay );\r\n\r\n\tNsProp( \"PlantTrees\", &AgricultureModel::GetPlantTrees, &AgricultureModel::SetPlantTrees );\r\n\tNsProp( \"FellTrees\", &AgricultureModel::GetFellTrees, &AgricultureModel::SetFellTrees );\r\n\tNsProp( \"PickFruits\", &AgricultureModel::GetPickFruits, &AgricultureModel::SetPickFruits );\r\n\r\n\tNsProp( \"Image\", &AgricultureModel::getBitmapSource );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( AcPriority )\r\n{\r\n\tNsProp( \"Name\", &AcPriority::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( PlantSelectEntry )\r\n{\r\n\tNsProp( \"Name\", &PlantSelectEntry::GetName );\r\n\tNsProp( \"ID\", &PlantSelectEntry::GetSID );\r\n\tNsProp( \"Image\", &PlantSelectEntry::getBitmapSource );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( PlantSelectRow )\r\n{\r\n\tNsProp( \"Plants\", &PlantSelectRow::GetPlants );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( AnimalSelectEntry )\r\n{\r\n\tNsProp( \"Name\", &AnimalSelectEntry::GetName );\r\n\tNsProp( \"ID\", &AnimalSelectEntry::GetSID );\r\n\tNsProp( \"Image\", &AnimalSelectEntry::getBitmapSource );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( AnimalSelectRow )\r\n{\r\n\tNsProp( \"Animals\", &AnimalSelectRow::GetAnimals );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( TreeSelectEntry )\r\n{\r\n\tNsProp( \"Name\", &TreeSelectEntry::GetName );\r\n\tNsProp( \"ID\", &TreeSelectEntry::GetSID );\r\n\tNsProp( \"Image\", &TreeSelectEntry::getBitmapSource );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( TreeSelectRow )\r\n{\r\n\tNsProp( \"Trees\", &TreeSelectRow::GetTrees );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( PastureAnimalEntry )\r\n{\r\n\tNsProp( \"Name\", &PastureAnimalEntry::GetName );\r\n\tNsProp( \"ToButcher\", &PastureAnimalEntry::GetButchering, &PastureAnimalEntry::SetButchering );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( FoodSelectEntry )\r\n{\r\n\tNsProp( \"Name\", &FoodSelectEntry::GetName );\r\n\tNsProp( \"Image\", &FoodSelectEntry::getBitmapSource );\r\n\tNsProp( \"Checked\", &FoodSelectEntry::getChecked, &FoodSelectEntry::setChecked );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( FoodSelectRow )\r\n{\r\n\tNsProp( \"Foods\", &FoodSelectRow::GetFoods );\r\n}"
  },
  {
    "path": "src/gui/xaml/agriculturemodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __AgricultureModel_H__\r\n#define __AgricultureModel_H__\r\n\r\n#include \"../aggregatoragri.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n#include <NsGui/ImageSource.h>\r\n#include <NsGui/BitmapSource.h>\r\n#include <NsGui/BitmapImage.h>\r\n\r\n#include <QString>\r\n\r\nclass AgricultureProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n#pragma region AcPriority\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass AcPriority final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tAcPriority( const char* name );\r\n\r\n\tconst char* GetName() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\r\n\tNS_DECLARE_REFLECTION( AcPriority, Noesis::BaseComponent )\r\n};\r\n#pragma endregion AcPriority\r\n\r\nclass TreeSelectEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tTreeSelectEntry( const GuiPlant& tree );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetSID() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\r\n\tconst Noesis::ImageSource* getBitmapSource() const\r\n\t{\r\n\t\treturn m_bitmapSource;\r\n\t}\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapSource;\r\n\r\n\tNS_DECLARE_REFLECTION( TreeSelectEntry, Noesis::BaseComponent )\r\n};\r\n\r\nclass TreeSelectRow : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tTreeSelectRow( QList<GuiPlant> trees );\r\n\r\nprivate:\r\n\tNoesis::ObservableCollection<TreeSelectEntry>* GetTrees() const;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<TreeSelectEntry>> m_entries;\r\n\r\n\tNS_DECLARE_REFLECTION( TreeSelectRow, Noesis::BaseComponent )\r\n};\r\n\r\nclass AnimalSelectEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tAnimalSelectEntry( const GuiAnimal& Animal );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetSID() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\r\n\tconst Noesis::ImageSource* getBitmapSource() const\r\n\t{\r\n\t\treturn m_bitmapSource;\r\n\t}\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapSource;\r\n\r\n\tNS_DECLARE_REFLECTION( AnimalSelectEntry, Noesis::BaseComponent )\r\n};\r\n\r\nclass AnimalSelectRow : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tAnimalSelectRow( QList<GuiAnimal> Animals );\r\n\r\nprivate:\r\n\tNoesis::ObservableCollection<AnimalSelectEntry>* GetAnimals() const;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AnimalSelectEntry>> m_entries;\r\n\r\n\tNS_DECLARE_REFLECTION( AnimalSelectRow, Noesis::BaseComponent )\r\n};\r\n\r\nclass PastureAnimalEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tPastureAnimalEntry( const GuiPastureAnimal& Animal, AgricultureProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tbool GetButchering() const;\r\n\tvoid SetButchering( bool value );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\tunsigned int m_id;\r\n\tbool m_toButcher = false;\r\n\tbool m_isYoung = false;\r\n\tGender m_gender = Gender::UNDEFINED;\r\n\r\n\tAgricultureProxy* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( PastureAnimalEntry, Noesis::BaseComponent )\r\n};\r\n\r\n\r\nclass PlantSelectEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tPlantSelectEntry( const GuiPlant& plant );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetSID() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\r\n\tconst Noesis::ImageSource* getBitmapSource() const\r\n\t{\r\n\t\treturn m_bitmapSource;\r\n\t}\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapSource;\r\n\r\n\tNS_DECLARE_REFLECTION( PlantSelectEntry, Noesis::BaseComponent )\r\n};\r\n\r\nclass PlantSelectRow : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tPlantSelectRow( QList<GuiPlant> plants );\r\n\r\nprivate:\r\n\tNoesis::ObservableCollection<PlantSelectEntry>* GetPlants() const;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<PlantSelectEntry>> m_entries;\r\n\r\n\tNS_DECLARE_REFLECTION( PlantSelectRow, Noesis::BaseComponent )\r\n};\r\n\r\n\r\n\r\nclass FoodSelectEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tFoodSelectEntry( const GuiPastureFoodItem& item, AgricultureProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tbool getChecked() const;\r\n\tvoid setChecked( bool value );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tQString m_itemSID;\r\n\tQString m_materialSID;\r\n\tbool m_checked = false;\r\n\r\n\tAgricultureProxy* m_proxy = nullptr;\r\n\r\n\tconst Noesis::ImageSource* getBitmapSource() const\r\n\t{\r\n\t\treturn m_bitmapSource;\r\n\t}\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapSource;\r\n\r\n\tNS_DECLARE_REFLECTION( FoodSelectEntry, Noesis::BaseComponent )\r\n};\r\n\r\nclass FoodSelectRow : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tFoodSelectRow( QList<GuiPastureFoodItem> plants, AgricultureProxy* proxy );\r\n\r\nprivate:\r\n\tNoesis::ObservableCollection<FoodSelectEntry>* GetFoods() const;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<FoodSelectEntry>> m_entries;\r\n\r\n\tNS_DECLARE_REFLECTION( FoodSelectRow, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass AgricultureModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tAgricultureModel();\r\n\r\n\tvoid updateStandardInfo( unsigned int ID, AgriType type, QString name, QString product, int priority, int maxPriority, bool suspended );\r\n\tvoid updateFarmInfo( const GuiFarmInfo& info );\r\n\tvoid updatePastureInfo( const GuiPastureInfo& info );\r\n\tvoid updateGroveInfo( const GuiGroveInfo& info );\r\n\tvoid updateGlobalPlantInfo( const QList<GuiPlant>& info );\r\n\tvoid updateGlobalAnimalInfo( const QList<GuiAnimal>& info );\r\n\tvoid updateGlobalTreeInfo( const QList<GuiPlant>& info );\r\n\r\nprivate:\r\n\tconst char* GetName() const;\r\n\tconst char* GetTitle() const;\r\n\tvoid SetName( const char* value );\r\n\tbool GetSuspended() const;\r\n\tvoid SetSuspended( bool value );\r\n\tbool GetHarvest() const;\r\n\tvoid SetHarvest( bool value );\r\n\tbool GetPlantTrees() const;\r\n\tvoid SetPlantTrees( bool value );\r\n\tbool GetFellTrees() const;\r\n\tvoid SetFellTrees( bool value );\r\n\tbool GetPickFruits() const;\r\n\tvoid SetPickFruits( bool value );\r\n\tbool GetHarvestHay() const;\r\n\tvoid SetHarvestHay( bool value );\r\n\tbool GetTame() const;\r\n\tvoid SetTame( bool value );\r\n\r\n\tconst char* GetShowFarm() const;\r\n\tconst char* GetShowPasture() const;\r\n\tconst char* GetShowGrove() const;\r\n\tconst char* GetShowPlantSelect() const;\r\n\tconst char* GetShowAnimalSelect() const;\r\n\tconst char* GetShowTreeSelect() const;\r\n\tconst char* GetShowPastureFoodSelect() const;\r\n\r\n\tconst char* GetTilled() const;\r\n\tconst char* GetPlanted() const;\r\n\tconst char* GetHarvestReady() const;\r\n\r\n\tconst char* GetNumAnimals() const;\r\n\tconst char* GetNumMale() const;\r\n\tconst char* GetNumFemale() const;\r\n\tconst char* GetMaxMale() const;\r\n\tconst char* GetMaxFemale() const;\r\n\tvoid SetMaxMale( const char* value );\r\n\tvoid SetMaxFemale( const char* value );\r\n\tconst char* GetManageAnimalsVisible() const;\r\n\tconst char* GetManageWindowVis() const;\r\n\r\n\tconst char* GetNumPlots() const;\r\n\tconst char* GetNumSeeds() const;\r\n\tconst char* GetNumItems() const;\r\n\tconst char* GetNumPlants() const;\r\n\r\n\tconst char* GetFoodStatus() const;\r\n\tconst char* GetHayStatus() const;\r\n\tconst char* GetMaxHay() const;\r\n\tvoid SetMaxHay( const char* value );\r\n\r\n\tNoesis::ObservableCollection<AcPriority>* GetPrios() const;\r\n\tvoid SetSelectedPriority( AcPriority* prio );\r\n\tAcPriority* GetSelectedPriority() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AcPriority>> m_prios;\r\n\tAcPriority* m_selectedPrio = nullptr;\r\n\r\n\tvoid onCmdSelectProduct( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetCmdSelectProduct() const\r\n\t{\r\n\t\treturn &m_cmdSelectProduct;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_cmdSelectProduct;\r\n\r\n\tvoid onSelectProduct( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSelectProduct() const\r\n\t{\r\n\t\treturn &m_selectProduct;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_selectProduct;\r\n\r\n\tvoid onManageAnimals( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetManageAnimals() const\r\n\t{\r\n\t\treturn &m_manageAnimalsCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_manageAnimalsCmd;\r\n\r\n\tvoid onManageAnimalsBack( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetManageAnimalsBack() const\r\n\t{\r\n\t\treturn &m_manageAnimalsBackCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_manageAnimalsBackCmd;\r\n\r\n\tvoid onShowPastureFood( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetShowPastureFoodCmd() const\r\n\t{\r\n\t\treturn &m_showPastureFoodCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_showPastureFoodCmd;\r\n\r\n\tNoesis::ObservableCollection<PlantSelectRow>* GetPlants() const\r\n\t{\r\n\t\treturn m_plantRows;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<PlantSelectRow>> m_plantRows;\r\n\r\n\tNoesis::ObservableCollection<AnimalSelectRow>* GetAnimals() const\r\n\t{\r\n\t\treturn m_animalRows;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AnimalSelectRow>> m_animalRows;\r\n\r\n\tNoesis::ObservableCollection<TreeSelectRow>* GetTrees() const\r\n\t{\r\n\t\treturn m_treeRows;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<TreeSelectRow>> m_treeRows;\r\n\r\n\tNoesis::ObservableCollection<PastureAnimalEntry>* GetPastureAnimals() const\r\n\t{\r\n\t\treturn m_pastureAnimals;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<PastureAnimalEntry>> m_pastureAnimals;\r\n\r\n\tNoesis::ObservableCollection<FoodSelectRow>* GetFoods() const\r\n\t{\r\n\t\treturn m_foodRows;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<FoodSelectRow>> m_foodRows;\r\n\r\n\tAgricultureProxy* m_proxy = nullptr;\r\n\tbool m_blockSignals = false;\r\n\r\n\tvoid setBasicOptions();\r\n\r\n\tunsigned int m_id           = 0;\r\n\tNoesis::String m_name       = \"-Farm-\";\r\n\tNoesis::String m_title      = \"Farm\";\r\n\tbool m_suspended            = false;\r\n\tbool m_harvest              = false;\r\n\tbool m_harvestHay           = false;\r\n\tbool m_tameWild             = false;\r\n\tNoesis::String m_tilled     = \"0/0\";\r\n\tNoesis::String m_planted    = \"0/0\";\r\n\tNoesis::String m_ready      = \"0/0\";\r\n\tNoesis::String m_numPlots   = \"0\";\r\n\tNoesis::String m_numSeeds   = \"0\";\r\n\tNoesis::String m_numItems   = \"0\";\r\n\tNoesis::String m_numPlants  = \"0\";\r\n\tNoesis::String m_numAnimals = \"0/0\";\r\n\tNoesis::String m_numMale    = \"0/\";\r\n\tNoesis::String m_numFemale  = \"0/\";\r\n\tint\tm_maxAnimals = 0;\r\n\tNoesis::String m_maxMale    = \"0\";\r\n\tNoesis::String m_maxFemale    = \"0\";\r\n\tbool m_plantTrees           = true;\r\n\tbool m_fellTrees            = false;\r\n\tbool m_pickFruits           = true;\r\n\tNoesis::String m_foodStatus = \"0/0\";\r\n\tNoesis::String m_hayStatus  = \"0/\";\r\n\tNoesis::String m_maxHay     = \"100\";\r\n\r\n\r\n\tbool m_productSelect = false;\r\n\tbool m_manageWindow = false;\r\n\tbool m_pastureFoodSelect = false;\r\n\r\n\tQString m_gui;\r\n\r\n\tAgriType m_type = AgriType::Farm;\r\n\r\n\tQString m_productID;\r\n\r\n\tconst Noesis::ImageSource* getBitmapSource() const\r\n\t{\r\n\t\treturn m_bitmapSource;\r\n\t}\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapSource;\r\n\r\n\tNS_DECLARE_REFLECTION( AgricultureModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/agricultureproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"agricultureproxy.h\"\r\n\r\n#include \"../../base/gamestate.h\"\r\n#include \"../../gfx/sprite.h\"\r\n#include \"../../gfx/spritefactory.h\"\r\n#include \"../../base/global.h\"\r\n#include \"../../gui/eventconnector.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nAgricultureProxy::AgricultureProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalUpdateFarm, this, &AgricultureProxy::onUpdateFarm, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalUpdatePasture, this, &AgricultureProxy::onUpdatePasture, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalUpdateGrove, this, &AgricultureProxy::onUpdateGrove, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalGlobalPlantInfo, this, &AgricultureProxy::onUpdateGlobalPlants, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalGlobalAnimalInfo, this, &AgricultureProxy::onUpdateGlobalAnimals, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorAgri(), &AggregatorAgri::signalGlobalTreeInfo, this, &AgricultureProxy::onUpdateGlobalTrees, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &AgricultureProxy::signalSetBasicOptions, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetBasicOptions, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalSelectProduct, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSelectProduct, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalSetHarvestOptions, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetHarvestOptions, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalSetGroveOptions, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetGroveOptions, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalRequestGlobalPlantInfo, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onRequestGlobalPlantInfo, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalRequestGlobalAnimalInfo, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onRequestGlobalAnimalInfo, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalRequestGlobalTreeInfo, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onRequestGlobalTreeInfo, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &AgricultureProxy::signalSetMaxMale, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetMaxMale, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalSetMaxFemale, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetMaxFemale, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalSetButchering, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetButchering, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalRequestPastureAnimalInfo, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onRequestPastureAnimalInfo, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalRequestPastureFoodInfo, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onRequestPastureFoodInfo, Qt::QueuedConnection );\r\n\tconnect( this, &AgricultureProxy::signalSetFoodItemChecked, Global::eventConnector->aggregatorAgri(), &AggregatorAgri::onSetFoodItemChecked, Qt::QueuedConnection );\r\n}\r\n\r\nAgricultureProxy::~AgricultureProxy()\r\n{\r\n}\r\n\r\nvoid AgricultureProxy::setParent( IngnomiaGUI::AgricultureModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid AgricultureProxy::onUpdateFarm( const GuiFarmInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_AgricultureID = info.ID;\r\n\t\tm_type          = AgriType::Farm;\r\n\t\tm_parent->updateFarmInfo( info );\r\n\t}\r\n}\r\n\r\nvoid AgricultureProxy::onUpdatePasture( const GuiPastureInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_AgricultureID = info.ID;\r\n\t\tm_type          = AgriType::Pasture;\r\n\t\tm_parent->updatePastureInfo( info );\r\n\t}\r\n}\r\n\r\nvoid AgricultureProxy::onUpdateGrove( const GuiGroveInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_AgricultureID = info.ID;\r\n\t\tm_type          = AgriType::Grove;\r\n\t\tm_parent->updateGroveInfo( info );\r\n\t}\r\n}\r\n\r\nvoid AgricultureProxy::setBasicOptions( unsigned int agricultureID, QString name, int priority, bool suspended )\r\n{\r\n\temit signalSetBasicOptions( m_type, agricultureID, name, priority, suspended );\r\n}\r\n\r\nvoid AgricultureProxy::selectProduct( unsigned int agricultureID, QString product )\r\n{\r\n\temit signalSelectProduct( m_type, agricultureID, product );\r\n}\r\n\r\nvoid AgricultureProxy::setHarvestOptions( unsigned int agricultureID, bool harvest, bool harvestHay, bool tame )\r\n{\r\n\temit signalSetHarvestOptions( m_type, agricultureID, harvest, harvestHay, tame );\r\n}\r\n\r\nvoid AgricultureProxy::setGroveOptions( unsigned int designationID, bool pick, bool plant, bool fell )\r\n{\r\n\temit signalSetGroveOptions( designationID, pick, plant, fell );\r\n}\r\n\r\nvoid AgricultureProxy::onUpdateGlobalPlants( const QList<GuiPlant>& plants )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateGlobalPlantInfo( plants );\r\n\t}\r\n}\r\n\r\nvoid AgricultureProxy::onUpdateGlobalAnimals( const QList<GuiAnimal>& animals )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateGlobalAnimalInfo( animals );\r\n\t}\r\n}\r\n\r\nvoid AgricultureProxy::onUpdateGlobalTrees( const QList<GuiPlant>& trees )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateGlobalTreeInfo( trees );\r\n\t}\r\n}\r\n\r\nvoid AgricultureProxy::requestGlobalPlantInfo()\r\n{\r\n\temit signalRequestGlobalPlantInfo();\r\n}\r\n\r\nvoid AgricultureProxy::requestGlobalAnimalInfo()\r\n{\r\n\temit signalRequestGlobalAnimalInfo();\r\n}\r\n\r\nvoid AgricultureProxy::requestGlobalTreeInfo()\r\n{\r\n\temit signalRequestGlobalTreeInfo();\r\n}\r\n\r\nvoid AgricultureProxy::setMaxMale( unsigned int designationID, int max )\r\n{\r\n\temit signalSetMaxMale( designationID, max );\r\n}\r\n\t\r\nvoid AgricultureProxy::setMaxFemale( unsigned int designationID, int max )\r\n{\r\n\temit signalSetMaxFemale( designationID, max );\r\n}\r\n\r\nvoid AgricultureProxy::setButchering( unsigned int animalId, bool value )\r\n{\r\n\temit signalSetButchering( animalId, value );\r\n}\r\n\r\nvoid AgricultureProxy::requestPastureAnimalInfo()\r\n{\r\n\temit signalRequestPastureAnimalInfo( m_AgricultureID );\r\n}\r\n\r\nvoid AgricultureProxy::requestPastureFoodInfo()\r\n{\r\n\temit signalRequestPastureFoodInfo( m_AgricultureID );\r\n}\r\n\r\nvoid AgricultureProxy::setFoodItemChecked( QString itemSID, QString materialSID, bool checked )\r\n{\r\n\temit signalSetFoodItemChecked( m_AgricultureID, itemSID, materialSID, checked );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/agricultureproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatoragri.h\"\r\n#include \"agriculturemodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass AgricultureProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tAgricultureProxy( QObject* parent = nullptr );\r\n\t~AgricultureProxy();\r\n\r\n\tvoid setParent( IngnomiaGUI::AgricultureModel* parent );\r\n\r\n\tvoid setBasicOptions( unsigned int designationID, QString name, int priority, bool suspended );\r\n\tvoid setHarvestOptions( unsigned int designationID, bool farmHarvest, bool harvestHay, bool tame );\r\n\tvoid setGroveOptions( unsigned int designationID, bool pick, bool plant, bool fell );\r\n\r\n\tvoid selectProduct( unsigned int designationID, QString product );\r\n\r\n\tvoid setMaxMale( unsigned int designationID, int max );\r\n\tvoid setMaxFemale( unsigned int designationID, int max );\r\n\r\n\tvoid requestGlobalPlantInfo();\r\n\tvoid requestGlobalAnimalInfo();\r\n\tvoid requestGlobalTreeInfo();\r\n\r\n\tvoid requestPastureAnimalInfo();\r\n\tvoid requestPastureFoodInfo();\r\n\r\n\tvoid setButchering( unsigned int animalId, bool value );\r\n\r\n\tvoid setFoodItemChecked( QString itemSID, QString materialSID, bool checked );\r\n\r\nprivate:\r\n\tIngnomiaGUI::AgricultureModel* m_parent = nullptr;\r\n\r\n\tunsigned int m_AgricultureID = 0;\r\n\tAgriType m_type              = AgriType::Farm;\r\n\r\nprivate slots:\r\n\tvoid onUpdateFarm( const GuiFarmInfo& info );\r\n\tvoid onUpdatePasture( const GuiPastureInfo& info );\r\n\tvoid onUpdateGrove( const GuiGroveInfo& info );\r\n\r\n\tvoid onUpdateGlobalPlants( const QList<GuiPlant>& plants );\r\n\tvoid onUpdateGlobalAnimals( const QList<GuiAnimal>& animals );\r\n\tvoid onUpdateGlobalTrees( const QList<GuiPlant>& trees );\r\n\r\nsignals:\r\n\tvoid signalSetBasicOptions( AgriType type, unsigned int designationID, QString name, int priority, bool suspended );\r\n\tvoid signalSelectProduct( AgriType type, unsigned int designationID, QString product );\r\n\tvoid signalSetHarvestOptions( AgriType type, unsigned int designationID, bool harvest, bool harvestHay, bool tame );\r\n\tvoid signalSetGroveOptions( unsigned int designationID, bool pick, bool plant, bool fell );\r\n\tvoid signalRequestGlobalPlantInfo();\r\n\tvoid signalRequestGlobalAnimalInfo();\r\n\tvoid signalRequestGlobalTreeInfo();\r\n\tvoid signalSetMaxMale( unsigned int designationID, int max );\r\n\tvoid signalSetMaxFemale( unsigned int designationID, int max );\r\n\tvoid signalSetButchering( unsigned int animalId, bool value );\r\n\tvoid signalRequestPastureAnimalInfo( unsigned int pastureID );\r\n\tvoid signalRequestPastureFoodInfo( unsigned int pastureID );\r\n\tvoid signalSetFoodItemChecked( unsigned int pastureID, QString itemSID, QString materialSID, bool checked );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/converters.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"converters.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\nbool ColorToBrushConverter::TryConvert( BaseComponent* value, const Type* targetType, BaseComponent*, Noesis::Ptr<BaseComponent>& result )\r\n{\r\n    if ( targetType == Noesis::TypeOf<Brush>() )\r\n    {\r\n        QString param = value->ToString().Str();\r\n        auto cl = param.split( \" \" );\r\n        if( cl.size() > 2 )\r\n\t\t{\r\n\t\t    auto col = Color( cl[0].toInt(), cl[1].toInt(), cl[2].toInt() );\r\n            result = MakePtr<SolidColorBrush>(col);\r\n        }\r\n\t\telse\r\n\t\t{\r\n            auto col = Color( 255, 0, 255 );\r\n            result = MakePtr<SolidColorBrush>(col);\r\n\t\t}\r\n        return true;\r\n    }\r\n\r\n    return false;\r\n}\r\n\r\nbool ColorToBrushConverterDark::TryConvert( BaseComponent* value, const Type* targetType, BaseComponent*, Noesis::Ptr<BaseComponent>& result )\r\n{\r\n    if ( targetType == Noesis::TypeOf<Brush>() )\r\n    {\r\n        QString param = value->ToString().Str();\r\n        auto cl = param.split( \" \" );\r\n        if( cl.size() > 2 )\r\n\t\t{\r\n\t\t    auto col = Color( cl[0].toInt() / 2, cl[1].toInt() / 2, cl[2].toInt() / 2 );\r\n            result = MakePtr<SolidColorBrush>(col);\r\n        }\r\n\t\telse\r\n\t\t{\r\n            auto col = Color( 155, 0, 155 );\r\n            result = MakePtr<SolidColorBrush>(col);\r\n\t\t}\r\n        return true;\r\n    }\r\n\r\n    return false;\r\n}\r\n\r\n\r\n\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( ColorToBrushConverter, \"IngnomiaGUI.ColorToBrushConverter\")\r\n{\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( ColorToBrushConverterDark, \"IngnomiaGUI.ColorToBrushConverterDark\")\r\n{\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/converters.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\nclass ColorToBrushConverter : public Noesis::BaseValueConverter\r\n{\r\npublic:\r\n    bool TryConvert( BaseComponent* value, const Noesis::Type* targetType, BaseComponent*, Noesis::Ptr<BaseComponent>& result );\r\n    \r\nprivate:\r\n    NS_DECLARE_REFLECTION( ColorToBrushConverter, Noesis::BaseValueConverter )\r\n};\r\n\r\nclass ColorToBrushConverterDark : public Noesis::BaseValueConverter\r\n{\r\npublic:\r\n    bool TryConvert( BaseComponent* value, const Noesis::Type* targetType, BaseComponent*, Noesis::Ptr<BaseComponent>& result );\r\n    \r\nprivate:\r\n    NS_DECLARE_REFLECTION( ColorToBrushConverterDark, Noesis::BaseValueConverter )\r\n};\r\n\r\n\r\n}"
  },
  {
    "path": "src/gui/xaml/creatureinfo.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creatureinfo.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nCreatureInfo::CreatureInfo()\r\n{\r\n\tLoaded() += MakeDelegate( this, &CreatureInfo::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid CreatureInfo::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"CreatureInfo.xaml\" );\r\n}\r\n\r\nbool CreatureInfo::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid CreatureInfo::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::CreatureInfo, \"IngnomiaGUI.CreatureInfo\" )\r\n"
  },
  {
    "path": "src/gui/xaml/creatureinfo.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __CreatureInfo_H__\r\n#define __CreatureInfo_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass CreatureInfo final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tCreatureInfo();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( CreatureInfo, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/creatureinfomodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creatureinfomodel.h\"\r\n\r\n#include \"creatureinfoproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n#include <NsGui/BitmapImage.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nCreatureInfoModel::CreatureInfoModel()\r\n{\r\n\tm_proxy = new CreatureInfoProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_professions = *new ObservableCollection<ProfItem>();\r\n\tm_proxy->requestProfessionList();\r\n}\r\n\r\nvoid CreatureInfoModel::updateEmptySlotImages( const QMap< QString, std::vector<unsigned char> >& pics )\r\n{\r\n\tm_bitmapHeadEmpty =  BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotHead\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapChestEmpty = BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotChest\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapArmsEmpty =  BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotArms\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapHandsEmpty = BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotHands\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapLegsEmpty =  BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotLegs\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapFeetEmpty =  BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotFeet\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapLHeldEmpty = BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotShield\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapRHeldEmpty = BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotWeapon\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapBackEmpty =  BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotBack\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapNeckEmpty =  BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotNeck\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapLRingEmpty = BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotRing\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_bitmapRRingEmpty = BitmapImage::Create( 32, 32, 96, 96, pics.value( \"UIEmptySlotRing\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\tm_emptyPicsInitialized = true;\r\n}\r\n\r\nvoid CreatureInfoModel::updateProfessionList( const QStringList& professions )\r\n{\r\n\tm_professions->Clear();\r\n\tfor( const auto& prof : professions )\r\n\t{\r\n\t\tm_professions->Add( MakePtr<ProfItem>( prof.toStdString().c_str() ) );\r\n\t}\r\n\tOnPropertyChanged( \"Professions\" );\r\n}\r\n\r\nvoid CreatureInfoModel::updateInfo( const GuiCreatureInfo& info )\r\n{\r\n\tif( !m_emptyPicsInitialized )\r\n\t{\r\n\t\tm_proxy->requestEmptySlotImages();\r\n\t}\r\n\r\n\tm_name = info.name.toStdString().c_str();\r\n\tm_id = info.id;\r\n\r\n\tm_str = std::to_string( info.str ).c_str();\r\n\tm_con = std::to_string( info.con ).c_str();\r\n\tm_dex = std::to_string( info.dex ).c_str();\r\n\tm_int = std::to_string( info.intel ).c_str();\r\n\tm_wis = std::to_string( info.wis ).c_str();\r\n\tm_cha = std::to_string( info.cha ).c_str();\r\n\r\n\tm_hunger = std::to_string( info.hunger ).c_str();\r\n\tm_thirst = std::to_string( info.thirst ).c_str();\r\n\tm_sleep = std::to_string( info.sleep ).c_str();\r\n\tm_happiness = std::to_string( info.happiness ).c_str();\r\n\r\n\tfor( int i = 0; i < m_professions->Count(); ++i )\r\n\t{\r\n\t\tif( m_professions->Get( i )->GetName() == info.profession )\r\n\t\t{\r\n\t\t\tSetProfession( m_professions->Get( i ) );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\t\r\n\tm_activity = info.activity.toStdString().c_str();\r\n\r\n\tOnPropertyChanged( \"Name\" );\r\n\tOnPropertyChanged( \"Str\" );\r\n\tOnPropertyChanged( \"Con\" );\r\n\tOnPropertyChanged( \"Dex\" );\r\n\tOnPropertyChanged( \"Int\" );\r\n\tOnPropertyChanged( \"Wis\" );\r\n\tOnPropertyChanged( \"Cha\" );\r\n\tOnPropertyChanged( \"Hunger\" );\r\n\tOnPropertyChanged( \"Thirst\" );\r\n\tOnPropertyChanged( \"Sleep\" );\r\n\tOnPropertyChanged( \"Happiness\" );\r\n\tOnPropertyChanged( \"Activity\" );\r\n\r\n\tm_bitmapHead  = m_bitmapHeadEmpty;\r\n\tm_bitmapChest = m_bitmapChestEmpty;\r\n\tm_bitmapArms  = m_bitmapArmsEmpty;\r\n\tm_bitmapHands = m_bitmapHandsEmpty;\r\n\tm_bitmapLegs  = m_bitmapLegsEmpty;\r\n\tm_bitmapFeet  = m_bitmapFeetEmpty;\r\n\tm_bitmapLHeld = m_bitmapLHeldEmpty;\r\n\tm_bitmapRHeld = m_bitmapRHeldEmpty;\r\n\tm_bitmapBack  = m_bitmapBackEmpty;\r\n\tm_bitmapNeck  = m_bitmapNeckEmpty;\r\n\tm_bitmapLRing =\tm_bitmapLRingEmpty;\r\n\tm_bitmapRRing =\tm_bitmapRRingEmpty;\r\n\r\n\tif( info.equipment.head.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"ArmorHead\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"ArmorHead\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapHead = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"ArmorHead\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.chest.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"ArmorChest\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"ArmorChest\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapChest = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"ArmorChest\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.arm.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"ArmorArms\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"ArmorArms\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapArms = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"ArmorArms\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.hand.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"ArmorHands\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"ArmorHands\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapHands = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"ArmorHands\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.leg.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"ArmorLegs\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"ArmorLegs\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapLegs = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"ArmorLegs\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.foot.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"ArmorFeet\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"ArmorFeet\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapFeet = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"ArmorFeet\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.leftHandHeld.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"LeftHandHeld\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"LeftHandHeld\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapLHeld = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"LeftHandHeld\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif( info.equipment.rightHandHeld.itemID )\r\n\t{\r\n\t\tif( info.itemPics.contains( \"RightHandHeld\" ) )\r\n\t\t{\r\n\t\t\tif( info.itemPics.value( \"RightHandHeld\" ).size() == 8192 )\r\n\t\t\t{\r\n\t\t\t\tm_bitmapRHeld = BitmapImage::Create( 32, 32, 96, 96, info.itemPics.value( \"RightHandHeld\" ).data(), 128, BitmapSource::Format::Format_RGBA8 );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t//m_bitmapBack = createUniformImg( \"Back\", info.uniform );\r\n\t//m_bitmapNeck = createUniformImg( \"\", info.uniform );\r\n\t//m_bitmapLRing = createUniformImg( \"\", info.uniform );\r\n\t//m_bitmapRRing = createUniformImg( \"\", info.uniform );\r\n\t\r\n\tOnPropertyChanged( \"ImgHead\" );\r\n\tOnPropertyChanged( \"ImgChest\" );\r\n\tOnPropertyChanged( \"ImgArms\" );\r\n\tOnPropertyChanged( \"ImgHands\" );\r\n\tOnPropertyChanged( \"ImgLegs\" );\r\n\tOnPropertyChanged( \"ImgFeet\" );\r\n\tOnPropertyChanged( \"ImgLeftHand\" );\r\n\tOnPropertyChanged( \"ImgRightHand\" );\r\n\tOnPropertyChanged( \"ImgBack\" );\r\n\tOnPropertyChanged( \"ImgNeck\" );\r\n\tOnPropertyChanged( \"ImgLRing\" );\r\n\tOnPropertyChanged( \"ImgRRing\" );\r\n}\r\n\r\nconst char* CreatureInfoModel::GetName() const { return m_name.Str(); }\r\nconst char* CreatureInfoModel::GetStr() const { return m_str.Str(); }\r\nconst char* CreatureInfoModel::GetCon() const { return m_con.Str(); }\r\nconst char* CreatureInfoModel::GetDex() const { return m_dex.Str(); }\r\nconst char* CreatureInfoModel::GetInt() const { return m_int.Str(); }\r\nconst char* CreatureInfoModel::GetWis() const { return m_wis.Str(); }\r\nconst char* CreatureInfoModel::GetCha() const { return m_cha.Str(); }\r\nconst char* CreatureInfoModel::GetHunger() const { return m_hunger.Str(); }\r\nconst char* CreatureInfoModel::GetThirst() const { return m_thirst.Str(); }\r\nconst char* CreatureInfoModel::GetSleep() const { return m_sleep.Str(); }\r\nconst char* CreatureInfoModel::GetHappiness() const { return m_happiness.Str(); }\r\nconst char* CreatureInfoModel::GetActivity() const { return m_activity.Str(); }\r\n\r\n\r\nNoesis::ObservableCollection<ProfItem>* CreatureInfoModel::GetProfessions() const\r\n{\r\n\treturn m_professions;\r\n}\r\n\t\r\nvoid CreatureInfoModel::SetProfession( ProfItem* item )\r\n{\r\n\tif ( item && m_selectedProfession != item )\r\n\t{\r\n\t\tm_selectedProfession = item;\r\n\t\tm_proxy->setProfession( m_id, item->GetName() );\r\n\r\n\t\tOnPropertyChanged( \"Profession\" );\r\n\t}\r\n}\r\n\r\nProfItem* CreatureInfoModel::GetProfession() const\r\n{\r\n\treturn m_selectedProfession;\r\n}\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\n\r\nNS_IMPLEMENT_REFLECTION( CreatureInfoModel, \"IngnomiaGUI.CreatureInfoModel\" )\r\n{\r\n\tNsProp( \"Name\", &CreatureInfoModel::GetName );\r\n\tNsProp( \"Professions\", &CreatureInfoModel::GetProfessions );\r\n\tNsProp( \"Profession\", &CreatureInfoModel::GetProfession, &CreatureInfoModel::SetProfession );\r\n\r\n\tNsProp( \"Str\", &CreatureInfoModel::GetStr );\r\n\tNsProp( \"Con\", &CreatureInfoModel::GetCon );\r\n\tNsProp( \"Dex\", &CreatureInfoModel::GetDex );\r\n\tNsProp( \"Int\", &CreatureInfoModel::GetInt );\r\n\tNsProp( \"Wis\", &CreatureInfoModel::GetWis );\r\n\tNsProp( \"Cha\", &CreatureInfoModel::GetCha );\r\n\tNsProp( \"Hunger\", &CreatureInfoModel::GetHunger );\r\n\tNsProp( \"Thirst\", &CreatureInfoModel::GetThirst );\r\n\tNsProp( \"Sleep\", &CreatureInfoModel::GetSleep );\r\n\tNsProp( \"Happiness\", &CreatureInfoModel::GetHappiness );\r\n\r\n\tNsProp( \"Activity\", &CreatureInfoModel::GetActivity );\r\n\r\n\tNsProp( \"ImgHead\",      &CreatureInfoModel::getBitmapSourceHead );\r\n\tNsProp( \"ImgChest\",     &CreatureInfoModel::getBitmapSourceChest );\r\n\tNsProp( \"ImgArms\" ,     &CreatureInfoModel::getBitmapSourceArms );\r\n\tNsProp( \"ImgHands\",     &CreatureInfoModel::getBitmapSourceHands );\r\n\tNsProp( \"ImgLegs\" ,     &CreatureInfoModel::getBitmapSourceLegs );\r\n\tNsProp( \"ImgFeet\" ,     &CreatureInfoModel::getBitmapSourceFeet );\r\n\tNsProp( \"ImgLeftHand\",  &CreatureInfoModel::getBitmapSourceLHeld );\r\n\tNsProp( \"ImgRightHand\", &CreatureInfoModel::getBitmapSourceRHeld );\r\n\tNsProp( \"ImgBack\" ,     &CreatureInfoModel::getBitmapSourceBack );\r\n\tNsProp( \"ImgNeck\" ,     &CreatureInfoModel::getBitmapSourceNeck );\r\n\tNsProp( \"ImgLRing\",     &CreatureInfoModel::getBitmapSourceLRing );\r\n\tNsProp( \"ImgRRing\" ,    &CreatureInfoModel::getBitmapSourceRRing );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/creatureinfomodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __CreatureInfoModel_H__\r\n#define __CreatureInfoModel_H__\r\n\r\n#include \"PopulationModel.h\"\r\n\r\n#include \"../aggregatorcreatureinfo.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n#include <NsGui/ImageSource.h>\r\n#include <NsGui/BitmapSource.h>\r\n\r\n#include <QString>\r\n\r\nclass CreatureInfoProxy;\r\nstruct UniformItem;\r\nstruct EquipmentItem;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass CreatureInfoModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tCreatureInfoModel();\r\n\r\n\tvoid updateInfo( const GuiCreatureInfo& info );\r\n\tvoid updateProfessionList( const QStringList& professions );\r\n\r\n\tvoid updateEmptySlotImages( const QMap< QString, std::vector<unsigned char> >& pics );\r\n\r\nprivate:\r\n\tCreatureInfoProxy* m_proxy = nullptr;\r\n\tunsigned int m_id = 0;\r\n\r\n\tNoesis::String m_str;\r\n\tNoesis::String m_con;\r\n\tNoesis::String m_dex;\r\n\tNoesis::String m_int;\r\n\tNoesis::String m_wis;\r\n\tNoesis::String m_cha;\r\n\tNoesis::String m_hunger;\r\n\tNoesis::String m_thirst;\r\n\tNoesis::String m_sleep;\r\n\tNoesis::String m_happiness;\r\n\tNoesis::String m_activity;\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetStr() const;\r\n\tconst char* GetCon() const;\r\n\tconst char* GetDex() const;\r\n\tconst char* GetInt() const;\r\n\tconst char* GetWis() const;\r\n\tconst char* GetCha() const;\r\n\tconst char* GetHunger() const;\r\n\tconst char* GetThirst() const;\r\n\tconst char* GetSleep() const;\r\n\tconst char* GetHappiness() const;\r\n\r\n\tconst char* GetActivity() const;\r\n\r\n\tNoesis::String m_name;\r\n\r\n\tNoesis::ObservableCollection<ProfItem>* GetProfessions() const;\r\n\tvoid SetProfession( ProfItem* item );\r\n\tProfItem* GetProfession() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<ProfItem>> m_professions;\r\n\tProfItem* m_selectedProfession = nullptr;\r\n\r\n\tconst Noesis::ImageSource* getBitmapSourceHead()  const { return m_bitmapHead; };\r\n\tconst Noesis::ImageSource* getBitmapSourceChest() const { return m_bitmapChest; };\r\n\tconst Noesis::ImageSource* getBitmapSourceArms()  const { return m_bitmapArms; };\r\n\tconst Noesis::ImageSource* getBitmapSourceHands() const { return m_bitmapHands; };\r\n\tconst Noesis::ImageSource* getBitmapSourceLegs()  const { return m_bitmapLegs; };\r\n\tconst Noesis::ImageSource* getBitmapSourceFeet()  const { return m_bitmapFeet; };\r\n\tconst Noesis::ImageSource* getBitmapSourceLHeld() const { return m_bitmapLHeld; };\r\n\tconst Noesis::ImageSource* getBitmapSourceRHeld() const { return m_bitmapRHeld; };\r\n\tconst Noesis::ImageSource* getBitmapSourceBack()  const { return m_bitmapBack; };\r\n\tconst Noesis::ImageSource* getBitmapSourceNeck()  const { return m_bitmapNeck; };\r\n\tconst Noesis::ImageSource* getBitmapSourceLRing() const { return m_bitmapLRing; };\r\n\tconst Noesis::ImageSource* getBitmapSourceRRing() const { return m_bitmapRRing; };\r\n\t\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapHead = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapChest = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapArms = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapHands = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapLegs = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapFeet = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapLHeld = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapRHeld = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapBack = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapNeck = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapLRing = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapRRing = nullptr;\r\n\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapHeadEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapChestEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapArmsEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapHandsEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapLegsEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapFeetEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapLHeldEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapRHeldEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapBackEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapNeckEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapLRingEmpty = nullptr;\r\n\tNoesis::Ptr<Noesis::BitmapSource> m_bitmapRRingEmpty = nullptr;\r\n\tbool m_emptyPicsInitialized = false;\r\n\r\n\tNS_DECLARE_REFLECTION( CreatureInfoModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/creatureinfoproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"creatureinfoproxy.h\"\r\n\r\n#include \"../../base/db.h\"\r\n#include \"../../base/gamestate.h\"\r\n#include \"../../gfx/sprite.h\"\r\n#include \"../../gfx/spritefactory.h\"\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include \"PopulationModel.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nCreatureInfoProxy::CreatureInfoProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::signalCreatureUpdate, this, &CreatureInfoProxy::onUpdateInfo, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::signalProfessionList, this, &CreatureInfoProxy::onProfessionList, Qt::QueuedConnection );\r\n\t\r\n\tconnect( this, &CreatureInfoProxy::signalRequestProfessionList, Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::onRequestProfessionList, Qt::QueuedConnection );\r\n\tconnect( this, &CreatureInfoProxy::signalSetProfession, Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::onSetProfession, Qt::QueuedConnection );\r\n\t\r\n\tconnect( this, &CreatureInfoProxy::signalRequestEmptySlotImages, Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::onRequestEmptySlotImages, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorCreatureInfo(), &AggregatorCreatureInfo::signalEmptyPics, this, &CreatureInfoProxy::onEmptyPics, Qt::QueuedConnection );\r\n}\r\n\r\nCreatureInfoProxy::~CreatureInfoProxy()\r\n{\r\n}\r\n\r\nvoid CreatureInfoProxy::setParent( IngnomiaGUI::CreatureInfoModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid CreatureInfoProxy::onUpdateInfo( const GuiCreatureInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateInfo( info );\r\n\t}\r\n}\r\n\r\nvoid CreatureInfoProxy::requestProfessionList()\r\n{\r\n\temit signalRequestProfessionList();\r\n}\r\n\r\nvoid CreatureInfoProxy::onProfessionList( const QStringList& profs )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateProfessionList( profs );\r\n\t}\r\n}\r\n\r\nvoid CreatureInfoProxy::setProfession( unsigned int gnomeID, QString profession )\r\n{\r\n\temit signalSetProfession( gnomeID, profession );\r\n}\r\n\r\nvoid CreatureInfoProxy::requestEmptySlotImages()\r\n{\r\n\temit signalRequestEmptySlotImages();\r\n}\r\n\r\nvoid CreatureInfoProxy::onEmptyPics( const QMap< QString, std::vector<unsigned char> >& emptyPics )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateEmptySlotImages( emptyPics );\r\n\t}\r\n}"
  },
  {
    "path": "src/gui/xaml/creatureinfoproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorcreatureinfo.h\"\r\n#include \"creatureinfomodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass CreatureInfoProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tCreatureInfoProxy( QObject* parent = nullptr );\r\n\t~CreatureInfoProxy();\r\n\r\n\tvoid setParent( IngnomiaGUI::CreatureInfoModel* parent );\r\n\tvoid requestProfessionList();\r\n\tvoid setProfession( unsigned int gnomeID, QString profession );\r\n\r\n\tvoid requestEmptySlotImages();\r\n\r\n\r\nprivate:\r\n\tIngnomiaGUI::CreatureInfoModel* m_parent = nullptr;\r\n\r\nprivate slots:\r\n\tvoid onUpdateInfo( const GuiCreatureInfo& info );\r\n\tvoid onProfessionList( const QStringList& profs );\r\n\tvoid onEmptyPics( const QMap< QString, std::vector<unsigned char> >& emptyPics );\r\nsignals:\r\n\tvoid signalRequestCreatureUpdate( unsigned int creatureID );\r\n\tvoid signalRequestProfessionList();\r\n\tvoid signalSetProfession( unsigned int gnomeID, QString profession );\r\n\tvoid signalRequestEmptySlotImages();\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/debug.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"debug.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nDebugGui::DebugGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &DebugGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid DebugGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"DebugGui.xaml\" );\r\n}\r\n\r\nbool DebugGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid DebugGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::DebugGui, \"IngnomiaGUI.DebugGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/debug.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __DebugGui_H__\r\n#define __DebugGui_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass DebugGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tDebugGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( DebugGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/debugmodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"debugmodel.h\"\r\n#include \"debugproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWSEntry::WSEntry( int width, int height ) :\r\n\tm_width( width ),\r\n\tm_height( height )\r\n{\r\n\tm_name = ( QString::number( width ) + \"x\" + QString::number( height ) ).toStdString().c_str();\r\n}\r\n\r\nconst char* WSEntry::getName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nDebugModel::DebugModel()\r\n{\r\n\tm_proxy = new DebugProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_pageCmd.SetExecuteFunc( MakeDelegate( this, &DebugModel::onPageCmd ) );\r\n\tm_spawnCmd.SetExecuteFunc( MakeDelegate( this, &DebugModel::onSpawnCmd ) );\r\n\r\n\tm_windowSizes = *new ObservableCollection<WSEntry>();\r\n\tm_windowSizes->Add( MakePtr<WSEntry>( 1920, 1080 ) );\r\n\tm_windowSizes->Add( MakePtr<WSEntry>( 1360, 768 ) );\r\n}\r\n\r\nconst char* DebugModel::GetShowFirst() const\r\n{\r\n\tif ( m_page == DebugPage::First )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nconst char* DebugModel::GetShowSecond() const\r\n{\r\n\tif ( m_page == DebugPage::Second )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* DebugModel::GetShowThird() const\r\n{\r\n\tif ( m_page == DebugPage::Third )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid DebugModel::onPageCmd( BaseComponent* param )\r\n{\r\n\tif( param->ToString() == \"First\" )\r\n\t{\r\n\t\tm_page = DebugPage::First;\r\n\t}\r\n\telse if( param->ToString() == \"Second\" )\r\n\t{\r\n\t\tm_page = DebugPage::Second;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_page = DebugPage::Third;\r\n\t}\r\n\t\r\n\tOnPropertyChanged( \"ShowFirst\" );\r\n\tOnPropertyChanged( \"ShowSecond\" );\r\n\tOnPropertyChanged( \"ShowThird\" );\r\n}\r\n\r\nvoid DebugModel::onSpawnCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->spawnCreature( param->ToString().Str() );\r\n}\r\n\r\nNoesis::ObservableCollection<WSEntry>* DebugModel::getWindowSizes() const\r\n{\r\n    return m_windowSizes;\r\n}\r\n\r\nvoid DebugModel::setWindowSize( WSEntry* item )\r\n{\r\n    if( item && m_selectedWindowSize != item )\r\n\t{\r\n        m_selectedWindowSize = item;\r\n        m_proxy->setWindowSize( item->m_width, item->m_height );\r\n\t}\r\n}\r\n\r\nWSEntry* DebugModel::getWindowSize() const\r\n{\r\n    return m_selectedWindowSize;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( DebugModel, \"IngnomiaGUI.DebugModel\" )\r\n{\r\n\tNsProp( \"PageCmd\", &DebugModel::GetPageCmd );\r\n\tNsProp( \"ShowFirst\", &DebugModel::GetShowFirst );\r\n\tNsProp( \"ShowSecond\", &DebugModel::GetShowSecond );\r\n\tNsProp( \"ShowThird\", &DebugModel::GetShowThird );\r\n\r\n\tNsProp( \"SpawnCmd\", &DebugModel::GetSpawnCmd );\r\n\r\n\tNsProp( \"WindowSizes\", &DebugModel::getWindowSizes );\r\n\tNsProp( \"SelectedWindowSize\", &DebugModel::getWindowSize, &DebugModel::setWindowSize );\r\n\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WSEntry )\r\n{\r\n\tNsProp( \"Name\", &WSEntry::getName );\r\n}"
  },
  {
    "path": "src/gui/xaml/debugmodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __DebugModel_H__\r\n#define __DebugModel_H__\r\n\r\n#include \"../aggregatordebug.h\"\r\n\r\n#include <QString>\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\nclass DebugProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\nenum class DebugPage\r\n{\r\n\tFirst,\r\n\tSecond,\r\n\tThird\r\n};\r\n\r\nstruct WSEntry : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tWSEntry( int width, int height );\r\n\r\n\tNoesis::String m_name;\r\n\tint m_width;\r\n\tint m_height;\r\n\r\n    const char* getName() const;\r\n\t\r\n\tNS_DECLARE_REFLECTION( WSEntry, BaseComponent )\r\n};\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass DebugModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tDebugModel();\r\n\r\n\r\nprivate:\r\n\tDebugProxy* m_proxy = nullptr;\r\n\r\n\tDebugPage m_page = DebugPage::First;\r\n\r\n\tconst char* GetShowFirst() const;\r\n\tconst char* GetShowSecond() const;\r\n\tconst char* GetShowThird() const;\r\n\r\n\tvoid onPageCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetPageCmd() const\r\n\t{\r\n\t\treturn &m_pageCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_pageCmd;\r\n\r\n\tvoid onSpawnCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSpawnCmd() const\r\n\t{\r\n\t\treturn &m_spawnCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_spawnCmd;\r\n\r\n\tNoesis::ObservableCollection<WSEntry>* getWindowSizes() const;\r\n\tvoid setWindowSize( WSEntry* item );\r\n\tWSEntry* getWindowSize() const;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WSEntry>> m_windowSizes;\r\n    WSEntry* m_selectedWindowSize = nullptr;;\r\n\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( DebugModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/debugproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"debugproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nDebugProxy::DebugProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( this, &DebugProxy::signalSpawnCreature, Global::eventConnector->aggregatorDebug(), &AggregatorDebug::onSpawnCreature, Qt::QueuedConnection );\r\n    connect( this, &DebugProxy::signalSetWindowSize, Global::eventConnector->aggregatorDebug(), &AggregatorDebug::onSetWindowSize, Qt::QueuedConnection );\r\n}\r\n\r\nvoid DebugProxy::setParent( IngnomiaGUI::DebugModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid DebugProxy::spawnCreature( QString type )\r\n{\r\n\temit signalSpawnCreature( type );\r\n}\r\n\r\nvoid DebugProxy::setWindowSize( int width, int height )\r\n{\r\n    emit signalSetWindowSize( width, height );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/debugproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatordebug.h\"\r\n#include \"debugmodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass DebugProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tDebugProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::DebugModel* parent );\r\n\r\n\tvoid spawnCreature( QString type );\r\n\r\n    void setWindowSize( int width, int height );\r\n\r\nprivate:\r\n\tIngnomiaGUI::DebugModel* m_parent = nullptr;\r\n\r\n\r\n\r\nprivate slots:\r\n\r\nsignals:\r\n\tvoid signalSpawnCreature( QString type );\r\n    void signalSetWindowSize( int width, int height );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/inventory.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"inventory.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nInventoryGui::InventoryGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &InventoryGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid InventoryGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"InventoryGui.xaml\" );\r\n}\r\n\r\nbool InventoryGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid InventoryGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::InventoryGui, \"IngnomiaGUI.InventoryGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/inventory.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass InventoryGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tInventoryGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( InventoryGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n"
  },
  {
    "path": "src/gui/xaml/inventorymodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"inventorymodel.h\"\r\n#include \"inventoryproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n\r\n#pragma region MaterialItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::InvMaterialItem::InvMaterialItem( const GuiInventoryMaterial& mat, InventoryProxy* proxy ) :\r\n\tm_proxy( proxy ),\r\n\tm_sid( mat.id ),\r\n\tm_category( mat.cat ),\r\n\tm_group( mat.group ),\r\n\tm_item( mat.item )\r\n{\r\n\tm_name   = mat.name.toStdString().c_str();\r\n\tm_active = mat.watched;\r\n\r\n\tm_inStock = QString::number( mat.countInStockpiles ).toStdString().c_str();\r\n\tm_total = QString::number( mat.countTotal ).toStdString().c_str();\r\n}\r\n\r\nconst char* IngnomiaGUI::InvMaterialItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nbool IngnomiaGUI::InvMaterialItem::GetChecked() const\r\n{\r\n\treturn m_active;\r\n}\r\n\r\nvoid IngnomiaGUI::InvMaterialItem::SetChecked( bool value )\r\n{\r\n\tif ( m_active != value )\r\n\t{\r\n\t\tm_active = value;\r\n\t\tGuiWatchedItem gwi{ m_category, m_group, m_item, m_sid };\r\n\t\tm_proxy->setActive( value, gwi );\r\n\t}\r\n}\r\n\r\nconst char* IngnomiaGUI::InvMaterialItem::getTotal() const\r\n{\r\n\treturn m_total.Str();\r\n}\r\n\t\r\nconst char* IngnomiaGUI::InvMaterialItem::getInStock() const\r\n{\r\n\treturn m_inStock.Str();\r\n}\r\n\r\n#pragma endregion MaterialItem\r\n\r\n#pragma region ItemItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::InvItemItem::InvItemItem( const GuiInventoryItem& gii, InventoryProxy* proxy ) :\r\n\tm_proxy( proxy ),\r\n\tm_sid( gii.id ),\r\n\tm_category( gii.cat ),\r\n\tm_group( gii.group )\r\n{\r\n\tm_name = gii.name.toStdString().c_str();\r\n\tm_inStock = QString::number( gii.countInStockpiles ).toStdString().c_str();\r\n\tm_total = QString::number( gii.countTotal ).toStdString().c_str();\r\n\r\n\tm_materials = *new ObservableCollection<InvMaterialItem>();\r\n\r\n\tfor( const auto& mat : gii.materials )\r\n\t{\r\n\t\tm_materials->Add( MakePtr<InvMaterialItem>( mat, proxy ) );\r\n\t}\r\n\r\n\tm_state = gii.watched;\r\n\tif( !m_state )\r\n\t{\r\n\t\tUpdateState();\r\n\t}\r\n}\r\n\r\nconst char* IngnomiaGUI::InvItemItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst Noesis::Nullable<bool>& IngnomiaGUI::InvItemItem::GetState() const\r\n{\r\n\treturn m_state;\r\n}\r\n\r\nbool IngnomiaGUI::InvItemItem::getExpanded() const\r\n{\r\n\treturn !GetState().HasValue();\r\n}\r\n\r\nvoid IngnomiaGUI::InvItemItem::SetState( const Noesis::Nullable<bool>& value )\r\n{\r\n\tbool active = value.HasValue() && value.GetValue();\r\n\tm_state = active;\r\n\tGuiWatchedItem gwi{ m_category, m_group, m_sid };\r\n\tm_proxy->setActive( active, gwi );\r\n}\r\n\r\nvoid IngnomiaGUI::InvItemItem::UpdateState()\r\n{\r\n\tbool allChecked   = false;\r\n\tbool allUnchecked = true;\r\n\tfor ( int i = 0; i < m_materials->Count(); ++i )\r\n\t{\r\n\t\tbool checked = m_materials->Get( i )->GetChecked();\r\n\t\tif ( !checked )\r\n\t\t{\r\n\t\t\tallChecked = false;\r\n\t\t}\r\n\t\telse if ( checked )\r\n\t\t{\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t}\r\n\tif ( allChecked && !allUnchecked )\r\n\t{\r\n\t\tm_state = true;\r\n\t}\r\n\telse if ( !allChecked && allUnchecked )\r\n\t{\r\n\t\tm_state = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = nullptr;\r\n\t}\r\n\r\n\tOnPropertyChanged( \"Checked\" );\r\n\tOnPropertyChanged( \"Expanded\" );\r\n}\r\n\r\nconst char* IngnomiaGUI::InvItemItem::getTotal() const\r\n{\r\n\treturn m_total.Str();\r\n}\r\n\t\r\nconst char* IngnomiaGUI::InvItemItem::getInStock() const\r\n{\r\n\treturn m_inStock.Str();\r\n}\r\n\r\n#pragma endregion ItemItem\r\n\r\n#pragma region GroupItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::InvGroupItem::InvGroupItem( const GuiInventoryGroup& gig, InventoryProxy* proxy ) :\r\n\tm_proxy( proxy ),\r\n\tm_sid( gig.id ),\r\n\tm_category( gig.cat )\r\n{\r\n\tm_name = gig.name.toStdString().c_str();\r\n\tm_inStock = QString::number( gig.countInStockpiles ).toStdString().c_str();\r\n\tm_total = QString::number( gig.countTotal ).toStdString().c_str();\r\n\r\n\tm_items = *new ObservableCollection<InvItemItem>();\r\n\r\n\tfor ( auto item : gig.items )\r\n\t{\r\n\t\tm_items->Add( MakePtr<InvItemItem>( item, proxy ) );\r\n\t}\r\n\r\n\tm_state = gig.watched;\r\n\tif( !m_state )\r\n\t{\r\n\t\tUpdateState();\r\n\t}\r\n}\r\n\r\nconst char* IngnomiaGUI::InvGroupItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst Noesis::Nullable<bool>& IngnomiaGUI::InvGroupItem::GetState() const\r\n{\r\n\treturn m_state;\r\n}\r\n\r\nbool IngnomiaGUI::InvGroupItem::getExpanded() const\r\n{\r\n\treturn !GetState().HasValue();\r\n}\r\n\r\nvoid IngnomiaGUI::InvGroupItem::SetState( const Noesis::Nullable<bool>& value )\r\n{\r\n\tbool active = value.HasValue() && value.GetValue();\r\n\tm_state = active;\r\n\tGuiWatchedItem gwi{ m_category, m_sid };\r\n\tm_proxy->setActive( active, gwi );\r\n}\r\n\r\nvoid IngnomiaGUI::InvGroupItem::UpdateState()\r\n{\r\n\tbool allChecked   = false;\r\n\tbool allUnchecked = true;\r\n\tfor ( int i = 0; i < m_items->Count(); ++i )\r\n\t{\r\n\t\tauto checked = m_items->Get( i )->GetState();\r\n\t\tif ( checked.HasValue() && checked )\r\n\t\t{\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t\telse if ( checked.HasValue() && !checked )\r\n\t\t{\r\n\t\t\tallChecked = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tallChecked   = false;\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t}\r\n\tif ( allChecked && !allUnchecked )\r\n\t{\r\n\t\tm_state = true;\r\n\t}\r\n\telse if ( !allChecked && allUnchecked )\r\n\t{\r\n\t\tm_state = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = nullptr;\r\n\t}\r\n\tOnPropertyChanged( \"Checked\" );\r\n\tOnPropertyChanged( \"Expanded\" );\r\n}\r\n\r\nconst char* IngnomiaGUI::InvGroupItem::getTotal() const\r\n{\r\n\treturn m_total.Str();\r\n}\r\n\t\r\nconst char* IngnomiaGUI::InvGroupItem::getInStock() const\r\n{\r\n\treturn m_inStock.Str();\r\n}\r\n\r\n\r\n#pragma endregion GroupItem\r\n\r\n#pragma region CategoryItem\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\n\r\nIngnomiaGUI::InvCategoryItem::InvCategoryItem( const GuiInventoryCategory& gic, InventoryProxy* proxy ) :\r\n\tm_proxy( proxy ),\r\n\tm_sid( gic.id )\r\n{\r\n\tm_name = gic.name.toStdString().c_str();\r\n\tm_inStock = QString::number( gic.countInStockpiles ).toStdString().c_str();\r\n\tm_total = QString::number( gic.countTotal ).toStdString().c_str();\r\n\r\n\tm_groups = *new ObservableCollection<InvGroupItem>();\r\n\t\r\n\tfor ( auto group : gic.groups )\r\n\t{\r\n\t\tm_groups->Add( MakePtr<InvGroupItem>( group, proxy ) );\r\n\t}\r\n\tm_state = gic.watched;\r\n\tif( !m_state )\r\n\t{\r\n\t\tUpdateState();\r\n\t}\r\n}\r\n\r\nconst char* IngnomiaGUI::InvCategoryItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst Noesis::Nullable<bool>& IngnomiaGUI::InvCategoryItem::GetState() const\r\n{\r\n\treturn m_state;\r\n}\r\n\r\nbool IngnomiaGUI::InvCategoryItem::getExpanded() const\r\n{\r\n\treturn !GetState().HasValue();\r\n}\r\n\r\nvoid IngnomiaGUI::InvCategoryItem::SetState( const Noesis::Nullable<bool>& value )\r\n{\r\n\t//qDebug() << value.HasValue() << value.GetValue() << m_state.HasValue() << m_state.GetValue();\r\n\tbool active = value.HasValue() && value.GetValue();\r\n\tif( value.HasValue() && !value.GetValue() && !m_state.HasValue() && !m_state.GetValue() )\r\n\t{\r\n\t\tactive = true;\r\n\t}\r\n\tm_state = active;\r\n\tGuiWatchedItem gwi{ m_sid };\r\n\tm_proxy->setActive( active, gwi );\r\n}\r\n\r\nvoid IngnomiaGUI::InvCategoryItem::UpdateState()\r\n{\r\n\tbool allChecked   = false;\r\n\tbool allUnchecked = true;\r\n\tfor ( int i = 0; i < m_groups->Count(); ++i )\r\n\t{\r\n\t\tauto checked = m_groups->Get( i )->GetState();\r\n\t\tif ( checked.HasValue() && checked )\r\n\t\t{\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t\telse if ( checked.HasValue() && !checked )\r\n\t\t{\r\n\t\t\tallChecked = false;\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tallChecked   = false;\r\n\t\t\tallUnchecked = false;\r\n\t\t}\r\n\t}\r\n\tif ( allChecked && !allUnchecked )\r\n\t{\r\n\t\tm_state = true;\r\n\t}\r\n\telse if ( !allChecked && allUnchecked )\r\n\t{\r\n\t\tm_state = false;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_state = nullptr;\r\n\t}\r\n\tOnPropertyChanged( \"Checked\" );\r\n\tOnPropertyChanged( \"Expanded\" );\r\n}\r\n\r\nconst char* IngnomiaGUI::InvCategoryItem::getTotal() const\r\n{\r\n\treturn m_total.Str();\r\n}\r\n\t\r\nconst char* IngnomiaGUI::InvCategoryItem::getInStock() const\r\n{\r\n\treturn m_inStock.Str();\r\n}\r\n\r\n\r\n#pragma endregion CategoryItem\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nInventoryModel::InventoryModel()\r\n{\r\n\tm_proxy = new InventoryProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_categories = *new ObservableCollection<InvCategoryItem>();\r\n\r\n\tm_proxy->requestCategories();\r\n}\r\n\r\nvoid InventoryModel::updateCategories( const QList<GuiInventoryCategory>& categories )\r\n{\r\n\tm_categories->Clear();\r\n\tfor ( const auto& cat : categories )\r\n\t{\r\n\t\tm_categories->Add( MakePtr<InvCategoryItem>( cat, m_proxy ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"Categories\" );\r\n}\r\n\r\nNoesis::ObservableCollection<InvCategoryItem>* InventoryModel::GetCategories() const\r\n{\r\n\treturn m_categories;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( InventoryModel, \"IngnomiaGUI.InventoryModel\" )\r\n{\r\n\tNsProp( \"Categories\", &InventoryModel::GetCategories );\r\n}\r\n\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::InvCategoryItem )\r\n{\r\n\tNsProp( \"Name\", &InvCategoryItem::GetName );\r\n\tNsProp( \"Checked\", &InvCategoryItem::GetState, &InvCategoryItem::SetState );\r\n\tNsProp( \"Expanded\", &InvCategoryItem::getExpanded );\r\n\tNsProp( \"Children\", &InvCategoryItem::GetGroups );\r\n\tNsProp( \"Total\", &InvCategoryItem::getTotal );\r\n\tNsProp( \"InStock\", &InvCategoryItem::getInStock );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::InvGroupItem )\r\n{\r\n\tNsProp( \"Name\", &InvGroupItem::GetName );\r\n\tNsProp( \"Checked\", &InvGroupItem::GetState, &InvGroupItem::SetState );\r\n\tNsProp( \"Expanded\", &InvGroupItem::getExpanded );\r\n\tNsProp( \"Children\", &InvGroupItem::GetItems );\r\n\tNsProp( \"Total\", &InvGroupItem::getTotal );\r\n\tNsProp( \"InStock\", &InvGroupItem::getInStock );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::InvItemItem )\r\n{\r\n\tNsProp( \"Name\", &InvItemItem::GetName );\r\n\tNsProp( \"Checked\", &InvItemItem::GetState, &InvItemItem::SetState );\r\n\tNsProp( \"Expanded\", &InvItemItem::getExpanded );\r\n\tNsProp( \"Children\", &InvItemItem::GetMaterials );\r\n\tNsProp( \"Total\", &InvItemItem::getTotal );\r\n\tNsProp( \"InStock\", &InvItemItem::getInStock );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( IngnomiaGUI::InvMaterialItem )\r\n{\r\n\tNsProp( \"Name\", &InvMaterialItem::GetName );\r\n\tNsProp( \"Checked\", &InvMaterialItem::GetChecked, &InvMaterialItem::SetChecked );\r\n\tNsProp( \"Total\", &InvMaterialItem::getTotal );\r\n\tNsProp( \"InStock\", &InvMaterialItem::getInStock );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/inventorymodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorinventory.h\"\r\n\r\n#include <QString>\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\nclass InventoryProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n#pragma region FilterItems\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass InvMaterialItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tInvMaterialItem( const GuiInventoryMaterial& mat, InventoryProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tbool GetChecked() const;\r\n\tvoid SetChecked( bool value );\r\n\r\n\tconst char* getTotal() const;\r\n\tconst char* getInStock() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_inStock;\r\n\tNoesis::String m_total;\r\n\tQString m_sid;\r\n\tQString m_item;\r\n\tQString m_group;\r\n\tQString m_category;\r\n\r\n\tbool m_active = false;\r\n\r\n\tInventoryProxy* m_proxy = nullptr;\r\n\r\n\tNS_DECLARE_REFLECTION( InvMaterialItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass InvItemItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tInvItemItem( const GuiInventoryItem& gii, InventoryProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\tconst Noesis::Nullable<bool>& GetState() const;\r\n\tvoid SetState( const Noesis::Nullable<bool>& value );\r\n\tbool getExpanded() const;\r\n\r\n\tconst char* getTotal() const;\r\n\tconst char* getInStock() const;\r\n\r\nprivate:\r\n\tvoid UpdateState();\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_inStock;\r\n\tNoesis::String m_total;\r\n\tQString m_sid;\r\n\tQString m_group;\r\n\tQString m_category;\r\n\r\n\tunsigned char m_active = 0;\r\n\tNoesis::Nullable<bool> m_state;\r\n\r\n\tInventoryProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<InvMaterialItem>* GetMaterials() const\r\n\t{\r\n\t\treturn m_materials;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<InvMaterialItem>> m_materials;\r\n\r\n\tNS_DECLARE_REFLECTION( InvItemItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass InvGroupItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tInvGroupItem( const GuiInventoryGroup& gig, InventoryProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tconst Noesis::Nullable<bool>& GetState() const;\r\n\tvoid SetState( const Noesis::Nullable<bool>& value );\r\n\tbool getExpanded() const;\r\n\r\n\tconst char* getTotal() const;\r\n\tconst char* getInStock() const;\r\n\r\nprivate:\r\n\tvoid UpdateState();\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_inStock;\r\n\tNoesis::String m_total;\r\n\tunsigned int m_stockpileID = 0;\r\n\tQString m_sid;\r\n\tQString m_category;\r\n\r\n\tunsigned char m_active = 0;\r\n\tNoesis::Nullable<bool> m_state;\r\n\r\n\tInventoryProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<InvItemItem>* GetItems() const\r\n\t{\r\n\t\treturn m_items;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<InvItemItem>> m_items;\r\n\r\n\tNS_DECLARE_REFLECTION( InvGroupItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass InvCategoryItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tInvCategoryItem( const GuiInventoryCategory& gic, InventoryProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tconst Noesis::Nullable<bool>& GetState() const;\r\n\tvoid SetState( const Noesis::Nullable<bool>& value );\r\n\tbool getExpanded() const;\r\n\r\n\tconst char* getTotal() const;\r\n\tconst char* getInStock() const;\r\n\r\nprivate:\r\n\tvoid UpdateState();\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_inStock;\r\n\tNoesis::String m_total;\r\n\tQString m_sid;\r\n\r\n\tunsigned char m_active = 0;\r\n\tNoesis::Nullable<bool> m_state;\r\n\r\n\tInventoryProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<InvGroupItem>* GetGroups() const\r\n\t{\r\n\t\treturn m_groups;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<InvGroupItem>> m_groups;\r\n\r\n\tNS_DECLARE_REFLECTION( InvCategoryItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n#pragma endregion FilterItems\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass InventoryModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tInventoryModel();\r\n\r\n\tvoid updateCategories( const QList<GuiInventoryCategory>& categories );\r\n\r\nprivate:\r\n\tInventoryProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::ObservableCollection<InvCategoryItem>* GetCategories() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<InvCategoryItem>> m_categories;\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( InventoryModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n"
  },
  {
    "path": "src/gui/xaml/inventoryproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"inventoryproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nInventoryProxy::InventoryProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\t\r\n    connect( Global::eventConnector->aggregatorInventory(), &AggregatorInventory::signalInventoryCategories, this, &InventoryProxy::onCategoryUpdate, Qt::QueuedConnection );\r\n\r\n    connect( this, &InventoryProxy::signalRequestCategories, Global::eventConnector->aggregatorInventory(), &AggregatorInventory::onRequestCategories, Qt::QueuedConnection );\r\n    connect( this, &InventoryProxy::signalSetActive, Global::eventConnector->aggregatorInventory(), &AggregatorInventory::onSetActive, Qt::QueuedConnection );\r\n}\r\n\r\nvoid InventoryProxy::setParent( IngnomiaGUI::InventoryModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\n    \r\nvoid InventoryProxy::requestCategories()\r\n{\r\n    emit signalRequestCategories();\r\n}\r\n\t\r\nvoid InventoryProxy::onCategoryUpdate( const QList<GuiInventoryCategory>& categories )\r\n{\r\n    if( m_parent )\r\n\t{\r\n        m_parent->updateCategories( categories );\r\n\t}\r\n}\r\n\r\nvoid InventoryProxy::setActive( bool active, const GuiWatchedItem& gwi )\r\n{\r\n    emit signalSetActive( active, gwi );\r\n}"
  },
  {
    "path": "src/gui/xaml/inventoryproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorinventory.h\"\r\n#include \"inventorymodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass InventoryProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tInventoryProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::InventoryModel* parent );\r\n\r\n    void requestCategories();\r\n\r\n    void setActive( bool active, const GuiWatchedItem& gwi );\r\n\r\nprivate:\r\n\tIngnomiaGUI::InventoryModel* m_parent = nullptr;\r\n\r\n\r\n\r\nprivate slots:\r\n    void onCategoryUpdate( const QList<GuiInventoryCategory>& categories );\r\n\r\nsignals:\r\n    void signalRequestCategories();\r\n    void signalSetActive( bool active, const GuiWatchedItem& gwi );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/loadgameproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"loadgameproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nLoadGameProxy::LoadGameProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( this, &LoadGameProxy::signalRequestKingdoms, Global::eventConnector->aggregatorLoadGame(), &AggregatorLoadGame::onRequestKingdoms, Qt::QueuedConnection );\r\n\tconnect( this, &LoadGameProxy::signalRequestSaveGames, Global::eventConnector->aggregatorLoadGame(), &AggregatorLoadGame::onRequestSaveGames, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorLoadGame(), &AggregatorLoadGame::signalKingdoms, this, &LoadGameProxy::onKingdoms, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorLoadGame(), &AggregatorLoadGame::signalSaveGames, this, &LoadGameProxy::onSaveGames, Qt::QueuedConnection );\r\n}\r\n\r\nvoid LoadGameProxy::setParent( IngnomiaGUI::LoadGameModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid LoadGameProxy::requestKingdoms()\r\n{\r\n\temit signalRequestKingdoms();\r\n}\r\n\r\nvoid LoadGameProxy::onKingdoms( const QList<GuiSaveInfo>& kingdoms )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateSavedKingdoms( kingdoms );\r\n\t}\r\n}\r\n\r\nvoid LoadGameProxy::requestSaveGames( const QString path )\r\n{\r\n\temit signalRequestSaveGames( path );\r\n}\r\n\r\nvoid LoadGameProxy::onSaveGames( const QList<GuiSaveInfo>& saveGames )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateSaveGames( saveGames );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/loadgameproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorloadgame.h\"\r\n#include \"LoadGameModel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass LoadGameProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tLoadGameProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::LoadGameModel* parent );\r\n\r\n\tvoid requestKingdoms();\r\n\tvoid requestSaveGames( const QString path );\r\n\r\nprivate:\r\n\tIngnomiaGUI::LoadGameModel* m_parent = nullptr;\r\n\r\nprivate slots:\r\n\tvoid onKingdoms( const QList<GuiSaveInfo>& kingdoms );\r\n\tvoid onSaveGames( const QList<GuiSaveInfo>& saveGames );\r\n\r\nsignals:\r\n\tvoid signalRequestKingdoms();\r\n\tvoid signalRequestSaveGames( const QString path );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/military.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"military.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nMilitaryGui::MilitaryGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &MilitaryGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid MilitaryGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"MilitaryGui.xaml\" );\r\n}\r\n\r\nbool MilitaryGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid MilitaryGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::MilitaryGui, \"IngnomiaGUI.MilitaryGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/military.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass MilitaryGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tMilitaryGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( MilitaryGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n"
  },
  {
    "path": "src/gui/xaml/militarymodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"militarymodel.h\"\r\n#include \"militaryproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSquadPriority::SquadPriority( const GuiTargetPriority& prio, unsigned int squadID, MilitaryProxy* proxy ) :\r\n\tm_name( prio.name.toStdString().c_str() ),\r\n\tm_idString( prio.id.toStdString().c_str() ),\r\n\tm_attitude( prio.attitude ),\r\n\tm_squadID( squadID ),\r\n\tm_proxy( proxy )\r\n{\r\n\tm_moveUpCmd.SetExecuteFunc( MakeDelegate( this, &SquadPriority::onMoveUpCmd ) );\r\n\tm_moveDownCmd.SetExecuteFunc( MakeDelegate( this, &SquadPriority::onMoveDownCmd ) );\r\n}\r\n\r\n\r\nvoid SquadPriority::setDefend( bool value )\r\n{\r\n\tif( value && m_attitude != MilAttitude::DEFEND )\r\n\t{\r\n\t\tm_attitude = MilAttitude::DEFEND;\r\n\t\tm_proxy->setAttitude( m_squadID, m_idString.Str(), m_attitude );\r\n\t\tOnPropertyChanged( \"Flee\" );\r\n\t\tOnPropertyChanged( \"Defend\" );\r\n\t\tOnPropertyChanged( \"Attack\" );\r\n\t\tOnPropertyChanged( \"Hunt\" );\r\n\t}\r\n}\r\n\r\nvoid SquadPriority::setFlee( bool value )\r\n{\r\n\tif( value && m_attitude != MilAttitude::FLEE )\r\n\t{\r\n\t\tm_attitude = MilAttitude::FLEE;\r\n\t\tm_proxy->setAttitude( m_squadID, m_idString.Str(), m_attitude );\r\n\t\tOnPropertyChanged( \"Flee\" );\r\n\t\tOnPropertyChanged( \"Defend\" );\r\n\t\tOnPropertyChanged( \"Attack\" );\r\n\t\tOnPropertyChanged( \"Hunt\" );\r\n\t}\r\n}\r\n\r\nvoid SquadPriority::setAttack( bool value )\r\n{\r\n\tif( value && m_attitude != MilAttitude::ATTACK )\r\n\t{\r\n\t\tm_attitude = MilAttitude::ATTACK;\r\n\t\tm_proxy->setAttitude( m_squadID, m_idString.Str(), m_attitude );\r\n\t\tOnPropertyChanged( \"Flee\" );\r\n\t\tOnPropertyChanged( \"Defend\" );\r\n\t\tOnPropertyChanged( \"Attack\" );\r\n\t\tOnPropertyChanged( \"Hunt\" );\r\n\t}\r\n}\r\n\r\nvoid SquadPriority::setHunt( bool value )\r\n{\r\n\tif( value && m_attitude != MilAttitude::HUNT )\r\n\t{\r\n\t\tm_attitude = MilAttitude::HUNT;\r\n\t\tm_proxy->setAttitude( m_squadID, m_idString.Str(), m_attitude );\r\n\t\tOnPropertyChanged( \"Flee\" );\r\n\t\tOnPropertyChanged( \"Defend\" );\r\n\t\tOnPropertyChanged( \"Attack\" );\r\n\t\tOnPropertyChanged( \"Hunt\" );\r\n\t}\r\n}\r\n\r\nvoid SquadPriority::onMoveUpCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tm_proxy->movePrioUp( m_squadID, param->ToString().Str() );\r\n\t}\r\n}\r\n\r\nvoid SquadPriority::onMoveDownCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tm_proxy->movePrioDown( m_squadID, param->ToString().Str() );\r\n\t}\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSquadGnome::SquadGnome( const GuiSquadGnome& gnome, bool showLeft, bool showRight, bool showX, MilitaryProxy* proxy ) :\r\n\tm_id( gnome.id ),\r\n\tm_idString( QString::number( gnome.id ).toStdString().c_str() ),\r\n\tm_name( gnome.name.toStdString().c_str() ),\r\n\tm_showLeftArrow( showLeft ),\r\n\tm_showRightArrow( showRight ),\r\n\tm_showX( showX ),\r\n\tm_proxy( proxy ),\r\n\tm_roleID( gnome.roleID )\r\n{\r\n}\r\n\r\nRoleItem* SquadGnome::getRole() const\r\n{\r\n\treturn m_role;\r\n}\r\n\t\r\nvoid SquadGnome::setRole( RoleItem* role )\r\n{\r\n\tif( m_role != role )\r\n\t{\r\n\t\tm_role = role;\r\n\t\tm_proxy->setRole( m_id, role->getID() );\r\n\t\tOnPropertyChanged( \"Role\" );\r\n\t}\r\n}\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSquadItem::SquadItem( const GuiSquad& squad, MilitaryProxy* proxy ) :\r\n\tm_id( squad.id ),\r\n\tm_idString( QString::number( squad.id ).toStdString().c_str() ),\r\n\tm_name( squad.name.toStdString().c_str() ),\r\n\tm_showLeftArrow( squad.showLeftArrow ),\r\n\tm_showRightArrow( squad.showRightArrow ),\r\n\tm_proxy( proxy )\r\n{\r\n\tm_gnomes = *new ObservableCollection<SquadGnome>();\r\n\tfor( const auto& gnome: squad.gnomes )\r\n\t{\r\n\t\tm_gnomes->Add( MakePtr<SquadGnome>( gnome, m_showLeftArrow, m_showRightArrow || ( m_id == 0 ), ( m_id != 0 ),  m_proxy ) );\r\n\t}\r\n\r\n\tm_priorities = *new ObservableCollection<SquadPriority>();\r\n\tfor( const auto& prio : squad.priorities )\r\n\t{\r\n\t\tm_priorities->Add( MakePtr<SquadPriority>( prio, squad.id, proxy ) );\r\n\t}\r\n\r\n\tm_showConfigCmd.SetExecuteFunc( MakeDelegate( this, &SquadItem::onShowConfigCmd ) );\r\n}\r\n\r\nvoid SquadItem::setName( const char* value )\r\n{\r\n\tm_name = value;\r\n\tm_proxy->renameSquad( m_id, m_name.Str() );\r\n\t//OnPropertyChanged( \"Name\" );\r\n}\r\n\r\nvoid SquadItem::onShowConfigCmd( BaseComponent* param )\r\n{\r\n\tm_showConfig = !m_showConfig;\r\n\tOnPropertyChanged( \"ShowConfig\" );\r\n}\r\n\r\nvoid SquadItem::updatePriorities( const QList<GuiTargetPriority>& prios )\r\n{\r\n\tm_priorities->Clear();\r\n\tfor( const auto& prio : prios )\r\n\t{\r\n\t\tm_priorities->Add( MakePtr<SquadPriority>( prio, m_id, m_proxy ) );\r\n\t}\r\n\tOnPropertyChanged( \"Priorities\" );\r\n}\r\n\r\nUniformModelMaterial::UniformModelMaterial( QString sid, QString name ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_sid( sid.toStdString().c_str() )\r\n{\r\n\r\n}\r\n\r\n\r\n\r\nUniformModelType::UniformModelType( QString sid, QString name ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_sid( sid.toStdString().c_str() )\r\n{\r\n\r\n}\r\n\r\nUniformModelItem::UniformModelItem( const GuiUniformItem& gui, unsigned int roleID, MilitaryProxy* proxy ) :\r\n\tm_name( gui.slotName.toStdString().c_str() ),\r\n\tm_sid( gui.slotName.toStdString().c_str() ),\r\n\tm_mat( gui.material ),\r\n\tm_roleID( roleID ),\r\n\tm_proxy( proxy )\r\n{\r\n\tm_availableTypes = *new ObservableCollection<UniformModelType>();\r\n\tm_availableMats = *new ObservableCollection<UniformModelMaterial>();\r\n\r\n\tint selectedIndex = -1;\r\n\tint i = -1;\r\n\tfor( auto type : gui.possibleTypesForSlot )\r\n\t{\r\n\t\t++i;\r\n\t\tif( type == gui.armorType )\r\n\t\t{\r\n\t\t\tselectedIndex = i;\r\n\t\t}\r\n\t\tm_availableTypes->Add( MakePtr<UniformModelType>( type, type ) );\r\n\t}\r\n\tif( selectedIndex != -1 )\r\n\t{\r\n\t\tsetSelectedType( m_availableTypes->Get( selectedIndex ) );\r\n\t\tm_mat = gui.material;\r\n\t}\r\n}\r\n\r\nvoid UniformModelItem::setSelectedType( UniformModelType* type )\r\n{\r\n\tif ( m_selectedType != type && type != nullptr )\r\n\t{\r\n\t\tm_selectedType = type;\r\n\t\tm_mat = \"any\";\r\n\t\tm_proxy->setArmorType( m_roleID, m_sid.Str(), type->sid(), \"any\" );\r\n\t\t\r\n\t\t//OnPropertyChanged( \"SelectedType\" );\r\n\t}\r\n}\r\n\r\nvoid UniformModelItem::setSelectedMaterial( UniformModelMaterial* mat )\r\n{\r\n\tif ( m_selectedMat != mat && mat != nullptr )\r\n\t{\r\n\t\tm_selectedMat = mat;\r\n\t\tm_mat = mat->sid();\r\n\t\tif( m_selectedType )\r\n\t\t{\r\n\t\t\tm_proxy->setArmorType( m_roleID, m_sid.Str(), m_selectedType->sid(), mat->sid() );\r\n\t\t}\r\n\t\t//OnPropertyChanged( \"SelectedType\" );\r\n\t}\r\n}\r\n\r\nvoid UniformModelItem::setPossibleMats( QStringList mats )\r\n{\r\n\tm_availableMats->Clear();\r\n\tint selectedMat = -1;\r\n\t\r\n\tfor( int i = 0; i < mats.size(); ++i )\r\n\t{\r\n\t\tQString mat = mats[i];\r\n\t\tm_availableMats->Add( MakePtr<UniformModelMaterial>( mat, mat ) );\r\n\t\tif( mat == m_mat )\r\n\t\t{\r\n\t\t\tselectedMat = i;\r\n\t\t}\r\n\t}\r\n\tif( selectedMat != -1 )\r\n\t{\r\n\t\tm_selectedMat = m_availableMats->Get( selectedMat );\r\n\t}\r\n\tOnPropertyChanged( \"AvailableMaterials\" );\r\n\tOnPropertyChanged( \"SelectedMaterial\" );\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nRoleItem::RoleItem( const GuiMilRole& role, MilitaryProxy* proxy ) :\r\n\tm_id( role.id ),\r\n\tm_idString( QString::number( role.id ).toStdString().c_str() ),\r\n\tm_name( role.name.toStdString().c_str() ),\r\n\tm_showLeftArrow( role.showLeftArrow ),\r\n\tm_showRightArrow( role.showRightArrow ),\r\n\tm_proxy( proxy )\r\n{\r\n\tm_showConfigCmd.SetExecuteFunc( MakeDelegate( this, &RoleItem::onShowConfigCmd ) );\r\n\r\n\tm_uniformItems = *new ObservableCollection<UniformModelItem>();\r\n\r\n\tfor( const auto& gui : role.uniform )\r\n\t{\r\n\t\tm_uniformItems->Add( MakePtr<UniformModelItem>( gui, m_id, m_proxy ) );\r\n\t}\r\n\r\n}\r\n\r\nvoid RoleItem::setName( const char* value )\r\n{\r\n\tm_name = value;\r\n\tm_proxy->renameRole( m_id, m_name.Str() );\r\n\t//OnPropertyChanged( \"Name\" );\r\n}\r\n\r\nvoid RoleItem::onShowConfigCmd( BaseComponent* param )\r\n{\r\n\tm_showConfig = !m_showConfig;\r\n\tOnPropertyChanged( \"ShowConfig\" );\r\n}\r\n\r\nvoid RoleItem::updatePossibleMaterials( QString slot, QStringList mats )\r\n{\r\n\tfor( int i = 0; i < m_uniformItems->Count(); ++i )\r\n\t{\r\n\t\tauto item = m_uniformItems->Get( i );\r\n\t\tif( item->sid() == slot )\r\n\t\t{\r\n\t\t\titem->setPossibleMats( mats );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nbool RoleItem::GetCivilian() const\r\n{\r\n\treturn m_civilian;\r\n}\r\n\t\r\nvoid RoleItem::SetCivilian( bool value )\r\n{\r\n\tif( m_civilian != value )\r\n\t{\r\n\t\tm_civilian = value;\r\n\t\tm_proxy->setRoleCivilian( m_id, value );\r\n\t}\r\n}\r\n\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nMilitaryModel::MilitaryModel()\r\n{\r\n\tm_proxy = new MilitaryProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_pageCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onPageCmd ) );\r\n\tm_addSquadCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onAddSquadCmd ) );\r\n\tm_removeSquadCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onRemoveSquadCmd ) );\r\n\tm_moveSquadLeftCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onMoveSquadLeftCmd ) );\r\n\tm_moveSquadRightCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onMoveSquadRightCmd ) );\r\n\r\n\tm_removeGnomeFromSquadCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onRemoveGnomeFromSquadCmd ) );\r\n\tm_moveGnomeLeftCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onMoveGnomeLeftCmd ) );\r\n\tm_moveGnomeRightCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onMoveGnomeRightCmd ) );\r\n\t\r\n\tm_addRoleCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onAddRoleCmd ) );\r\n\tm_removeRoleCmd.SetExecuteFunc( MakeDelegate( this, &MilitaryModel::onRemoveRoleCmd ) );\r\n\r\n\r\n\tm_squads = *new ObservableCollection<SquadItem>();\r\n\tm_roles = *new ObservableCollection<RoleItem>();\r\n}\r\n\r\nconst char* MilitaryModel::getShowFirst() const\r\n{\r\n\tif ( m_page == MilitaryPage::First )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nconst char* MilitaryModel::getShowSecond() const\r\n{\r\n\tif ( m_page == MilitaryPage::Second )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* MilitaryModel::getShowThird() const\r\n{\r\n\tif ( m_page == MilitaryPage::Third )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid MilitaryModel::onPageCmd( BaseComponent* param )\r\n{\r\n\tif( param->ToString() == \"First\" )\r\n\t{\r\n\t\tm_page = MilitaryPage::First;\r\n\t}\r\n\telse if( param->ToString() == \"Second\" )\r\n\t{\r\n\t\tm_proxy->requestRoles();\r\n\t\tm_page = MilitaryPage::Second;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_page = MilitaryPage::Third;\r\n\t}\r\n\t\r\n\tOnPropertyChanged( \"ShowFirst\" );\r\n\tOnPropertyChanged( \"ShowSecond\" );\r\n\tOnPropertyChanged( \"ShowThird\" );\r\n}\r\n\r\nvoid MilitaryModel::updateSquads( const QList<GuiSquad>& squads )\r\n{\r\n\tm_squads->Clear();\r\n\r\n\tfor( const auto& squad : squads )\r\n\t{\r\n\t\tm_squads->Add( MakePtr<SquadItem>( squad, m_proxy ) );\r\n\t}\r\n\tm_proxy->requestRoles();\r\n\r\n\tOnPropertyChanged( \"SquadList\" );\r\n}\r\n\r\nvoid MilitaryModel::updateRoles( const QList<GuiMilRole>& roles )\r\n{\r\n\tfor( int r = 0; r < m_roles->Count(); ++r )\r\n\t{\r\n\t\tauto roleItem = m_roles->Get( r );\r\n\r\n\t\tfor( int i = 0; i < m_squads->Count(); ++i )\r\n\t\t{\r\n\t\t\tauto squad = m_squads->Get( i );\r\n\t\t\tauto gnomes = squad->getGnomes();\r\n\t\t\tfor( int k = 0; k < gnomes->Count(); ++k )\r\n\t\t\t{\r\n\t\t\t\tauto gnome = gnomes->Get( k );\r\n\t\t\t\tgnome->nullifyRole();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tm_roles->Clear();\r\n\r\n\tfor( const auto& role : roles )\r\n\t{\r\n\t\tm_roles->Add( MakePtr<RoleItem>( role, m_proxy ) );\r\n\t}\r\n\t\r\n\tfor( int r = 0; r < m_roles->Count(); ++r )\r\n\t{\r\n\t\tauto roleItem = m_roles->Get( r );\r\n\r\n\t\tfor( int i = 0; i < m_squads->Count(); ++i )\r\n\t\t{\r\n\t\t\tauto squad = m_squads->Get( i );\r\n\t\t\tauto gnomes = squad->getGnomes();\r\n\t\t\tfor( int k = 0; k < gnomes->Count(); ++k )\r\n\t\t\t{\r\n\t\t\t\tauto gnome = gnomes->Get( k );\r\n\t\t\t\tif( gnome->roleID() == roleItem->getID() )\r\n\t\t\t\t{\r\n\t\t\t\t\tgnome->setRole( roleItem );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"RoleList\" );\r\n}\r\n\r\nvoid MilitaryModel::onAddSquadCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->addSquad();\r\n}\r\n\r\nvoid MilitaryModel::onRemoveSquadCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->removeSquad( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::onMoveSquadLeftCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->moveSquadLeft( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::onMoveSquadRightCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->moveSquadRight( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::onRemoveGnomeFromSquadCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->removeGnomeFromSquad( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::onMoveGnomeLeftCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->moveGnomeLeft( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::onMoveGnomeRightCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->moveGnomeRight( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::updatePriorities( unsigned int squadID, const QList<GuiTargetPriority>& priorities )\r\n{\r\n\tfor( int i = 0; i < m_squads->Count(); ++i )\r\n\t{\r\n\t\tauto squad = m_squads->Get( i );\r\n\t\tif( squad->getID() == squadID )\r\n\t\t{\r\n\t\t\tsquad->updatePriorities( priorities );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\nvoid MilitaryModel::onAddRoleCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->addRole();\r\n}\r\n\r\nvoid MilitaryModel::onRemoveRoleCmd( BaseComponent* param )\r\n{\r\n\tif( param )\r\n\t{\r\n\t\tQString qID( param->ToString().Str() );\r\n\t\tunsigned int id = qID.toUInt();\r\n\t\tm_proxy->removeRole( id );\r\n\t}\r\n}\r\n\r\nvoid MilitaryModel::updatePossibleMaterials( unsigned int roleID, const QString slot, const QStringList mats )\r\n{\r\n\tfor( int i = 0; i < m_roles->Count(); ++i )\r\n\t{\r\n\t\tif( m_roles->Get( i )->getID() == roleID )\r\n\t\t{\r\n\t\t\tm_roles->Get( i )->updatePossibleMaterials( slot, mats );\r\n\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( MilitaryModel, \"IngnomiaGUI.MilitaryModel\" )\r\n{\r\n\tNsProp( \"PageCmd\", &MilitaryModel::getPageCmd );\r\n\tNsProp( \"ShowFirst\", &MilitaryModel::getShowFirst );\r\n\tNsProp( \"ShowSecond\", &MilitaryModel::getShowSecond );\r\n\tNsProp( \"ShowThird\", &MilitaryModel::getShowThird );\r\n\r\n\tNsProp( \"SquadList\", &MilitaryModel::getSquads );\r\n\tNsProp( \"AddSquadCmd\", &MilitaryModel::getAddSquadCmd );\r\n\tNsProp( \"RemoveSquadCmd\", &MilitaryModel::getRemoveSquadCmd );\r\n\tNsProp( \"MoveSquadLeftCmd\", &MilitaryModel::getMoveSquadLeftCmd );\r\n\tNsProp( \"MoveSquadRightCmd\", &MilitaryModel::getMoveSquadRightCmd );\r\n\tNsProp( \"RemoveGnomeFromSquadCmd\", &MilitaryModel::getRemoveGnomeFromSquadCmd );\r\n\tNsProp( \"MoveGnomeLeftCmd\", &MilitaryModel::getMoveGnomeLeftCmd );\r\n\tNsProp( \"MoveGnomeRightCmd\", &MilitaryModel::getMoveGnomeRightCmd );\r\n\r\n\tNsProp( \"RoleList\", &MilitaryModel::getRoles );\r\n\tNsProp( \"AddRoleCmd\", &MilitaryModel::getAddRoleCmd );\r\n\tNsProp( \"RemoveRoleCmd\", &MilitaryModel::getRemoveRoleCmd );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( SquadItem, \"IngnomiaGUI.SquadItem\" )\r\n{\r\n\tNsProp( \"ID\", &SquadItem::getIDString );\r\n\tNsProp( \"Name\", &SquadItem::getName, &SquadItem::setName );\r\n\tNsProp( \"Gnomes\", &SquadItem::getGnomes );\r\n\tNsProp( \"Priorities\", &SquadItem::getPriorities );\r\n\tNsProp( \"ShowLeftArrow\", &SquadItem::getShowLeftArrow );\r\n\tNsProp( \"ShowRightArrow\", &SquadItem::getShowRightArrow );\r\n\tNsProp( \"ShowX\", &SquadItem::getShowX );\r\n\tNsProp( \"ConfigureSquadCmd\", &SquadItem::getShowConfigCmd );\r\n\tNsProp( \"ShowConfig\", &SquadItem::getShowConfig );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( SquadGnome, \"IngnomiaGUI.SquadGnome\" )\r\n{\r\n\tNsProp( \"ID\", &SquadGnome::getIDString );\r\n\tNsProp( \"Name\", &SquadGnome::getName );\r\n\t\r\n\tNsProp( \"ShowLeftArrow\", &SquadGnome::getShowLeftArrow );\r\n\tNsProp( \"ShowRightArrow\", &SquadGnome::getShowRightArrow );\r\n\tNsProp( \"ShowX\", &SquadGnome::getShowX );\r\n\tNsProp( \"Role\", &SquadGnome::getRole, &SquadGnome::setRole );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( SquadPriority, \"IngnomiaGUI.SquadPriority\" )\r\n{\r\n\tNsProp( \"Name\", &SquadPriority::getName );\r\n\tNsProp( \"ID\", &SquadPriority::getIDString );\r\n\tNsProp( \"Flee\", &SquadPriority::getFlee, &SquadPriority::setFlee );\r\n\tNsProp( \"Defend\", &SquadPriority::getDefend, &SquadPriority::setDefend );\r\n\tNsProp( \"Attack\", &SquadPriority::getAttack, &SquadPriority::setAttack );\r\n\tNsProp( \"Hunt\", &SquadPriority::getHunt, &SquadPriority::setHunt );\r\n\tNsProp( \"MoveUpCmd\", &SquadPriority::getMoveUpCmd );\r\n\tNsProp( \"MoveDownCmd\", &SquadPriority::getMoveDownCmd );\r\n\t\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( RoleItem, \"IngnomiaGUI.RoleItem\" )\r\n{\r\n\tNsProp( \"ID\", &RoleItem::getIDString );\r\n\tNsProp( \"Name\", &RoleItem::getName, &RoleItem::setName );\r\n\tNsProp( \"ShowLeftArrow\", &RoleItem::getShowLeftArrow );\r\n\tNsProp( \"ShowRightArrow\", &RoleItem::getShowRightArrow );\r\n\tNsProp( \"ShowX\", &RoleItem::getShowX );\r\n\tNsProp( \"ConfigureUniformCmd\", &RoleItem::getShowConfigCmd );\r\n\tNsProp( \"ShowConfig\", &RoleItem::getShowConfig );\r\n\tNsProp( \"UniformItems\", &RoleItem::getUniformItems );\r\n\tNsProp( \"Civilian\", &RoleItem::GetCivilian, &RoleItem::SetCivilian );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( UniformModelItem, \"IngnomiaGUI.UniformModelItem\" )\r\n{\r\n\tNsProp( \"ID\", &UniformModelItem::sid );\r\n\tNsProp( \"Name\", &UniformModelItem::getName );\r\n\tNsProp( \"SelectedType\", &UniformModelItem::getSelectedType, &UniformModelItem::setSelectedType );\r\n\tNsProp( \"SelectedMaterial\", &UniformModelItem::getSelectedMaterial, &UniformModelItem::setSelectedMaterial );\r\n\tNsProp( \"AvailableTypes\", &UniformModelItem::availableTypes );\r\n\tNsProp( \"AvailableMaterials\", &UniformModelItem::availableMaterials );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( UniformModelType, \"IngnomiaGUI.UniformModelType\" )\r\n{\r\n\tNsProp( \"ID\", &UniformModelType::sid );\r\n\tNsProp( \"Name\", &UniformModelType::getName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( UniformModelMaterial, \"IngnomiaGUI.UniformModelMaterial\" )\r\n{\r\n\tNsProp( \"ID\", &UniformModelMaterial::sid );\r\n\tNsProp( \"Name\", &UniformModelMaterial::getName );\r\n}"
  },
  {
    "path": "src/gui/xaml/militarymodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatormilitary.h\"\r\n\r\n#include <QString>\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\nclass MilitaryProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\nenum class MilitaryPage\r\n{\r\n\tFirst,\r\n\tSecond,\r\n\tThird\r\n};\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SquadPriority final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tSquadPriority( const GuiTargetPriority& prio, unsigned int squadID, MilitaryProxy* proxy );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\r\n\tQString getID() { return m_idString.Str(); }\r\n\r\n\tbool getDefend() const { return m_attitude == MilAttitude::DEFEND; }\r\n\tvoid setDefend( bool value );\r\n\tbool getFlee() const { return m_attitude == MilAttitude::FLEE; }\r\n\tvoid setFlee( bool value );\r\n\tbool getAttack() const { return m_attitude == MilAttitude::ATTACK; }\r\n\tvoid setAttack( bool value );\r\n\tbool getHunt() const { return m_attitude == MilAttitude::HUNT; }\r\n\tvoid setHunt( bool value );\r\n\r\nprivate:\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_name;\r\n\tMilAttitude m_attitude = MilAttitude::FLEE;\r\n\r\n\tunsigned int m_squadID = 0;\r\n\tMilitaryProxy* m_proxy = nullptr;\r\n\r\n\tvoid onMoveUpCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getMoveUpCmd() const\r\n\t{\r\n\t\treturn &m_moveUpCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_moveUpCmd;\r\n\r\n\tvoid onMoveDownCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getMoveDownCmd() const\r\n\t{\r\n\t\treturn &m_moveDownCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_moveDownCmd;\r\n\t\r\n\tNS_DECLARE_REFLECTION( SquadPriority, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass RoleItem;\r\nclass SquadGnome final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tSquadGnome( const GuiSquadGnome& gnome, bool showLeft, bool showRight, bool showX, MilitaryProxy* proxy );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\r\n\tunsigned int getID() { return m_id; }\r\n\r\n\tconst char* getShowLeftArrow() const { return m_showLeftArrow ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowRightArrow() const { return m_showRightArrow ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowX() const { return m_showX ? \"Visible\" : \"Hidden\"; }\r\n\r\n\tRoleItem* getRole() const;\r\n\tvoid setRole( RoleItem* role );\r\n\tvoid nullifyRole() { m_role = nullptr; }\r\n\tunsigned int roleID() { return m_roleID; }\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_name;\r\n\tMilitaryProxy* m_proxy = nullptr;\r\n\r\n\tbool m_showLeftArrow = true;\r\n\tbool m_showRightArrow = true;\r\n\tbool m_showX = true;\r\n\r\n\tunsigned int m_roleID = 0;\r\n\tRoleItem* m_role = nullptr;\r\n\t\r\n\tNS_DECLARE_REFLECTION( SquadGnome, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SquadItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tSquadItem( const GuiSquad& squad, MilitaryProxy* proxy );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\tvoid setName( const char* value );\r\n\r\n\tunsigned int getID() { return m_id; }\r\n\r\n\tvoid updatePriorities( const QList<GuiTargetPriority>& prios );\r\n\r\n\tNoesis::ObservableCollection<SquadGnome>* getGnomes() const\r\n\t{\r\n\t\treturn m_gnomes;\r\n\t}\r\n\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_name;\r\n\tMilitaryProxy* m_proxy = nullptr;\r\n\r\n\tbool m_showLeftArrow = true;\r\n\tbool m_showRightArrow = true;\r\n\r\n\tbool m_showConfig = false;\r\n\r\n\tconst char* getShowLeftArrow() const { return m_showLeftArrow ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowRightArrow() const { return m_showRightArrow ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowX() const { return ( m_id != 0 ) ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowConfig() const { return m_showConfig ? \"Visible\" : \"Collapsed\"; }\r\n\r\n\t\r\n\tNoesis::Ptr<Noesis::ObservableCollection<SquadGnome>> m_gnomes;\r\n\r\n\tvoid onShowConfigCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getShowConfigCmd() const\r\n\t{\r\n\t\treturn &m_showConfigCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_showConfigCmd;\r\n\r\n\tNoesis::ObservableCollection<SquadPriority>* getPriorities() const\r\n\t{\r\n\t\treturn m_priorities;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<SquadPriority>> m_priorities;\r\n\r\n\tNS_DECLARE_REFLECTION( SquadItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass UniformModelType final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tUniformModelType( QString sid, QString name );\r\n\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\tconst char* sid() const { return m_sid.Str(); }\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\r\n\tNS_DECLARE_REFLECTION( UniformModelType, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass UniformModelMaterial final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tUniformModelMaterial( QString sid, QString name );\r\n\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\tconst char* sid() const { return m_sid.Str(); }\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\r\n\tNS_DECLARE_REFLECTION( UniformModelMaterial, Noesis::BaseComponent )\r\n};\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass UniformModelItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tUniformModelItem( const GuiUniformItem& gui, unsigned int roleID, MilitaryProxy* proxy );\r\n\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\tconst char* sid() const { return m_sid.Str(); }\r\n\r\n\tvoid setPossibleMats( QStringList mats );\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_sid;\r\n\tMilitaryProxy* m_proxy = nullptr;\r\n\tunsigned int m_roleID = 0;\r\n\r\n\tQString m_mat;\r\n\t\r\n\tNoesis::ObservableCollection<UniformModelType>* availableTypes() const { return m_availableTypes; }\r\n\tNoesis::ObservableCollection<UniformModelMaterial>* availableMaterials() const { return m_availableMats; }\r\n\r\n\tvoid setSelectedType( UniformModelType* type );\r\n\tUniformModelType* getSelectedType() const { return m_selectedType; };\r\n\tvoid setSelectedMaterial( UniformModelMaterial* mat );\r\n\tUniformModelMaterial* getSelectedMaterial() const { return m_selectedMat; };\r\n\r\n\tUniformModelType* m_selectedType = nullptr;\r\n\tUniformModelMaterial* m_selectedMat = nullptr;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<UniformModelType>> m_availableTypes;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<UniformModelMaterial>> m_availableMats;\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( UniformModelItem,  NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass RoleItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tRoleItem( const GuiMilRole& role, MilitaryProxy* proxy );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\tvoid setName( const char* value );\r\n\r\n\tunsigned int getID() { return m_id; }\r\n\tvoid updatePossibleMaterials( QString slot, QStringList mats );\r\n\r\n\tbool GetCivilian() const;\r\n\tvoid SetCivilian( bool value );\r\n\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_name;\r\n\tMilitaryProxy* m_proxy = nullptr;\r\n\r\n\tbool m_showLeftArrow = false;\r\n\tbool m_showRightArrow = false;\r\n\r\n\tbool m_showConfig = false;\r\n\r\n\tbool m_civilian = false;\r\n\r\n\tconst char* getShowLeftArrow() const { return m_showLeftArrow ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowRightArrow() const { return m_showRightArrow ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowX() const { return ( m_id != 0 ) ? \"Visible\" : \"Hidden\"; }\r\n\tconst char* getShowConfig() const { return m_showConfig ? \"Visible\" : \"Collapsed\"; }\r\n\r\n\t\r\n\tvoid onShowConfigCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getShowConfigCmd() const\r\n\t{\r\n\t\treturn &m_showConfigCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_showConfigCmd;\r\n\r\n\tNoesis::ObservableCollection<UniformModelItem>* getUniformItems() const\r\n\t{\r\n\t\treturn m_uniformItems;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<UniformModelItem>> m_uniformItems;\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( RoleItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass MilitaryModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tMilitaryModel();\r\n\r\n\tvoid updateSquads( const QList<GuiSquad>& squads );\r\n\tvoid updatePriorities( unsigned int squadID, const QList<GuiTargetPriority>& priorities );\r\n\tvoid updateRoles( const QList<GuiMilRole>& roles );\r\n\tvoid updatePossibleMaterials( unsigned int roleID, const QString slot, const QStringList mats );\r\n\r\nprivate:\r\n\tMilitaryProxy* m_proxy = nullptr;\r\n\r\n\tMilitaryPage m_page = MilitaryPage::First;\r\n\r\n\tconst char* getShowFirst() const;\r\n\tconst char* getShowSecond() const;\r\n\tconst char* getShowThird() const;\r\n\r\n\tvoid onPageCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getPageCmd() const\r\n\t{\r\n\t\treturn &m_pageCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_pageCmd;\r\n\r\n\tNoesis::ObservableCollection<SquadItem>* getSquads() const\r\n\t{\r\n\t\treturn m_squads;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<SquadItem>> m_squads;\r\n\t\r\n\tvoid onAddSquadCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getAddSquadCmd() const\r\n\t{\r\n\t\treturn &m_addSquadCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_addSquadCmd;\r\n\r\n\tvoid onRemoveSquadCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getRemoveSquadCmd() const\r\n\t{\r\n\t\treturn &m_removeSquadCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_removeSquadCmd;\r\n\r\n\tvoid onMoveSquadLeftCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getMoveSquadLeftCmd() const\r\n\t{\r\n\t\treturn &m_moveSquadLeftCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_moveSquadLeftCmd;\r\n\r\n\tvoid onMoveSquadRightCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getMoveSquadRightCmd() const\r\n\t{\r\n\t\treturn &m_moveSquadRightCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_moveSquadRightCmd;\r\n\r\n\tvoid onRemoveGnomeFromSquadCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getRemoveGnomeFromSquadCmd() const\r\n\t{\r\n\t\treturn &m_removeGnomeFromSquadCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_removeGnomeFromSquadCmd;\r\n\r\n\tvoid onMoveGnomeLeftCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getMoveGnomeLeftCmd() const\r\n\t{\r\n\t\treturn &m_moveGnomeLeftCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_moveGnomeLeftCmd;\r\n\r\n\tvoid onMoveGnomeRightCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getMoveGnomeRightCmd() const\r\n\t{\r\n\t\treturn &m_moveGnomeRightCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_moveGnomeRightCmd;\r\n\r\n\r\n\tNoesis::ObservableCollection<RoleItem>* getRoles() const\r\n\t{\r\n\t\treturn m_roles;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<RoleItem>> m_roles;\r\n\r\n\r\n\tvoid onAddRoleCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getAddRoleCmd() const\r\n\t{\r\n\t\treturn &m_addRoleCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_addRoleCmd;\r\n\r\n\tvoid onRemoveRoleCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getRemoveRoleCmd() const\r\n\t{\r\n\t\treturn &m_removeRoleCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_removeRoleCmd;\r\n\r\n\r\n\r\n\r\n\tNS_DECLARE_REFLECTION( MilitaryModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n"
  },
  {
    "path": "src/gui/xaml/militaryproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"militaryproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nMilitaryProxy::MilitaryProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( this, &MilitaryProxy::signalAddSquad, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onAddSquad, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalRemoveSquad, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRemoveSquad, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalRenameSquad, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRenameSquad, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalMoveSquadLeft, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onMoveSquadLeft, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalMoveSquadRight, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onMoveSquadRight, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalRemoveGnomeFromSquad, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRemoveGnomeFromSquad, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalMoveGnomeLeft, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onMoveGnomeLeft, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalMoveGnomeRight, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onMoveGnomeRight, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalSetAttitude, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onSetAttitude, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalMovePrioUp, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onMovePrioUp, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalMovePrioDown, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onMovePrioDown, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalRequestRoles, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRequestRoles, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalAddRole, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onAddRole, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalRemoveRole, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRemoveRole, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalRenameRole, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onRenameRole, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalSetArmorType, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onSetArmorType, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalSetRole, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onSetRole, Qt::QueuedConnection );\r\n\tconnect( this, &MilitaryProxy::signalSetRoleCivilian, Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::onSetRoleCivilian, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::signalSquads, this, &MilitaryProxy::onSquads, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::signalPriorities, this, &MilitaryProxy::onPriorities, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::signalRoles, this, &MilitaryProxy::onRoles, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorMilitary(), &AggregatorMilitary::signalPossibleMaterials, this, &MilitaryProxy::onPossibleMaterials, Qt::QueuedConnection );\r\n\r\n\r\n}\r\n\r\nvoid MilitaryProxy::setParent( IngnomiaGUI::MilitaryModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid MilitaryProxy::onSquads( const QList<GuiSquad>& squads )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateSquads( squads );\r\n\t}\r\n}\r\n\r\nvoid MilitaryProxy::addSquad()\r\n{\r\n\temit signalAddSquad();\r\n}\r\n\r\nvoid MilitaryProxy::removeSquad( unsigned int id )\r\n{\r\n\temit signalRemoveSquad( id );\r\n}\r\n\r\nvoid MilitaryProxy::renameSquad( unsigned int id, QString newName )\r\n{\r\n\temit signalRenameSquad( id, newName );\r\n}\r\n\r\nvoid MilitaryProxy::moveSquadLeft( unsigned int id )\r\n{\r\n\temit signalMoveSquadLeft( id );\r\n}\r\n\t\r\nvoid MilitaryProxy::moveSquadRight( unsigned int id )\r\n{\r\n\temit signalMoveSquadRight( id );\r\n}\r\n\r\nvoid MilitaryProxy::removeGnomeFromSquad( unsigned int gnomeID )\r\n{\r\n\temit signalRemoveGnomeFromSquad( gnomeID );\r\n\t\r\n}\r\n\t\r\nvoid MilitaryProxy::moveGnomeLeft( unsigned int gnomeID )\r\n{\r\n\temit signalMoveGnomeLeft( gnomeID );\r\n\t\r\n}\r\n\r\nvoid MilitaryProxy::moveGnomeRight( unsigned int gnomeID )\r\n{\r\n\t\r\n\temit signalMoveGnomeRight( gnomeID );\r\n}\r\n\r\nvoid MilitaryProxy::setAttitude( unsigned int squadID, QString type, MilAttitude attitude )\r\n{\r\n\temit signalSetAttitude( squadID, type, attitude );\r\n}\r\n\r\nvoid MilitaryProxy::movePrioUp( unsigned int squadID, QString type )\r\n{\r\n\temit signalMovePrioUp( squadID, type );\r\n}\r\n\t\r\nvoid MilitaryProxy::movePrioDown( unsigned int squadID, QString type )\r\n{\r\n\temit signalMovePrioDown( squadID, type );\r\n}\r\n\r\nvoid MilitaryProxy::onPriorities( unsigned int squadID, const QList<GuiTargetPriority>& priorities )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updatePriorities( squadID, priorities );\r\n\t}\r\n}\r\n\r\nvoid MilitaryProxy::requestRoles()\r\n{\r\n\temit signalRequestRoles();\r\n}\r\n\r\nvoid MilitaryProxy::onRoles( const QList<GuiMilRole> roles )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateRoles( roles );\r\n\t}\r\n}\r\n\r\nvoid MilitaryProxy::addRole()\r\n{\r\n\temit signalAddRole();\r\n}\r\n\r\nvoid MilitaryProxy::removeRole( unsigned int id )\r\n{\r\n\temit signalRemoveRole( id );\r\n}\r\n\r\nvoid MilitaryProxy::renameRole( unsigned int id, QString newName )\r\n{\r\n\temit signalRenameRole( id, newName );\r\n}\r\n\r\nvoid MilitaryProxy::setArmorType( unsigned int roleID, QString slot, QString type, QString material )\r\n{\r\n\temit signalSetArmorType( roleID, slot, type, material );\r\n}\r\n\r\nvoid MilitaryProxy::onPossibleMaterials( unsigned int roleID, const QString slot, const QStringList mats )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updatePossibleMaterials( roleID, slot, mats );\r\n\t}\r\n}\r\n\r\nvoid MilitaryProxy::setRole( unsigned int gnomeID, unsigned int roleID )\r\n{\r\n\temit signalSetRole( gnomeID, roleID );\r\n}\r\n\r\nvoid MilitaryProxy::setRoleCivilian( unsigned int roleID, bool value )\r\n{\r\n\temit signalSetRoleCivilian( roleID, value );\r\n}"
  },
  {
    "path": "src/gui/xaml/militaryproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatormilitary.h\"\r\n#include \"militarymodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass MilitaryProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tMilitaryProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::MilitaryModel* parent );\r\n\r\n\tvoid addSquad();\r\n\tvoid removeSquad( unsigned int id );\r\n\tvoid renameSquad( unsigned int id, QString newName );\r\n\tvoid moveSquadLeft( unsigned int id );\r\n\tvoid moveSquadRight( unsigned int id );\r\n\tvoid removeGnomeFromSquad( unsigned int gnomeID );\r\n\tvoid moveGnomeLeft( unsigned int id );\r\n\tvoid moveGnomeRight( unsigned int id );\r\n\tvoid movePrioUp( unsigned int squadID, QString type );\r\n\tvoid movePrioDown( unsigned int squadID, QString type );\r\n\r\n\tvoid setAttitude( unsigned int squadID, QString type, MilAttitude attitude );\r\n\r\n\tvoid requestRoles();\r\n\tvoid addRole();\r\n\tvoid removeRole( unsigned int id );\r\n\tvoid renameRole( unsigned int id, QString newName );\r\n\r\n\tvoid setArmorType( unsigned int roleID, QString slot, QString type, QString material );\r\n\tvoid setRole( unsigned int gnomeID, unsigned int roleID );\r\n\r\n\tvoid setRoleCivilian( unsigned int roleID, bool value );\r\n\r\nprivate:\r\n\tIngnomiaGUI::MilitaryModel* m_parent = nullptr;\r\n\r\n\r\n\r\nprivate slots:\r\n\tvoid onSquads( const QList<GuiSquad>& squads );\r\n\tvoid onPriorities( unsigned int squadID, const QList<GuiTargetPriority>& priorities );\r\n\tvoid onRoles( const QList<GuiMilRole> roles );\r\n\tvoid onPossibleMaterials( unsigned int roleID, const QString slot, const QStringList mats );\r\n\r\nsignals:\r\n\tvoid signalAddSquad();\r\n\tvoid signalRemoveSquad( unsigned int id );\r\n\tvoid signalRenameSquad( unsigned int id, QString newName );\r\n\tvoid signalMoveSquadLeft( unsigned int id );\r\n\tvoid signalMoveSquadRight( unsigned int id );\r\n\tvoid signalRemoveGnomeFromSquad( unsigned int gnomeID );\r\n\tvoid signalMoveGnomeLeft( unsigned int id );\r\n\tvoid signalMoveGnomeRight( unsigned int id );\r\n\tvoid signalSetAttitude( unsigned int squadID, QString type, MilAttitude attitude );\r\n\tvoid signalMovePrioUp( unsigned int squadID, QString type );\r\n\tvoid signalMovePrioDown( unsigned int squadID, QString type );\r\n\tvoid signalRequestRoles();\r\n\tvoid signalAddRole();\r\n\tvoid signalRemoveRole( unsigned int id );\r\n\tvoid signalRenameRole( unsigned int id, QString newName );\r\n\tvoid signalSetArmorType( unsigned int roleID, QString slot, QString type, QString material );\r\n\tvoid signalSetRole( unsigned int gnomeID, unsigned int roleID );\r\n\tvoid signalSetRoleCivilian( unsigned int roleID, bool value );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/neighbors.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"neighbors.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNeighborsGui::NeighborsGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &NeighborsGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid NeighborsGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"Neighbors.xaml\" );\r\n}\r\n\r\nbool NeighborsGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid NeighborsGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::NeighborsGui, \"IngnomiaGUI.NeighborsGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/neighbors.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __NeighborsGui_H__\r\n#define __NeighborsGui_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass NeighborsGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tNeighborsGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( NeighborsGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/neighborsmodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"neighborsmodel.h\"\r\n#include \"neighborsproxy.h\"\r\n\r\n#include \"../strings.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNeighborKingdomInfo::NeighborKingdomInfo( const GuiNeighborInfo& info ) :\r\n\tm_id( info.id ),\r\n\tm_idString( QString::number( info.id ).toStdString().c_str() ),\r\n\tm_name( info.name.toStdString().c_str() ),\r\n\tm_distance( info.distance.toStdString().c_str() ),\r\n\tm_type( info.type.toStdString().c_str() ),\r\n\tm_attitude( info.attitude.toStdString().c_str() ),\r\n\tm_wealth( info.wealth.toStdString().c_str() ),\r\n\tm_economy( info.economy.toStdString().c_str() ),\r\n\tm_military( info.military.toStdString().c_str() ),\r\n\r\n\tm_discovered( info.discovered ),\r\n\tm_spyMission( info.spyMission ),\r\n\tm_sabotageMission( info.sabotageMission ),\r\n\tm_raidMission( info.raidMission ),\r\n\tm_diploMission( info.diploMission )\r\n{\r\n}\r\n\r\nconst char* NeighborKingdomInfo::getShowDiploBtn() const\r\n{\r\n\tif( m_discovered && m_diploMission )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nconst char* NeighborKingdomInfo::getShowSpyBtn() const\r\n{\r\n\tif( m_discovered && m_spyMission )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* NeighborKingdomInfo::getShowRaidBtn() const\r\n{\r\n\tif( m_discovered && m_raidMission )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* NeighborKingdomInfo::getShowSabotageBtn() const\r\n{\r\n\tif( m_discovered && m_sabotageMission )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nMissionInfo::MissionInfo( const Mission& mission ) :\r\n\tm_id( mission.id ),\r\n\tm_idString( QString::number( mission.id ).toStdString().c_str() )\r\n{\r\n\tQString qTime;\t\r\n\r\n\tswitch( mission.type )\r\n\t{\r\n\tcase MissionType::EXPLORE: \r\n\t\tm_title = \"Explore\"; \r\n\t\tswitch( mission.step )\r\n\t\t{\r\n\t\t\tcase MissionStep::LEAVE_MAP:\r\n\t\t\t\tm_currentAction = \"Leaving the area.\";\r\n\t\t\t\tqTime = \"I haven't left yet.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::TRAVEL:\r\n\t\t\t\tm_currentAction = \"Exploring the surrounding lands.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since I left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURN:\r\n\t\t\t\tm_currentAction = \"Returning from the mission.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since I left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURNED:\r\n\t\t\t{\r\n\t\t\t\tbool success = mission.result.value( \"Success\" ).toBool();\r\n\t\t\t\tif( success )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"I found a neighboring kingdom.\";\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"I failed to find something new.\";\r\n\t\t\t\t}\r\n\t\t\t\tqTime = \"It took \" + S::gi().numberWord( mission.result.value( \"TotalTime\" ).toInt() / 24 ) + \" days.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase MissionType::SPY: \r\n\t\tm_title = \"Spy\"; \r\n\t\tswitch( mission.step )\r\n\t\t{\r\n\t\t\tcase MissionStep::LEAVE_MAP:\r\n\t\t\t\tm_currentAction = \"Leaving the area.\";\r\n\t\t\t\tqTime = \"I haven't left yet.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::TRAVEL:\r\n\t\t\t\tm_currentAction = \"Traveling to the kingdom.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since I left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURN:\r\n\t\t\t\tm_currentAction = \"Returning from the mission.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since I left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURNED:\r\n\t\t\t{\r\n\t\t\t\tbool success = mission.result.value( \"Success\" ).toBool();\r\n\t\t\t\tif( success )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Success.\";\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Failure.\";\r\n\t\t\t\t}\r\n\t\t\t\tqTime = \"It took \" + S::gi().numberWord( mission.result.value( \"TotalTime\" ).toInt() / 24 ) + \" days.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase MissionType::EMISSARY: \r\n\t\tm_title = \"Emissary\";\r\n\t\tswitch( mission.step )\r\n\t\t{\r\n\t\t\tcase MissionStep::LEAVE_MAP:\r\n\t\t\t\tm_currentAction = \"Leaving the area.\";\r\n\t\t\t\tqTime = \"I haven't left yet.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::TRAVEL:\r\n\t\t\t\tm_currentAction = \"Traveling to the kingdom.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since I left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURN:\r\n\t\t\t\tm_currentAction = \"Returning from the mission.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since I left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURNED:\r\n\t\t\t{\r\n\t\t\t\tbool success = mission.result.value( \"Success\" ).toBool();\r\n\t\t\t\tif( success )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Success.\" ;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Failure.\";\r\n\t\t\t\t}\r\n\t\t\t\tqTime = \"It took \" + S::gi().numberWord( mission.result.value( \"TotalTime\" ).toInt() / 24 ) + \" days.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase MissionType::RAID: \r\n\t\tm_title = \"Raid\";\r\n\t\tswitch( mission.step )\r\n\t\t{\r\n\t\t\tcase MissionStep::LEAVE_MAP:\r\n\t\t\t\tm_currentAction = \"Leaving the area.\";\r\n\t\t\t\tqTime = \"We haven't left yet.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::TRAVEL:\r\n\t\t\t\tm_currentAction = \"Traveling to the kingdom.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since we left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURN:\r\n\t\t\t\tm_currentAction = \"Returning from the mission.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since we left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURNED:\r\n\t\t\t{\r\n\t\t\t\tbool success = mission.result.value( \"Success\" ).toBool();\r\n\t\t\t\tif( success )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Success.\";\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Failure.\";\r\n\t\t\t\t}\r\n\t\t\t\tqTime = \"It took \" + S::gi().numberWord( mission.result.value( \"TotalTime\" ).toInt() / 24 ) + \" days.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\tcase MissionType::SABOTAGE: \r\n\t\tm_title = \"Sabotage\"; \r\n\t\tswitch( mission.step )\r\n\t\t{\r\n\t\t\tcase MissionStep::LEAVE_MAP:\r\n\t\t\t\tm_currentAction = \"Leaving the area.\";\r\n\t\t\t\tqTime = \"We haven't left yet.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::TRAVEL:\r\n\t\t\t\tm_currentAction = \"Traveling to the kingdom.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since we left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURN:\r\n\t\t\t\tm_currentAction = \"Returning from the mission.\";\r\n\t\t\t\tqTime = \"It's been \" + QString::number( qMax( 1, mission.time ) ) + \" hours since we left.\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase MissionStep::RETURNED:\r\n\t\t\t{\r\n\t\t\t\tbool success = mission.result.value( \"Success\" ).toBool();\r\n\t\t\t\tif( success )\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Success.\";\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tm_currentAction = \"Failure.\";\r\n\t\t\t\t}\r\n\t\t\t\tqTime = \"It took \" + S::gi().numberWord( mission.result.value( \"TotalTime\" ).toInt() / 24 ) + \" days.\";\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbreak;\r\n\t}\r\n\r\n\tm_time = qTime.toStdString().c_str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nAvailableGnome::AvailableGnome( unsigned int id, QString name ) :\r\n\tm_id( id ),\r\n\tm_idString( QString::number( id ).toStdString().c_str() ),\r\n\tm_name( name.toStdString().c_str() )\r\n{\r\n\t\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNeighborsModel::NeighborsModel()\r\n{\r\n\tm_proxy = new NeighborsProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_pageCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onPageCmd ) );\r\n\tm_diploMissionCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onDiploMissionCmd ) );\r\n\tm_spyMissionCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onSpyMissionCmd ) );\r\n\tm_raidMissionCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onRaidMissionCmd ) );\r\n\tm_sabotageMissionCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onSabotageMissionCmd ) );\r\n\r\n\tm_newMissionBackCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onNewMissionBackCmd ) );\r\n\tm_newMissionStartCmd.SetExecuteFunc( MakeDelegate( this, &NeighborsModel::onNewMissionStartCmd ) );\r\n\r\n\tm_neighborList = *new ObservableCollection<NeighborKingdomInfo>();\r\n\tm_missionList = *new ObservableCollection<MissionInfo>();\r\n\tm_availGnomeList = *new ObservableCollection<AvailableGnome>();\r\n\tm_actionList = *new ObservableCollection<AvailableGnome>();\r\n}\r\n\r\nconst char* NeighborsModel::GetShowFirst() const\r\n{\r\n\tif ( m_page == NeighborsPage::First )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\t\r\nconst char* NeighborsModel::GetShowSecond() const\r\n{\r\n\tif ( m_page == NeighborsPage::Second )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nconst char* NeighborsModel::GetShowThird() const\r\n{\r\n\tif ( m_page == NeighborsPage::Third )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Hidden\";\r\n}\r\n\r\nvoid NeighborsModel::onPageCmd( BaseComponent* param )\r\n{\r\n\tif( param->ToString() == \"First\" )\r\n\t{\r\n\t\tm_page = NeighborsPage::First;\r\n\t}\r\n\telse if( param->ToString() == \"Second\" )\r\n\t{\r\n\t\tm_page = NeighborsPage::Second;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_page = NeighborsPage::Third;\r\n\t}\r\n\t\r\n\tOnPropertyChanged( \"ShowFirst\" );\r\n\tOnPropertyChanged( \"ShowSecond\" );\r\n\tOnPropertyChanged( \"ShowThird\" );\r\n}\r\n\r\nvoid NeighborsModel::onDiploMissionCmd( BaseComponent* param )\r\n{\r\n\tm_missionTitle = \"New diplomatic mission to\";\r\n\tOnPropertyChanged( \"MissionTitle\" );\r\n\r\n\tfor( int i = 0; i < m_neighborList->Count(); ++i )\r\n\t{\r\n\t\tauto neighbor = m_neighborList->Get( i );\r\n\t\tauto ids = neighbor->getIDString();\r\n\r\n\t\tif( strcmp( param->ToString().Str(), ids ) == 0 )\r\n\t\t{\r\n\t\t\tm_missionTarget = neighbor->getName();\r\n\t\t\tm_missionTargetID = neighbor->getID();\r\n\t\t\tOnPropertyChanged( \"MissionTarget\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tm_actionList->Clear();\r\n\r\n\tm_actionList->Add( MakePtr<AvailableGnome>( (int)MissionAction::IMPROVE, \"Improve Relations\" ) );\r\n\tm_actionList->Add( MakePtr<AvailableGnome>( (int)MissionAction::INSULT, \"Insult\" ) );\r\n\tm_actionList->Add( MakePtr<AvailableGnome>( (int)MissionAction::INVITE_TRADER, \"Invite Trader\" ) );\r\n\tm_actionList->Add( MakePtr<AvailableGnome>( (int)MissionAction::INVITE_AMBASSADOR, \"Invite Ambassador\" ) );\r\n\r\n\tOnPropertyChanged( \"MissionActions\" );\r\n\r\n\tsetSelectedAction( m_actionList->Get( 0 ) );\r\n\t\r\n\tm_showSelector = true;\r\n\tOnPropertyChanged( \"ShowGnomeSelect\" );\r\n\r\n\r\n\tm_proxy->requestAvailableGnomes();\r\n\r\n\r\n\tqDebug() << \"Diplo\" << param->ToString().Str();\r\n}\r\n\r\nvoid NeighborsModel::onSpyMissionCmd( BaseComponent* param )\r\n{\r\n\tqDebug() << \"Spy\" << param->ToString().Str();\r\n}\r\n\r\nvoid NeighborsModel::onRaidMissionCmd( BaseComponent* param )\r\n{\r\n\tqDebug() << \"Raid\" << param->ToString().Str();\r\n}\r\n\r\nvoid NeighborsModel::onSabotageMissionCmd( BaseComponent* param )\r\n{\r\n\tqDebug() << \"Sabotage\" << param->ToString().Str();\r\n}\r\n\r\nvoid NeighborsModel::neighborsUpdate( const QList<GuiNeighborInfo>& infos )\r\n{\r\n\tm_neighborList->Clear();\r\n\r\n\tfor( const auto& info : infos )\r\n\t{\r\n\t\tm_neighborList->Add( MakePtr<NeighborKingdomInfo>( info ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"NeighborList\" );\r\n}\r\n\r\nvoid NeighborsModel::missionsUpdate( const QList<Mission>& missions )\r\n{\r\n\tm_missionList->Clear();\r\n\r\n\tfor( const auto& info : missions )\r\n\t{\r\n\t\tm_missionList->Add( MakePtr<MissionInfo>( info ) );\r\n\t}\r\n\r\n\tOnPropertyChanged( \"MissionList\" );\r\n}\r\n\r\nconst char* NeighborsModel::getShowGnomeSelect() const\r\n{\r\n\treturn m_showSelector ? \"Visible\" : \"Hidden\";\r\n}\r\n\r\nvoid NeighborsModel::setSelectedGnome( AvailableGnome* gnome )\r\n{\r\n\tif( m_selectedGnome != gnome )\r\n\t{\r\n\t\tm_selectedGnome = gnome;\r\n\t\tOnPropertyChanged( \"SelectedGnome\" );\r\n\t}\r\n}\r\n\t\r\nAvailableGnome* NeighborsModel::getSelectedGnome() const\r\n{\r\n\treturn m_selectedGnome;\r\n}\r\n\r\nvoid NeighborsModel::setSelectedAction( AvailableGnome* action )\r\n{\r\n\tif( m_selectedAction != action )\r\n\t{\r\n\t\tm_selectedAction = action;\r\n\t\tOnPropertyChanged( \"SelectedAction\" );\r\n\t}\r\n}\r\n\t\r\nAvailableGnome* NeighborsModel::getSelectedAction() const\r\n{\r\n\treturn m_selectedAction;\r\n}\r\n\r\nconst char* NeighborsModel::getMissionTarget() const\r\n{\r\n\treturn m_missionTarget.Str();\r\n}\r\n\r\nconst char* NeighborsModel::getMissionTitle() const\r\n{\r\n\treturn m_missionTitle.Str();\r\n}\r\n\r\n\r\nvoid NeighborsModel::updateAvailableGnomes( const QList<GuiAvailableGnome>& gnomes )\r\n{\r\n\tm_availGnomeList->Clear();\r\n\tfor( const auto& gnome : gnomes )\r\n\t{\r\n\t\tm_availGnomeList->Add( MakePtr<AvailableGnome>( gnome.id, gnome.name ) );\r\n\t}\r\n\tOnPropertyChanged( \"MissionGnomes\" );\r\n\r\n\tif( m_availGnomeList->Count() > 0 )\r\n\t{\r\n\t\tsetSelectedGnome( m_availGnomeList->Get( 0 ) );\r\n\t}\r\n}\r\n\r\nvoid NeighborsModel::onNewMissionBackCmd( BaseComponent* param )\r\n{\r\n\tm_showSelector = false;\r\n\tOnPropertyChanged( \"ShowGnomeSelect\" );\r\n\tm_selectedGnome = nullptr;\r\n\tm_selectedAction = nullptr;\r\n\tm_missionTargetID = 0;\r\n}\r\n\r\nvoid NeighborsModel::onNewMissionStartCmd( BaseComponent* param )\r\n{\r\n\tif( m_selectedGnome && m_selectedAction && m_missionTargetID )\r\n\t{\r\n\t\tm_showSelector = false;\r\n\t\tOnPropertyChanged( \"ShowGnomeSelect\" );\r\n\t\t\r\n\t\tm_proxy->startMission( MissionType::EMISSARY, (MissionAction)m_selectedAction->getID(), m_missionTargetID, m_selectedGnome->getID() );\r\n\t}\r\n}\r\n\r\nvoid NeighborsModel::updateMission( const Mission& mission )\r\n{\r\n\tfor( int i = 0; i < m_missionList->Count(); ++i )\r\n\t{\r\n\t\tauto mis = m_missionList->Get( i );\r\n\t\tif( mis->getID() == mission.id )\r\n\t\t{\r\n\t\t\tm_missionList->RemoveAt( i );\r\n\t\t\tm_missionList->Insert( i, MakePtr<MissionInfo>( mission ) );\r\n\t\t\tOnPropertyChanged( \"MissionList\" );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( NeighborsModel, \"IngnomiaGUI.NeighborsModel\" )\r\n{\r\n\tNsProp( \"PageCmd\", &NeighborsModel::GetPageCmd );\r\n\tNsProp( \"ShowFirst\", &NeighborsModel::GetShowFirst );\r\n\tNsProp( \"ShowSecond\", &NeighborsModel::GetShowSecond );\r\n\tNsProp( \"ShowThird\", &NeighborsModel::GetShowThird );\r\n\tNsProp( \"NeighborList\", &NeighborsModel::getNeighborList );\r\n\tNsProp( \"MissionList\", &NeighborsModel::getMissionList );\r\n\r\n\tNsProp( \"CmdDiploMission\", &NeighborsModel::GetDiploMissionCmd );\r\n\tNsProp( \"CmdSpyMission\", &NeighborsModel::GetSpyMissionCmd );\r\n\tNsProp( \"CmdRaidMission\", &NeighborsModel::GetRaidMissionCmd );\r\n\tNsProp( \"CmdSabotageMission\", &NeighborsModel::GetSabotageMissionCmd );\r\n\r\n\tNsProp( \"CmdNewMissionBack\", &NeighborsModel::getNewMissionBackCmd );\r\n\tNsProp( \"CmdNewMissionStart\", &NeighborsModel::getNewMissionStartCmd );\r\n\r\n\tNsProp( \"ShowGnomeSelect\", &NeighborsModel::getShowGnomeSelect );\r\n\tNsProp( \"MissionGnomes\", &NeighborsModel::getAvailableGnomeList );\r\n\tNsProp( \"MissionActions\", &NeighborsModel::getActionList );\r\n\tNsProp( \"SelectedGnome\", &NeighborsModel::getSelectedGnome, &NeighborsModel::setSelectedGnome );\r\n\tNsProp( \"SelectedAction\", &NeighborsModel::getSelectedAction, &NeighborsModel::setSelectedAction );\r\n\tNsProp( \"MissionTarget\", &NeighborsModel::getMissionTarget );\r\n\tNsProp( \"MissionTitle\", &NeighborsModel::getMissionTitle );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( NeighborKingdomInfo, \"IngnomiaGUI.NeighborKingdomInfo\" )\r\n{\r\n\tNsProp( \"ID\", &NeighborKingdomInfo::getIDString );\r\n\tNsProp( \"Name\", &NeighborKingdomInfo::getName );\r\n\tNsProp( \"Distance\", &NeighborKingdomInfo::getDistance );\r\n\tNsProp( \"Wealth\", &NeighborKingdomInfo::getWealth );\r\n\tNsProp( \"Economy\", &NeighborKingdomInfo::getEconomy );\r\n\tNsProp( \"Military\", &NeighborKingdomInfo::getMilitary );\r\n\tNsProp( \"Attitude\", &NeighborKingdomInfo::getAttitude );\r\n\r\n\tNsProp( \"ShowDiploButton\", &NeighborKingdomInfo::getShowDiploBtn );\r\n\tNsProp( \"ShowSpyButton\", &NeighborKingdomInfo::getShowSpyBtn );\r\n\tNsProp( \"ShowRaidButton\", &NeighborKingdomInfo::getShowRaidBtn );\r\n\tNsProp( \"ShowSabotageButton\", &NeighborKingdomInfo::getShowSabotageBtn );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( MissionInfo, \"IngnomiaGUI.MissionInfo\" )\r\n{\r\n\tNsProp( \"ID\", &MissionInfo::getIDString );\r\n\tNsProp( \"Title\", &MissionInfo::getTitle );\r\n\tNsProp( \"Action\", &MissionInfo::getCurrentAction );\r\n\tNsProp( \"Time\", &MissionInfo::getTime );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( AvailableGnome, \"IngnomiaGUI.AvailableGnome\" )\r\n{\r\n\tNsProp( \"ID\", &AvailableGnome::getIDString );\r\n\tNsProp( \"Name\", &AvailableGnome::getName );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/neighborsmodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorneighbors.h\"\r\n\r\n#include <QString>\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\nclass NeighborsProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass NeighborKingdomInfo final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tNeighborKingdomInfo( const GuiNeighborInfo& info );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\tconst char* getDistance() const { return m_distance.Str(); }\r\n\tconst char* getType() const { return m_type.Str(); }\r\n\tconst char* getAttitude() const { return m_attitude.Str(); }\r\n\tconst char* getWealth() const { return m_wealth.Str(); }\r\n\tconst char* getEconomy() const { return m_economy.Str(); }\r\n\tconst char* getMilitary() const { return m_military.Str(); }\r\n\r\n\tconst char* getShowDiploBtn() const;\r\n\tconst char* getShowSpyBtn() const;\r\n\tconst char* getShowRaidBtn() const;\r\n\tconst char* getShowSabotageBtn() const;\r\n\r\n\tunsigned int getID() { return m_id;  }\r\n\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_distance;\r\n\tNoesis::String m_type;\r\n\tNoesis::String m_attitude;\r\n\tNoesis::String m_wealth;\r\n\tNoesis::String m_economy;\r\n\tNoesis::String m_military;\r\n\r\n\tbool m_discovered = false;\r\n\tbool m_spyMission = false;\r\n\tbool m_sabotageMission = false;\r\n\tbool m_raidMission = false;\r\n\tbool m_diploMission = false;\r\n\r\n\tNS_DECLARE_REFLECTION( NeighborKingdomInfo, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass MissionInfo final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tMissionInfo( const Mission& info );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getTitle() const { return m_title.Str(); }\r\n\tconst char* getCurrentAction() const { return m_currentAction.Str(); }\r\n\tconst char* getTime() const { return m_time.Str(); }\r\n\t\r\n\tunsigned int getID() { return m_id; }\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_title;\r\n\tNoesis::String m_currentAction;\r\n\tNoesis::String m_time;\r\n\t\r\n\tNS_DECLARE_REFLECTION( MissionInfo, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass AvailableGnome final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tAvailableGnome( unsigned int id, QString name );\r\n\r\n\tconst char* getIDString() const { return m_idString.Str(); }\r\n\tconst char* getName() const { return m_name.Str(); }\r\n\t\r\n\tunsigned int getID() { return m_id; }\r\n\r\nprivate:\r\n\tunsigned int m_id = 0;\r\n\tNoesis::String m_idString;\r\n\tNoesis::String m_name;\r\n\t\r\n\tNS_DECLARE_REFLECTION( AvailableGnome, BaseComponent )\r\n};\r\n\r\n\r\nenum class NeighborsPage\r\n{\r\n\tFirst,\r\n\tSecond,\r\n\tThird\r\n};\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass NeighborsModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tNeighborsModel();\r\n\r\n\tvoid neighborsUpdate( const QList<GuiNeighborInfo>& infos );\r\n\tvoid missionsUpdate( const QList<Mission>& missions );\r\n\tvoid updateAvailableGnomes( const QList<GuiAvailableGnome>& gnomes );\r\n\tvoid updateMission( const Mission& mission );\r\n\r\n\r\nprivate:\r\n\tNeighborsProxy* m_proxy = nullptr;\r\n\r\n\tNeighborsPage m_page = NeighborsPage::First;\r\n\r\n\tconst char* GetShowFirst() const;\r\n\tconst char* GetShowSecond() const;\r\n\tconst char* GetShowThird() const;\r\n\r\n\tvoid onPageCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetPageCmd() const\r\n\t{\r\n\t\treturn &m_pageCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_pageCmd;\r\n\r\n\tNoesis::ObservableCollection<NeighborKingdomInfo>* getNeighborList() const\r\n\t{\r\n\t\treturn m_neighborList;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<NeighborKingdomInfo>> m_neighborList;\r\n\r\n\tvoid onDiploMissionCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetDiploMissionCmd() const\r\n\t{\r\n\t\treturn &m_diploMissionCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_diploMissionCmd;\r\n\r\n\tvoid onSpyMissionCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSpyMissionCmd() const\r\n\t{\r\n\t\treturn &m_spyMissionCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_spyMissionCmd;\r\n\r\n\tvoid onRaidMissionCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetRaidMissionCmd() const\r\n\t{\r\n\t\treturn &m_raidMissionCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_raidMissionCmd;\r\n\r\n\tvoid onSabotageMissionCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetSabotageMissionCmd() const\r\n\t{\r\n\t\treturn &m_sabotageMissionCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_sabotageMissionCmd;\r\n\r\n\t\r\n\r\n\tNoesis::ObservableCollection<MissionInfo>* getMissionList() const\r\n\t{\r\n\t\treturn m_missionList;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<MissionInfo>> m_missionList;\r\n\r\n\tNS_DECLARE_REFLECTION( NeighborsModel, NotifyPropertyChangedBase )\r\n\r\n\tconst char* getShowGnomeSelect() const;\r\n\tbool m_showSelector = false;\r\n\r\n\tNoesis::ObservableCollection<AvailableGnome>* getAvailableGnomeList() const\r\n\t{\r\n\t\treturn m_availGnomeList;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AvailableGnome>> m_availGnomeList;\r\n\r\n\tNoesis::ObservableCollection<AvailableGnome>* getActionList() const\r\n\t{\r\n\t\treturn m_actionList;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<AvailableGnome>> m_actionList;\r\n\r\n\tAvailableGnome* m_selectedGnome = nullptr;\r\n\tvoid setSelectedGnome( AvailableGnome* gnome );\r\n\tAvailableGnome* getSelectedGnome() const;\r\n\r\n\tAvailableGnome* m_selectedAction = nullptr;\r\n\tvoid setSelectedAction( AvailableGnome* gnome );\r\n\tAvailableGnome* getSelectedAction() const;\r\n\r\n\tNoesis::String m_missionTarget;\r\n\tconst char* getMissionTarget() const;\r\n\r\n\tNoesis::String m_missionTitle;\r\n\tconst char* getMissionTitle() const;\r\n\r\n\tvoid onNewMissionBackCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getNewMissionBackCmd() const\r\n\t{\r\n\t\treturn &m_newMissionBackCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_newMissionBackCmd;\r\n\r\n\tvoid onNewMissionStartCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* getNewMissionStartCmd() const\r\n\t{\r\n\t\treturn &m_newMissionStartCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_newMissionStartCmd;\r\n\r\n\tunsigned int m_missionTargetID = 0;\r\n\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n\r\n"
  },
  {
    "path": "src/gui/xaml/neighborsproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"neighborsproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nNeighborsProxy::NeighborsProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( this, &NeighborsProxy::signalRequestAvailableGnomes, Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::onRequestAvailableGnomes, Qt::QueuedConnection );\r\n\tconnect( this, &NeighborsProxy::signalStartMission, Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::onStartMission, Qt::QueuedConnection );\r\n\t\r\n\tconnect( Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::signalNeighborsUpdate, this, &NeighborsProxy::onNeighborsUpdate, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::signalAvailableGnomes, this, &NeighborsProxy::onAvailableGnomes, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::signalMissions, this, &NeighborsProxy::onMissions, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorNeighbors(), &AggregatorNeighbors::signalUpdateMission, this, &NeighborsProxy::onUpdateMission, Qt::QueuedConnection );\r\n}\r\n\r\nvoid NeighborsProxy::setParent( IngnomiaGUI::NeighborsModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid NeighborsProxy::onNeighborsUpdate( const QList<GuiNeighborInfo>& infos )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->neighborsUpdate( infos );\r\n\t}\r\n}\r\n\r\nvoid NeighborsProxy::onMissions( const QList<Mission>& missions )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->missionsUpdate( missions );\r\n\t}\r\n}\r\n\r\nvoid NeighborsProxy::requestAvailableGnomes()\r\n{\r\n\temit signalRequestAvailableGnomes();\r\n}\r\n\r\nvoid NeighborsProxy::onAvailableGnomes( const QList<GuiAvailableGnome>& gnomes )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateAvailableGnomes( gnomes );\r\n\t}\r\n}\r\n\r\nvoid NeighborsProxy::startMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID )\r\n{\r\n\temit signalStartMission( type, action, targetKingdom, gnomeID );\r\n}\r\n\r\nvoid NeighborsProxy::onUpdateMission( const Mission& mission )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateMission( mission );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/neighborsproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorneighbors.h\"\r\n#include \"neighborsmodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass NeighborsProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tNeighborsProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::NeighborsModel* parent );\r\n\r\n\tvoid requestAvailableGnomes();\r\n\r\n\tvoid startMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID );\r\n\r\nprivate:\r\n\tIngnomiaGUI::NeighborsModel* m_parent = nullptr;\r\n\r\n\r\n\r\nprivate slots:\r\n\tvoid onNeighborsUpdate( const QList<GuiNeighborInfo>& infos );\r\n\tvoid onMissions( const QList<Mission>& missions );\r\n\tvoid onAvailableGnomes( const QList<GuiAvailableGnome>& gnomes );\r\n\tvoid onUpdateMission( const Mission& mission );\r\n\r\nsignals:\r\n\tvoid signalRequestAvailableGnomes();\r\n\tvoid signalStartMission( MissionType type, MissionAction action, unsigned int targetKingdom, unsigned int gnomeID );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/populationproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"populationproxy.h\"\r\n\r\n#include \"../../base/db.h\"\r\n#include \"../../base/gamestate.h\"\r\n#include \"../../gfx/sprite.h\"\r\n#include \"../../gfx/spritefactory.h\"\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n#include \"PopulationModel.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nPopulationProxy::PopulationProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalPopulationUpdate, this, &PopulationProxy::onUpdateInfo, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalProfessionList, this, &PopulationProxy::onProfessionList, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalProfessionSkills, this, &PopulationProxy::onProfessionSkills, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalUpdateSingleGnome, this, &PopulationProxy::onUpdateSingleGnome, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &PopulationProxy::signalSetSkillActive, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetSkillActive, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSetAllSkills, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetAllSkills, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSetAllGnomes, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetAllGnomes, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSetProfession, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetProfession, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSortGnomes, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSortGnomes, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &PopulationProxy::signalRequestSchedules, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onRequestSchedules, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSetSchedule, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetSchedule, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSetAllHours, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetAllHours, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalSetHourForAll, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onSetHourForAll, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalScheduleUpdate, this, &PopulationProxy::onUpdateSchedules, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalScheduleUpdateSingleGnome, this, &PopulationProxy::onScheduleUpdateSingleGnome, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::signalSelectEditProfession, this, &PopulationProxy::onSelectEditProfession, Qt::QueuedConnection );\r\n\t\r\n\tconnect( this, &PopulationProxy::signalRequestProfessions, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onRequestProfessions, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalRequestSkills, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onRequestSkills, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalUpdateProfession, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onUpdateProfession, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalNewProfession, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onNewProfession, Qt::QueuedConnection );\r\n\tconnect( this, &PopulationProxy::signalDeleteProfession, Global::eventConnector->aggregatorPopulation(), &AggregatorPopulation::onDeleteProfession, Qt::QueuedConnection );\r\n}\r\n\r\nPopulationProxy::~PopulationProxy()\r\n{\r\n}\r\n\r\nvoid PopulationProxy::setParent( IngnomiaGUI::PopulationModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid PopulationProxy::onUpdateInfo( const GuiPopulationInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->updateInfo( info );\r\n\t}\r\n}\r\n\r\nvoid PopulationProxy::setSkillActive( unsigned int gnomeID, QString skillID, bool value )\r\n{\r\n\temit signalSetSkillActive( gnomeID, skillID, value );\r\n}\r\n\r\nvoid PopulationProxy::setAllSkillsForGnome( unsigned int gnomeID, bool value )\r\n{\r\n\temit signalSetAllSkills( gnomeID, value );\r\n}\r\n\t\r\nvoid PopulationProxy::setSkillForAllGnomes( QString skillID, bool value )\r\n{\r\n\temit signalSetAllGnomes( skillID, value );\r\n}\r\n\r\nvoid PopulationProxy::onProfessionList( const QStringList& professions )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateProfessionList( professions );\r\n\t}\r\n}\r\n\r\nvoid PopulationProxy::onProfessionSkills( const QString profession, const QList<GuiSkillInfo>& skills )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateProfessionSkills( profession, skills );\r\n\t}\r\n}\r\n\r\nvoid PopulationProxy::setProfession( unsigned int gnomeID, QString profession )\r\n{\r\n\temit signalSetProfession( gnomeID, profession );\r\n}\r\n\r\nvoid PopulationProxy::onUpdateSingleGnome( const GuiGnomeInfo& gnome )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateSingleGnome( gnome );\r\n\t}\r\n}\r\n\r\nvoid PopulationProxy::sortGnomes( QString mode )\r\n{ \r\n\temit signalSortGnomes( mode );\r\n}\r\n\r\nvoid PopulationProxy::requestSchedules()\r\n{\r\n\temit signalRequestSchedules();\r\n}\r\n\t\r\nvoid PopulationProxy::setSchedule( unsigned int gnomeID, int hour, ScheduleActivity activity )\r\n{\r\n\temit signalSetSchedule( gnomeID, hour, m_currentActivitiy );\r\n}\r\n\r\nvoid PopulationProxy::setAllHours( unsigned int gnomeID, ScheduleActivity activitiy )\r\n{\r\n\temit signalSetAllHours( gnomeID, activitiy );\r\n}\r\n\t\r\nvoid PopulationProxy::setHourForAll( int hour, ScheduleActivity activity )\r\n{\r\n\temit signalSetHourForAll( hour, activity );\r\n}\r\n\r\nvoid PopulationProxy::onUpdateSchedules( const GuiScheduleInfo& info )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateSchedules( info );\r\n\t}\r\n}\r\n\r\nvoid PopulationProxy::onScheduleUpdateSingleGnome( const GuiGnomeScheduleInfo& info )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateScheduleSingleGnome( info );\r\n\t}\r\n}\r\n\r\nvoid PopulationProxy::setCurrentActivity( ScheduleActivity activity )\r\n{\r\n\tm_currentActivitiy = activity;\r\n}\r\n\r\nvoid PopulationProxy::requestProfessions()\r\n{\r\n\temit signalRequestProfessions();\r\n}\r\n\t\r\nvoid PopulationProxy::requestSkills( QString profession )\r\n{\r\n\temit signalRequestSkills( profession );\r\n}\r\n\r\nvoid PopulationProxy::updateProfession( QString name, QString newName, QStringList skills )\r\n{\r\n\temit signalUpdateProfession( name, newName, skills );\r\n}\r\n\r\nvoid PopulationProxy::deleteProfession( QString name )\r\n{\r\n\temit signalDeleteProfession( name );\r\n}\r\n\r\nvoid PopulationProxy::newProfession()\r\n{\r\n\temit signalNewProfession();\r\n}\r\n\r\nvoid PopulationProxy::onSelectEditProfession( const QString name )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->selectEditProfession( name );\r\n\t}\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/populationproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorpopulation.h\"\r\n#include \"PopulationModel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass PopulationProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tPopulationProxy( QObject* parent = nullptr );\r\n\t~PopulationProxy();\r\n\r\n\tvoid setParent( IngnomiaGUI::PopulationModel* parent );\r\n\tvoid setSkillActive( unsigned int gnomeID, QString skillID, bool value );\r\n\r\n\tvoid setAllSkillsForGnome( unsigned int gnomeID, bool value );\r\n\tvoid setSkillForAllGnomes( QString skillID, bool value );\r\n\r\n\tvoid setProfession( unsigned int gnomeID, QString profession );\r\n\r\n\tvoid sortGnomes( QString mode );\r\n\r\n\tvoid requestSchedules();\r\n\tvoid requestProfessions();\r\n\tvoid requestSkills( QString profession );\r\n\r\n\tvoid setAllHours( unsigned int gnomeID, ScheduleActivity activitiy );\r\n\tvoid setHourForAll( int hour, ScheduleActivity activitiy );\r\n\tvoid setSchedule( unsigned int gnomeID, int hour, ScheduleActivity activitiy );\r\n\r\n\tvoid setCurrentActivity( ScheduleActivity activitiy );\r\n\r\n\tvoid updateProfession( QString name, QString newName, QStringList skills );\r\n\tvoid deleteProfession( QString name );\r\n\tvoid newProfession();\r\n\r\nprivate:\r\n\tIngnomiaGUI::PopulationModel* m_parent = nullptr;\r\n\tScheduleActivity m_currentActivitiy = ScheduleActivity::None;\r\n\r\nprivate slots:\r\n\tvoid onUpdateInfo( const GuiPopulationInfo& info );\r\n\tvoid onProfessionList( const QStringList& professions );\r\n\tvoid onProfessionSkills( const QString profession, const QList<GuiSkillInfo>& skills );\r\n\tvoid onUpdateSingleGnome( const GuiGnomeInfo& gnome );\r\n\r\n\tvoid onUpdateSchedules( const GuiScheduleInfo& info );\r\n\tvoid onScheduleUpdateSingleGnome( const GuiGnomeScheduleInfo& info );\r\n\tvoid onSelectEditProfession( const QString name );\r\n\r\nsignals:\r\n\tvoid signalSetSkillActive( unsigned int gnomeID, QString skillID, bool value );\r\n\r\n\tvoid signalSetAllSkills( unsigned int gnomeID, bool value );\r\n\tvoid signalSetAllGnomes( QString skillID, bool value );\r\n\tvoid signalSetProfession( unsigned int gnomeID, QString profession );\r\n\tvoid signalSortGnomes( QString mode );\r\n\r\n\tvoid signalRequestSchedules();\r\n\tvoid signalRequestProfessions();\r\n\tvoid signalRequestSkills( QString profession );\r\n\tvoid signalSetSchedule( unsigned int gnomeID, int hour, ScheduleActivity activitiy );\r\n\tvoid signalSetAllHours( unsigned int gnomeID, ScheduleActivity activitiy );\r\n\tvoid signalSetHourForAll( int hour, ScheduleActivity activitiy );\r\n\r\n\tvoid signalUpdateProfession( QString name, QString newName, QStringList skills );\r\n\tvoid signalDeleteProfession( QString name );\r\n\tvoid signalNewProfession();\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/selection.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"selection.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSelectionGui::SelectionGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &SelectionGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid SelectionGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"SelectionGui.xaml\" );\r\n}\r\n\r\nbool SelectionGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid SelectionGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::SelectionGui, \"IngnomiaGUI.SelectionGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/selection.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __SelectionGui_H__\r\n#define __SelectionGui_H__\r\n\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SelectionGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tSelectionGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( SelectionGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif"
  },
  {
    "path": "src/gui/xaml/selectionmodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"selectionmodel.h\"\r\n#include \"selectionproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nSelectionModel::SelectionModel()\r\n{\r\n\tm_proxy = new SelectionProxy;\r\n\tm_proxy->setParent( this );\r\n}\r\n\r\nvoid SelectionModel::updateAction( QString action )\r\n{\r\n    m_action = action.toStdString().c_str();\r\n    OnPropertyChanged( \"Action\" );\r\n}\r\n\r\nvoid SelectionModel::updateCursor( QString pos )\r\n{\r\n    m_cursor = pos.toStdString().c_str();\r\n    OnPropertyChanged( \"Cursor\" );\r\n}\r\n\r\nvoid SelectionModel::updateFirstClick( QString pos )\r\n{\r\n    m_firstClick = pos.toStdString().c_str();\r\n    OnPropertyChanged( \"FirstClick\" );\r\n}\r\n\r\nvoid SelectionModel::updateSize( QString size )\r\n{\r\n    m_size = size.toStdString().c_str();\r\n    OnPropertyChanged( \"Size\" );\r\n}\r\n\r\n\r\nconst char* SelectionModel::getAction() const\r\n{\r\n    return m_action.Str();\r\n}\r\n\r\nconst char* SelectionModel::getCursor() const\r\n{\r\n    return m_cursor.Str();\r\n}\r\n\r\nconst char* SelectionModel::getFirstClick() const\r\n{\r\n    return m_firstClick.Str();\r\n}\r\n\r\nconst char* SelectionModel::getSize() const\r\n{\r\n    return m_size.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( SelectionModel, \"IngnomiaGUI.SelectionModel\" )\r\n{\r\n    NsProp( \"Action\", &SelectionModel::getAction );\r\n    NsProp( \"Cursor\", &SelectionModel::getCursor );\r\n    NsProp( \"FirstClick\", &SelectionModel::getFirstClick );\r\n    NsProp( \"Size\", &SelectionModel::getSize );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/selectionmodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __SelectionModel_H__\r\n#define __SelectionModel_H__\r\n\r\n#include \"../aggregatorselection.h\"\r\n\r\n#include <QString>\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\nclass SelectionProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass SelectionModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tSelectionModel();\r\n\r\n    void updateAction( QString action );\r\n    void updateCursor( QString pos );\r\n    void updateFirstClick( QString pos );\r\n    void updateSize( QString size );\r\n\r\nprivate:\r\n\tSelectionProxy* m_proxy = nullptr;\r\n\r\n    Noesis::String m_action;\r\n    Noesis::String m_cursor;\r\n    Noesis::String m_firstClick;\r\n    Noesis::String m_size;\r\n\r\n    const char* getAction() const;\r\n    const char* getCursor() const;\r\n    const char* getFirstClick() const;\r\n    const char* getSize() const;\r\n\r\n\tNS_DECLARE_REFLECTION( SelectionModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/selectionproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"selectionproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n#include \"../aggregatorselection.h\"\r\n\r\n#include <QDebug>\r\n\r\nSelectionProxy::SelectionProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorSelection(), &AggregatorSelection::signalAction, this, &SelectionProxy::onAction, Qt::QueuedConnection );\r\n    connect( Global::eventConnector->aggregatorSelection(), &AggregatorSelection::signalCursorPos, this, &SelectionProxy::onCursor, Qt::QueuedConnection );\r\n    connect( Global::eventConnector->aggregatorSelection(), &AggregatorSelection::signalFirstClick, this, &SelectionProxy::onFirstClick, Qt::QueuedConnection );\r\n    connect( Global::eventConnector->aggregatorSelection(), &AggregatorSelection::signalSize, this, &SelectionProxy::onSize, Qt::QueuedConnection );\r\n}\r\n\r\nvoid SelectionProxy::setParent( IngnomiaGUI::SelectionModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid SelectionProxy::onAction( QString action )\r\n{\r\n    if( m_parent )\r\n\t{\r\n        m_parent->updateAction( action );\r\n\t}\r\n}\r\n\r\nvoid SelectionProxy::onCursor( QString pos )\r\n{\r\n    if( m_parent )\r\n\t{\r\n        m_parent->updateCursor( pos );\r\n\t}\r\n}\r\n\r\nvoid SelectionProxy::onFirstClick( QString pos )\r\n{\r\n    if( m_parent )\r\n\t{\r\n        m_parent->updateFirstClick( pos );\r\n\t}\r\n}\r\n\r\nvoid SelectionProxy::onSize( QString size )\r\n{\r\n    if( m_parent )\r\n\t{\r\n        m_parent->updateSize( size );\r\n\t}\r\n}"
  },
  {
    "path": "src/gui/xaml/selectionproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"selectionmodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass SelectionProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tSelectionProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::SelectionModel* parent );\r\n\r\n\r\nprivate:\r\n\tIngnomiaGUI::SelectionModel* m_parent = nullptr;\r\n\r\n\r\n\r\nprivate slots:\r\n    void onAction( QString action );\r\n    void onCursor( QString pos );\r\n    void onFirstClick( QString pos );\r\n    void onSize( QString pos );\r\n\r\nsignals:\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/settingsproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"settingsproxy.h\"\r\n\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n\r\nSettingsProxy::SettingsProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( this, &SettingsProxy::signalRequestSettings, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onRequestSettings, Qt::QueuedConnection );\r\n    connect( this, &SettingsProxy::signalSetUIScale, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetUIScale, Qt::QueuedConnection );\r\n    connect( this, &SettingsProxy::signalSetKeyboardSpeed, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetKeyboardSpeed, Qt::QueuedConnection );\r\n    connect( this, &SettingsProxy::signalSetFullScreen, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetFullScreen, Qt::QueuedConnection );\r\n    connect( this, &SettingsProxy::signalSetLanguage, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetLanguage, Qt::QueuedConnection );\r\n    connect( this, &SettingsProxy::signalSetLightMin, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetLightMin, Qt::QueuedConnection );\r\n    connect( this, &SettingsProxy::signalSetToggleMouseWheel, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetToggleMouseWheel, Qt::QueuedConnection );\r\n\t connect( this, &SettingsProxy::signalSetAudioMasterVolume, Global::eventConnector->aggregatorSettings(), &AggregatorSettings::onSetAudioMasterVolume, Qt::QueuedConnection );\r\n    \r\n    connect( Global::eventConnector->aggregatorSettings(), &AggregatorSettings::signalUpdateSettings, this, &SettingsProxy::onSettings, Qt::QueuedConnection );\r\n}\r\n\r\nvoid SettingsProxy::setParent( IngnomiaGUI::SettingsModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid SettingsProxy::requestSettings()\r\n{\r\n    emit signalRequestSettings();\r\n}\r\n\r\nvoid SettingsProxy::onSettings( const GuiSettings& settings )\r\n{\r\n    if ( m_parent )\r\n\t{\r\n        m_parent->updateSettings( settings );\r\n\t}\r\n}\r\n\r\nvoid SettingsProxy::setLanguage( QString language )\r\n{\r\n    emit signalSetLanguage( language );\r\n}\r\n    \r\nvoid SettingsProxy::setUIScale( float scale )\r\n{\r\n    emit signalSetUIScale( scale );\r\n}\r\n\r\nvoid SettingsProxy::setFullScreen( bool value )\r\n{\r\n    emit signalSetFullScreen( value );\r\n}\r\n\r\nvoid SettingsProxy::setKeyboardSpeed( int value )\r\n{\r\n    emit signalSetKeyboardSpeed( value );\r\n}\r\n\r\nvoid SettingsProxy::setLightMin( int value )\r\n{\r\n    emit signalSetLightMin( value );\r\n}\r\n\r\nvoid SettingsProxy::setToggleMouseWheel( bool value )\r\n{\r\n    emit signalSetToggleMouseWheel( value );\r\n}\r\n\r\nvoid SettingsProxy::setAudioMasterVolume( float value )\r\n{\r\n    emit signalSetAudioMasterVolume( value );\r\n}"
  },
  {
    "path": "src/gui/xaml/settingsproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n//#include \"../aggregatorsettings.h\"\r\n#include \"SettingsModel.h\"\r\n#include \"../aggregatorsettings.h\"\r\n\r\n#include <QObject>\r\n\r\nclass SettingsProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tSettingsProxy( QObject* parent = nullptr );\r\n\tvoid setParent( IngnomiaGUI::SettingsModel* parent );\r\n\r\n\tvoid requestSettings();\r\n\r\n    void setLanguage( QString language );\r\n    void setUIScale( float scale );\r\n    void setFullScreen( bool value );\r\n    void setKeyboardSpeed( int value );\r\n    void setLightMin( int value );\r\n    void setToggleMouseWheel( bool value );\r\n\tvoid setAudioMasterVolume( float value );\r\n\r\nprivate:\r\n\tIngnomiaGUI::SettingsModel* m_parent = nullptr;\r\n\r\n\r\n\r\nprivate slots:\r\n\tvoid onSettings( const GuiSettings& settings );\r\n\r\nsignals:\r\n\tvoid signalRequestSettings();\r\n\r\n    void signalSetLanguage( QString language );\r\n    void signalSetUIScale( float scale );\r\n    void signalSetFullScreen( bool value );\r\n    void signalSetKeyboardSpeed( int value );\r\n    void signalSetLightMin( int value );\r\n    void signalSetToggleMouseWheel( bool value );\r\n\tvoid signalSetAudioMasterVolume( float value );\r\n};\r\n"
  },
  {
    "path": "src/gui/xaml/stockpilegui.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"stockpilegui.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nStockpileGui::StockpileGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &StockpileGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid StockpileGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"StockpileGui.xaml\" );\r\n}\r\n\r\nbool StockpileGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid StockpileGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::StockpileGui, \"IngnomiaGUI.StockpileGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/stockpilegui.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __StockpileGui_H__\r\n#define __StockpileGui_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass StockpileGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tStockpileGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( StockpileGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/workshopgui.xaml.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"workshopgui.xaml.h\"\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWorkshopGui::WorkshopGui()\r\n{\r\n\tLoaded() += MakeDelegate( this, &WorkshopGui::OnLoaded );\r\n\tInitializeComponent();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nvoid WorkshopGui::InitializeComponent()\r\n{\r\n\tGUI::LoadComponent( this, \"WorkshopGui.xaml\" );\r\n}\r\n\r\nbool WorkshopGui::ConnectEvent( BaseComponent* source, const char* event, const char* handler )\r\n{\r\n\treturn false;\r\n}\r\n\r\nvoid WorkshopGui::OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& )\r\n{\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION_( IngnomiaGUI::WorkshopGui, \"IngnomiaGUI.WorkshopGui\" )\r\n"
  },
  {
    "path": "src/gui/xaml/workshopgui.xaml.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#ifndef __WorkshopGui_H__\r\n#define __WorkshopGui_H__\r\n\r\n#include <NoesisPCH.h>\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WorkshopGui final : public Noesis::UserControl\r\n{\r\npublic:\r\n\tWorkshopGui();\r\n\r\nprivate:\r\n\tvoid InitializeComponent();\r\n\r\n\tbool ConnectEvent( BaseComponent* source, const char* event, const char* handler ) override;\r\n\r\n\tvoid OnLoaded( Noesis::BaseComponent*, const Noesis::RoutedEventArgs& );\r\n\r\n\tNS_DECLARE_REFLECTION( WorkshopGui, UserControl )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/workshopmodel.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"workshopmodel.h\"\r\n\r\n#include \"../strings.h\"\r\n#include \"workshopproxy.h\"\r\n\r\n#include <NsApp/Application.h>\r\n#include <NsCore/Log.h>\r\n#include <NsCore/ReflectionImplement.h>\r\n#include <NsCore/ReflectionImplementEnum.h>\r\n#include <NsGui/ObservableCollection.h>\r\n#include <NsGui/UIElement.h>\r\n\r\n#include <QDebug>\r\n\r\nusing namespace IngnomiaGUI;\r\nusing namespace Noesis;\r\nusing namespace NoesisApp;\r\n\r\n#pragma region WsPriority\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWsPriority::WsPriority( const char* name ) :\r\n\t_name( name )\r\n{\r\n}\r\n\r\nconst char* WsPriority::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n#pragma endregion WsPriority\r\n\r\n#pragma region RecipeTab\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWsAvailableMaterial::WsAvailableMaterial( QString sid, int amount, QString item )\r\n{\r\n\t_name   = ( S::s( \"$MaterialName_\" + sid ) + \" \" + S::s( \"$ItemName_\" + item ) ).toStdString().c_str();\r\n\t_sid    = sid.toStdString().c_str();\r\n\t_amount = QString::number( amount ).toStdString().c_str();\r\n}\r\n\r\nconst char* WsAvailableMaterial::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst char* WsAvailableMaterial::sid() const\r\n{\r\n\treturn _sid.Str();\r\n}\r\n\r\nconst char* WsAvailableMaterial::amount() const\r\n{\r\n\treturn _amount.Str();\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWsRequiredItem::WsRequiredItem( GuiWorkshopComponent gwc )\r\n{\r\n\t_name   = S::s( \"$ItemName_\" + gwc.sid ).toStdString().c_str();\r\n\t_sid    = gwc.sid;\r\n\t_amount = QString::number( gwc.amount ).toStdString().c_str();\r\n\r\n\t_availableMaterials = *new Noesis::ObservableCollection<WsAvailableMaterial>();\r\n\r\n\tfor ( auto mat : gwc.materials )\r\n\t{\r\n\t\t_availableMaterials->Add( MakePtr<WsAvailableMaterial>( mat.sid, mat.amount, _sid ) );\r\n\t}\r\n\r\n\tSetSelectedMaterial( _availableMaterials->Get( 0 ) );\r\n}\r\n\r\nconst char* WsRequiredItem::GetName() const\r\n{\r\n\treturn _name.Str();\r\n}\r\n\r\nconst QString WsRequiredItem::sid()\r\n{\r\n\treturn _sid;\r\n}\r\n\r\nconst char* WsRequiredItem::amount() const\r\n{\r\n\treturn _amount.Str();\r\n}\r\n\r\nNoesis::ObservableCollection<WsAvailableMaterial>* WsRequiredItem::availableMaterials() const\r\n{\r\n\treturn _availableMaterials;\r\n}\r\n\r\nvoid WsRequiredItem::SetSelectedMaterial( WsAvailableMaterial* mat )\r\n{\r\n\tif ( _selectedMaterial != mat )\r\n\t{\r\n\t\t_selectedMaterial = mat;\r\n\t\tOnPropertyChanged( \"SelectedMaterial\" );\r\n\t}\r\n}\r\n\r\nWsAvailableMaterial* WsRequiredItem::GetSelectedMaterial() const\r\n{\r\n\treturn _selectedMaterial;\r\n}\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWsProduct::WsProduct( GuiWorkshopProduct gwp, WorkshopProxy* proxy ) :\r\n\tm_proxy( proxy )\r\n{\r\n\tm_name        = S::s( \"$CraftName_\" + gwp.sid ).toStdString().c_str();\r\n\tm_sid         = gwp.sid;\r\n\tm_craftNumber = \"1\";\r\n\t_cmdBuild.SetExecuteFunc( MakeDelegate( this, &WsProduct::onCmdBuild ) );\r\n\r\n\t_requiredItems = *new Noesis::ObservableCollection<WsRequiredItem>();\r\n\r\n\tfor ( auto gwc : gwp.components )\r\n\t{\r\n\t\t_requiredItems->Add( MakePtr<WsRequiredItem>( gwc ) );\r\n\t}\r\n}\r\n\r\nconst char* WsProduct::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nQString WsProduct::sid() const\r\n{\r\n\treturn m_sid;\r\n}\r\n\r\nNoesis::ObservableCollection<WsRequiredItem>* WsProduct::requiredItems() const\r\n{\r\n\treturn _requiredItems;\r\n}\r\n\r\nconst NoesisApp::DelegateCommand* WsProduct::GetCmdBuild() const\r\n{\r\n\treturn &_cmdBuild;\r\n}\r\n\r\nvoid WsProduct::onCmdBuild( BaseComponent* param )\r\n{\r\n\tQStringList mats;\r\n\tfor ( int i = 0; i < _requiredItems->Count(); ++i )\r\n\t{\r\n\t\tauto item = _requiredItems->Get( i );\r\n\t\tauto mat  = item->GetSelectedMaterial();\r\n\t\tmats.append( mat->sid() );\r\n\t}\r\n\tQString num( m_craftNumber.Str() );\r\n\r\n\tbool ok;\r\n\tint number = num.toInt( &ok );\r\n\tif ( !ok )\r\n\t\tnumber = 1;\r\n\tm_proxy->craftItem( m_sid, m_mode, number, mats );\r\n}\r\n\r\nint WsProduct::GetMode() const\r\n{\r\n\treturn m_mode;\r\n}\r\n\r\nvoid WsProduct::SetMode( int mode )\r\n{\r\n\tif ( m_mode != mode )\r\n\t{\r\n\t\tm_mode = mode;\r\n\t\tOnPropertyChanged( \"Mode\" );\r\n\t}\r\n}\r\n\r\nconst char* WsProduct::GetCraftNumber() const\r\n{\r\n\treturn m_craftNumber.Str();\r\n}\r\n\r\nvoid WsProduct::SetCraftNumber( const char* value )\r\n{\r\n\tif ( m_craftNumber != value )\r\n\t{\r\n\t\tm_craftNumber = value;\r\n\t\tOnPropertyChanged( \"CraftNumber\" );\r\n\t}\r\n}\r\n#pragma endregion RecipeTab\r\n\r\n#pragma region CraftingListTab\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWsCraftJob::WsCraftJob( CraftJob cj, WorkshopProxy* proxy ) :\r\n\tm_proxy( proxy )\r\n{\r\n\t//\r\n\tif ( cj.requiredItems.size() )\r\n\t{\r\n\t\tm_name = ( S::s( \"$MaterialName_\" + cj.requiredItems.first().materialSID ) + \" \" + S::s( \"$ItemName_\" + cj.itemSID ) ).toStdString().c_str();\r\n\t}\r\n\telse\r\n\t{\r\n\t\tm_name = S::s( \"$CraftName_\" + cj.craftID ).toStdString().c_str();\r\n\t}\r\n\r\n\tm_craftJobID  = cj.id;\r\n\tm_sid         = cj.craftID;\r\n\tm_craftNumber = QString::number( cj.numItemsToCraft ).toStdString().c_str();\r\n\tm_mode        = (int)cj.mode;\r\n\tm_suspended   = cj.paused;\r\n\tm_moveBack    = cj.moveToBackWhenDone;\r\n\r\n\t_buttonCmd.SetExecuteFunc( MakeDelegate( this, &WsCraftJob::onButtonCmd ) );\r\n}\r\n\r\nconst char* WsCraftJob::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nQString WsCraftJob::sid() const\r\n{\r\n\treturn m_sid;\r\n}\r\n\r\nint WsCraftJob::GetMode() const\r\n{\r\n\treturn m_mode;\r\n}\r\n\r\nvoid WsCraftJob::SetMode( int mode )\r\n{\r\n\tif ( m_mode != mode )\r\n\t{\r\n\t\tm_mode = mode;\r\n\t\tm_proxy->craftJobParams( m_craftJobID, m_mode, m_craftNumber.Str(), m_suspended, m_moveBack );\r\n\t\tOnPropertyChanged( \"Mode\" );\r\n\t}\r\n}\r\n\r\nconst char* WsCraftJob::GetCraftNumber() const\r\n{\r\n\treturn m_craftNumber.Str();\r\n}\r\n\r\nvoid WsCraftJob::SetCraftNumber( const char* value )\r\n{\r\n\tif ( m_craftNumber != value )\r\n\t{\r\n\t\tm_craftNumber = value;\r\n\t\tm_proxy->craftJobParams( m_craftJobID, m_mode, m_craftNumber.Str(), m_suspended, m_moveBack );\r\n\t\tOnPropertyChanged( \"CraftNumber\" );\r\n\t}\r\n}\r\n\r\nbool WsCraftJob::GetSuspended() const\r\n{\r\n\treturn m_suspended;\r\n}\r\n\r\nvoid WsCraftJob::SetSuspended( bool value )\r\n{\r\n\tif ( m_suspended != value )\r\n\t{\r\n\t\tm_suspended = value;\r\n\t\tm_proxy->craftJobParams( m_craftJobID, m_mode, m_craftNumber.Str(), m_suspended, m_moveBack );\r\n\t\tOnPropertyChanged( \"Suspended\" );\r\n\t}\r\n}\r\n\r\nbool WsCraftJob::GetMoveBack() const\r\n{\r\n\treturn m_moveBack;\r\n}\r\n\r\nvoid WsCraftJob::SetMoveBack( bool value )\r\n{\r\n\tif ( m_moveBack != value )\r\n\t{\r\n\t\tm_moveBack = value;\r\n\t\tm_proxy->craftJobParams( m_craftJobID, m_mode, m_craftNumber.Str(), m_suspended, m_moveBack );\r\n\t\tOnPropertyChanged( \"MoveBack\" );\r\n\t}\r\n}\r\n\r\nvoid WsCraftJob::onButtonCmd( BaseComponent* param )\r\n{\r\n\tif ( param )\r\n\t{\r\n\t\tm_proxy->craftJobCommand( m_craftJobID, param->ToString().Str() );\r\n\t}\r\n}\r\n\r\n#pragma endregion CraftingListTab\r\n\r\n#pragma region TradeItems\r\n\r\nWsTradeItem::WsTradeItem( QString name, QString itemSID, QString materialSID, unsigned char quality, int count ) :\r\n\tm_name( name.toStdString().c_str() ),\r\n\tm_itemSID( itemSID ),\r\n\tm_materialSID( materialSID ),\r\n\tm_quality( quality ),\r\n\tm_count( count ),\r\n\tm_countString( QString::number( count ).toStdString().c_str() )\r\n{\r\n}\r\n\r\nconst char* WsTradeItem::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nconst char* WsTradeItem::GetCount() const\r\n{\r\n\treturn m_countString.Str();\r\n}\r\n\r\nvoid WsTradeItem::SetCount( int count )\r\n{\r\n\tm_count       = count;\r\n\tm_countString = QString::number( count ).toStdString().c_str();\r\n\tOnPropertyChanged( \"Count\" );\r\n}\r\n\r\n#pragma endregion TradeItems\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nWorkshopModel::WorkshopModel()\r\n{\r\n\tm_proxy = new WorkshopProxy;\r\n\tm_proxy->setParent( this );\r\n\r\n\tm_prios = *new ObservableCollection<WsPriority>();\r\n\tfor ( int i = 0; i < 2; ++i )\r\n\t{\r\n\t\tm_prios->Add( MakePtr<WsPriority>( ( QString( \"Priority \" ) + QString::number( i + 1 ) ).toStdString().c_str() ) );\r\n\t}\r\n\tSetSelectedPriority( m_prios->Get( 0 ) );\r\n\r\n\tm_products = *new ObservableCollection<WsProduct>();\r\n\tm_jobs     = *new ObservableCollection<WsCraftJob>();\r\n\r\n\tm_traderStock = *new ObservableCollection<WsTradeItem>();\r\n\tm_traderOffer = *new ObservableCollection<WsTradeItem>();\r\n\tm_playerStock = *new ObservableCollection<WsTradeItem>();\r\n\tm_playerOffer = *new ObservableCollection<WsTradeItem>();\r\n\r\n\tm_transferCmd.SetExecuteFunc( MakeDelegate( this, &WorkshopModel::onTransferCmd ) );\r\n\tm_tradeCmd.SetExecuteFunc( MakeDelegate( this, &WorkshopModel::onTradeCmd ) );\r\n}\r\n\r\nvoid WorkshopModel::onUpdateInfo( const GuiWorkshopInfo& info )\r\n{\r\n\tbool isSameWorkshop = ( m_workshopID == info.workshopID );\r\n\tm_workshopID        = info.workshopID;\r\n\tm_gui               = info.gui;\r\n\t\r\n\tm_proxy->blockWriteBack();\r\n\t\r\n\tSetName( info.name.toStdString().c_str() );\r\n\tSetSuspended( info.suspended );\r\n\tSetLinkStockpile( info.linkStockpile );\r\n\r\n\tm_prios->Clear();\r\n\tfor ( int i = 0; i < info.maxPriority; ++i )\r\n\t{\r\n\t\tm_prios->Add( MakePtr<WsPriority>( ( QString( \"Priority \" ) + QString::number( i + 1 ) ).toStdString().c_str() ) );\r\n\t}\r\n\tSetSelectedPriority( m_prios->Get( qMin( qMax( 0, info.priority ), m_prios->Count() ) ) );\r\n\r\n\tif ( m_gui.isEmpty() )\r\n\t{\r\n\t\tSetAcceptGenerated( info.acceptGenerated );\r\n\t\tSetAutoCraftMissing( info.autoCraftMissing );\r\n\r\n\t\tm_products->Clear();\r\n\t\tfor ( auto gwp : info.products )\r\n\t\t{\r\n\t\t\tm_products->Add( MakePtr<WsProduct>( gwp, m_proxy ) );\r\n\t\t}\r\n\t\tOnPropertyChanged( \"Products\" );\r\n\r\n\t\tm_jobs->Clear();\r\n\t\tfor ( auto cj : info.jobList )\r\n\t\t{\r\n\t\t\tm_jobs->Add( MakePtr<WsCraftJob>( cj, m_proxy ) );\r\n\t\t}\r\n\r\n\t\tOnPropertyChanged( \"Jobs\" );\r\n\t}\r\n\telse if ( m_gui == \"Butcher\" )\r\n\t{\r\n\t\tm_butcherCorpses = info.butcherCorpses;\r\n\t\tm_butcherExcess  = info.butcherExcess;\r\n\t}\r\n\telse if ( m_gui == \"Trader\" )\r\n\t{\r\n\t\tm_selectedTraderStock = nullptr;\r\n\t\tm_selectedTraderOffer = nullptr;\r\n\t\tm_selectedPlayerStock = nullptr;\r\n\t\tm_selectedPlayerOffer = nullptr;\r\n\t\tm_proxy->requestAllTradeItems( m_workshopID );\r\n\t}\r\n\telse if ( m_gui == \"Fishery\" )\r\n\t{\r\n\t\tm_catchFish   = info.catchFish;\r\n\t\tm_processFish = info.processFish;\r\n\t}\r\n\tqDebug() << m_gui;\r\n\r\n\tm_proxy->unblockWriteBack();\r\n\r\n\tOnPropertyChanged( \"Priorities\" );\r\n\tOnPropertyChanged( \"SelectedPrio\" );\r\n\r\n\tOnPropertyChanged( \"NormalGui\" );\r\n\tOnPropertyChanged( \"ButcherGui\" );\r\n\tOnPropertyChanged( \"TraderGui\" );\r\n\tOnPropertyChanged( \"FisherGui\" );\r\n\r\n\tOnPropertyChanged( \"ButcherExcess\" );\r\n\tOnPropertyChanged( \"ButcherCorpses\" );\r\n\tOnPropertyChanged( \"CatchFish\" );\r\n\tOnPropertyChanged( \"ProcessFish\" );\r\n\r\n\tm_proxy->unblockWriteBack();\r\n}\r\n\r\nvoid WorkshopModel::onUpdateCraftList( const GuiWorkshopInfo& info )\r\n{\r\n\tbool isSameWorkshop = ( m_workshopID == info.workshopID );\r\n\tif ( isSameWorkshop )\r\n\t{\r\n\t\tm_jobs->Clear();\r\n\t\tfor ( auto cj : info.jobList )\r\n\t\t{\r\n\t\t\tm_jobs->Add( MakePtr<WsCraftJob>( cj, m_proxy ) );\r\n\t\t}\r\n\t\tOnPropertyChanged( \"Jobs\" );\r\n\t}\r\n}\r\n\r\nbool WorkshopModel::GetSuspended() const\r\n{\r\n\treturn m_suspended;\r\n}\r\n\r\nvoid WorkshopModel::SetSuspended( bool value )\r\n{\r\n\tif ( m_suspended != value )\r\n\t{\r\n\t\tm_suspended = value;\r\n\t\tm_proxy->setBasicOptions( m_workshopID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_acceptGenerated, m_autoCraftMissing, m_connectStockpile );\r\n\t\tOnPropertyChanged( \"Suspended\" );\r\n\t}\r\n}\r\n\r\nNoesis::ObservableCollection<WsPriority>* WorkshopModel::GetPrios() const\r\n{\r\n\treturn m_prios;\r\n}\r\n\r\nvoid WorkshopModel::SetSelectedPriority( WsPriority* prio )\r\n{\r\n\tif ( m_selectedPrio != prio )\r\n\t{\r\n\t\tm_selectedPrio = prio;\r\n\t\tm_proxy->setBasicOptions( m_workshopID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_acceptGenerated, m_autoCraftMissing, m_connectStockpile );\r\n\t\tOnPropertyChanged( \"SelectedPrio\" );\r\n\t}\r\n}\r\n\r\nWsPriority* WorkshopModel::GetSelectedPriority() const\r\n{\r\n\treturn m_selectedPrio;\r\n}\r\n\r\nconst char* WorkshopModel::GetNormalVisible() const\r\n{\r\n\tif ( m_gui.isEmpty() )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* WorkshopModel::GetButcherVisible() const\r\n{\r\n\tif ( m_gui == \"Butcher\" )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* WorkshopModel::GetTraderVisible() const\r\n{\r\n\tif ( m_gui == \"Trader\" )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nconst char* WorkshopModel::GetFisherVisible() const\r\n{\r\n\tif ( m_gui == \"Fishery\" )\r\n\t{\r\n\t\treturn \"Visible\";\r\n\t}\r\n\treturn \"Collapsed\";\r\n}\r\n\r\nbool WorkshopModel::GetAutoCraftMissing() const\r\n{\r\n\treturn m_autoCraftMissing;\r\n}\r\n\r\nvoid WorkshopModel::SetAutoCraftMissing( bool value )\r\n{\r\n\tif ( m_autoCraftMissing != value )\r\n\t{\r\n\t\tm_autoCraftMissing = value;\r\n\t\tm_proxy->setBasicOptions( m_workshopID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_acceptGenerated, m_autoCraftMissing, m_connectStockpile );\r\n\t\tOnPropertyChanged( \"AutoCraft\" );\r\n\t}\r\n}\r\n\r\nbool WorkshopModel::GetAcceptGenerated() const\r\n{\r\n\treturn m_acceptGenerated;\r\n}\r\n\r\nvoid WorkshopModel::SetAcceptGenerated( bool value )\r\n{\r\n\tif ( m_acceptGenerated != value )\r\n\t{\r\n\t\tm_acceptGenerated = value;\r\n\t\tm_proxy->setBasicOptions( m_workshopID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_acceptGenerated, m_autoCraftMissing, m_connectStockpile );\r\n\t\tOnPropertyChanged( \"AcceptGenerated\" );\r\n\t}\r\n}\r\n\r\nbool WorkshopModel::GetLinkStockpile() const\r\n{\r\n\treturn m_connectStockpile;\r\n}\r\n\r\nvoid WorkshopModel::SetLinkStockpile( bool value )\r\n{\r\n\tif ( m_connectStockpile != value )\r\n\t{\r\n\t\tm_connectStockpile = value;\r\n\t\tm_proxy->setBasicOptions( m_workshopID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_acceptGenerated, m_autoCraftMissing, m_connectStockpile );\r\n\t\tOnPropertyChanged( \"LinkStockpile\" );\r\n\t}\r\n}\r\n\r\nconst char* WorkshopModel::GetName() const\r\n{\r\n\treturn m_name.Str();\r\n}\r\n\r\nvoid WorkshopModel::SetName( const char* value )\r\n{\r\n\tm_name = value;\r\n\r\n\tm_proxy->setBasicOptions( m_workshopID, m_name.Str(), m_prios->IndexOf( m_selectedPrio ), m_suspended, m_acceptGenerated, m_autoCraftMissing, m_connectStockpile );\r\n\tOnPropertyChanged( \"Name\" );\r\n}\r\n\r\n#pragma region ButcherSpecific\r\n\r\nbool WorkshopModel::GetButcherExcess() const\r\n{\r\n\treturn m_butcherExcess;\r\n}\r\n\r\nvoid WorkshopModel::SetButcherExcess( bool value )\r\n{\r\n\tif ( m_butcherExcess != value )\r\n\t{\r\n\t\tm_butcherExcess = value;\r\n\t\tm_proxy->setButcherOptions( m_workshopID, m_butcherCorpses, m_butcherExcess );\r\n\t}\r\n}\r\n\r\nbool WorkshopModel::GetButcherCorpses() const\r\n{\r\n\treturn m_butcherCorpses;\r\n}\r\n\r\nvoid WorkshopModel::SetButcherCorpses( bool value )\r\n{\r\n\tif ( m_butcherCorpses != value )\r\n\t{\r\n\t\tm_butcherCorpses = value;\r\n\t\tm_proxy->setButcherOptions( m_workshopID, m_butcherCorpses, m_butcherExcess );\r\n\t}\r\n}\r\n#pragma endregion ButcherSpecific\r\n\r\nbool WorkshopModel::GetCatchFish() const\r\n{\r\n\treturn m_catchFish;\r\n}\r\n\r\nvoid WorkshopModel::SetCatchFish( bool value )\r\n{\r\n\tif ( m_catchFish != value )\r\n\t{\r\n\t\tm_catchFish = value;\r\n\t\tm_proxy->setFisherOptions( m_workshopID, m_catchFish, m_processFish );\r\n\t}\r\n}\r\n\r\nbool WorkshopModel::GetProcessFish() const\r\n{\r\n\treturn m_processFish;\r\n}\r\n\r\nvoid WorkshopModel::SetProcessFish( bool value )\r\n{\r\n\tif ( m_processFish != value )\r\n\t{\r\n\t\tm_processFish = value;\r\n\t\tm_proxy->setFisherOptions( m_workshopID, m_catchFish, m_processFish );\r\n\t}\r\n}\r\n\r\n#pragma region TraderSpecific\r\nvoid WorkshopModel::updateTraderStock( const QList<GuiTradeItem>& items )\r\n{\r\n\tm_traderStock->Clear();\r\n\r\n\tfor ( const auto& item : items )\r\n\t{\r\n\t\tif ( item.count - item.reserved > 0 )\r\n\t\t{\r\n\t\t\tm_traderStock->Add( MakePtr<WsTradeItem>( item.name, item.itemSID, item.materialSIDorGender, item.quality, item.count - item.reserved ) );\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"TraderStock\" );\r\n\r\n\tm_traderOffer->Clear();\r\n\r\n\tfor ( const auto& item : items )\r\n\t{\r\n\t\tif ( item.reserved > 0 )\r\n\t\t{\r\n\t\t\tm_traderOffer->Add( MakePtr<WsTradeItem>( item.name, item.itemSID, item.materialSIDorGender, item.quality, item.reserved ) );\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"TraderOffer\" );\r\n}\r\n\r\nvoid WorkshopModel::updatePlayerStock( const QList<GuiTradeItem>& items )\r\n{\r\n\tm_playerStock->Clear();\r\n\r\n\tfor ( const auto& item : items )\r\n\t{\r\n\t\tm_playerStock->Add( MakePtr<WsTradeItem>( item.name, item.itemSID, item.materialSIDorGender, item.quality, item.count ) );\r\n\t}\r\n\tOnPropertyChanged( \"PlayerStock\" );\r\n\r\n\tm_playerOffer->Clear();\r\n\r\n\tfor ( const auto& item : items )\r\n\t{\r\n\t\tif ( item.reserved > 0 )\r\n\t\t{\r\n\t\t\tm_playerOffer->Add( MakePtr<WsTradeItem>( item.name, item.itemSID, item.materialSIDorGender, item.quality, item.reserved ) );\r\n\t\t}\r\n\t}\r\n\tOnPropertyChanged( \"PlayerOffer\" );\r\n}\r\n\r\nvoid WorkshopModel::updateTraderStockItem( const GuiTradeItem& gti )\r\n{\r\n\tfor ( int i = 0; i < m_traderStock->Count(); ++i )\r\n\t{\r\n\t\tauto item = m_traderStock->Get( i );\r\n\t\tif ( item->m_itemSID == gti.itemSID && item->m_materialSID == gti.materialSIDorGender && item->m_quality == gti.quality )\r\n\t\t{\r\n\t\t\titem->SetCount( gti.count - gti.reserved );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tbool found = false;\r\n\tfor ( int i = 0; i < m_traderOffer->Count(); ++i )\r\n\t{\r\n\t\tauto item = m_traderOffer->Get( i );\r\n\r\n\t\tif ( item->m_itemSID == gti.itemSID && item->m_materialSID == gti.materialSIDorGender && item->m_quality == gti.quality )\r\n\t\t{\r\n\t\t\tfound = true;\r\n\t\t\tif ( gti.reserved > 0 )\r\n\t\t\t{\r\n\t\t\t\titem->SetCount( gti.reserved );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_traderOffer->RemoveAt( i );\r\n\t\t\t\tOnPropertyChanged( \"TraderOffer\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( !found )\r\n\t{\r\n\t\tm_traderOffer->Add( MakePtr<WsTradeItem>( gti.name, gti.itemSID, gti.materialSIDorGender, gti.quality, gti.reserved ) );\r\n\t\tOnPropertyChanged( \"TraderOffer\" );\r\n\t}\r\n}\r\n\r\nvoid WorkshopModel::updatePlayerStockItem( const GuiTradeItem& gti )\r\n{\r\n\tfor ( int i = 0; i < m_playerStock->Count(); ++i )\r\n\t{\r\n\t\tauto item = m_playerStock->Get( i );\r\n\t\tif ( item->m_itemSID == gti.itemSID && item->m_materialSID == gti.materialSIDorGender && item->m_quality == gti.quality )\r\n\t\t{\r\n\t\t\titem->SetCount( gti.count - gti.reserved );\r\n\t\t\tbreak;\r\n\t\t}\r\n\t}\r\n\tbool found = false;\r\n\tfor ( int i = 0; i < m_playerOffer->Count(); ++i )\r\n\t{\r\n\t\tauto item = m_playerOffer->Get( i );\r\n\r\n\t\tif ( item->m_itemSID == gti.itemSID && item->m_materialSID == gti.materialSIDorGender && item->m_quality == gti.quality )\r\n\t\t{\r\n\t\t\tfound = true;\r\n\t\t\tif ( gti.reserved > 0 )\r\n\t\t\t{\r\n\t\t\t\titem->SetCount( gti.reserved );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tm_playerOffer->RemoveAt( i );\r\n\t\t\t\tOnPropertyChanged( \"PlayerOffer\" );\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tif ( !found )\r\n\t{\r\n\t\tm_playerOffer->Add( MakePtr<WsTradeItem>( gti.name, gti.itemSID, gti.materialSIDorGender, gti.quality, gti.reserved ) );\r\n\t\tOnPropertyChanged( \"PlayerOffer\" );\r\n\t}\r\n}\r\n\r\nvoid WorkshopModel::SetSelectedTraderStock( WsTradeItem* item )\r\n{\r\n\tif ( m_selectedTraderStock != item )\r\n\t{\r\n\t\tm_selectedTraderStock = item;\r\n\t\tOnPropertyChanged( \"SelectedTraderStock\" );\r\n\t}\r\n}\r\n\r\nWsTradeItem* WorkshopModel::GetSelectedTraderStock() const\r\n{\r\n\treturn m_selectedTraderStock;\r\n}\r\n\r\nvoid WorkshopModel::SetSelectedTraderOffer( WsTradeItem* item )\r\n{\r\n\tif ( m_selectedTraderOffer != item )\r\n\t{\r\n\t\tm_selectedTraderOffer = item;\r\n\t\tOnPropertyChanged( \"SelectedTraderOffer\" );\r\n\t}\r\n}\r\n\r\nWsTradeItem* WorkshopModel::GetSelectedTraderOffer() const\r\n{\r\n\treturn m_selectedTraderOffer;\r\n}\r\n\r\nvoid WorkshopModel::SetSelectedPlayerStock( WsTradeItem* item )\r\n{\r\n\tif ( m_selectedPlayerStock != item )\r\n\t{\r\n\t\tm_selectedPlayerStock = item;\r\n\t\tOnPropertyChanged( \"SelectedPlayerStock\" );\r\n\t}\r\n}\r\n\r\nWsTradeItem* WorkshopModel::GetSelectedPlayerStock() const\r\n{\r\n\treturn m_selectedPlayerStock;\r\n}\r\n\r\nvoid WorkshopModel::SetSelectedPlayerOffer( WsTradeItem* item )\r\n{\r\n\tif ( m_selectedPlayerOffer != item )\r\n\t{\r\n\t\tm_selectedPlayerOffer = item;\r\n\t\tOnPropertyChanged( \"SelectedPlayerOffer\" );\r\n\t}\r\n}\r\n\r\nWsTradeItem* WorkshopModel::GetSelectedPlayerOffer() const\r\n{\r\n\treturn m_selectedPlayerOffer;\r\n}\r\n\r\nbool WorkshopModel::GetAmount1Checked() const\r\n{\r\n\tif ( m_amountToTransfer == CheckedAmount::Amount1 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool WorkshopModel::GetAmount10Checked() const\r\n{\r\n\tif ( m_amountToTransfer == CheckedAmount::Amount10 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool WorkshopModel::GetAmount100Checked() const\r\n{\r\n\tif ( m_amountToTransfer == CheckedAmount::Amount100 )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nbool WorkshopModel::GetAmountAllChecked() const\r\n{\r\n\tif ( m_amountToTransfer == CheckedAmount::AmountAll )\r\n\t{\r\n\t\treturn true;\r\n\t}\r\n\treturn false;\r\n}\r\n\r\nvoid IngnomiaGUI::WorkshopModel::SetAmount1Checked( bool checked )\r\n{\r\n\tm_amountToTransfer = CheckedAmount::Amount1;\r\n\tOnPropertyChanged( \"Amount1\" );\r\n\tOnPropertyChanged( \"Amount10\" );\r\n\tOnPropertyChanged( \"Amount100\" );\r\n\tOnPropertyChanged( \"AmountAll\" );\r\n}\r\n\r\nvoid IngnomiaGUI::WorkshopModel::SetAmount10Checked( bool checked )\r\n{\r\n\tm_amountToTransfer = CheckedAmount::Amount10;\r\n\tOnPropertyChanged( \"Amount1\" );\r\n\tOnPropertyChanged( \"Amount10\" );\r\n\tOnPropertyChanged( \"Amount100\" );\r\n\tOnPropertyChanged( \"AmountAll\" );\r\n}\r\n\r\nvoid IngnomiaGUI::WorkshopModel::SetAmount100Checked( bool checked )\r\n{\r\n\tm_amountToTransfer = CheckedAmount::Amount100;\r\n\tOnPropertyChanged( \"Amount1\" );\r\n\tOnPropertyChanged( \"Amount10\" );\r\n\tOnPropertyChanged( \"Amount100\" );\r\n\tOnPropertyChanged( \"AmountAll\" );\r\n}\r\n\r\nvoid IngnomiaGUI::WorkshopModel::SetAmountAllChecked( bool checked )\r\n{\r\n\tm_amountToTransfer = CheckedAmount::AmountAll;\r\n\tOnPropertyChanged( \"Amount1\" );\r\n\tOnPropertyChanged( \"Amount10\" );\r\n\tOnPropertyChanged( \"Amount100\" );\r\n\tOnPropertyChanged( \"AmountAll\" );\r\n}\r\n\r\nvoid WorkshopModel::onTransferCmd( BaseComponent* param )\r\n{\r\n\tQString qParam = param->ToString().Str();\r\n\tint amount     = 0;\r\n\tswitch ( m_amountToTransfer )\r\n\t{\r\n\t\tcase CheckedAmount::Amount1:\r\n\t\t\tamount = 1;\r\n\t\t\tbreak;\r\n\t\tcase CheckedAmount::Amount10:\r\n\t\t\tamount = 10;\r\n\t\t\tbreak;\r\n\t\tcase CheckedAmount::Amount100:\r\n\t\t\tamount = 100;\r\n\t\t\tbreak;\r\n\t\tcase CheckedAmount::AmountAll:\r\n\t\t\tamount = -1;\r\n\t\t\tbreak;\r\n\t}\r\n\r\n\tif ( qParam == \"TraderLeft\" )\r\n\t{\r\n\t\tif ( m_selectedTraderOffer )\r\n\t\t{\r\n\t\t\tm_proxy->traderOffertoStock( m_workshopID, m_selectedTraderOffer->m_itemSID, m_selectedTraderOffer->m_materialSID, m_selectedTraderOffer->m_quality, amount );\r\n\t\t}\r\n\t}\r\n\telse if ( qParam == \"TraderRight\" )\r\n\t{\r\n\t\tif ( m_selectedTraderStock )\r\n\t\t{\r\n\t\t\tm_proxy->traderStocktoOffer( m_workshopID, m_selectedTraderStock->m_itemSID, m_selectedTraderStock->m_materialSID, m_selectedTraderStock->m_quality, amount );\r\n\t\t}\r\n\t}\r\n\telse if ( qParam == \"PlayerLeft\" )\r\n\t{\r\n\t\tif ( m_selectedPlayerOffer )\r\n\t\t{\r\n\t\t\tm_proxy->playerOffertoStock( m_workshopID, m_selectedPlayerOffer->m_itemSID, m_selectedPlayerOffer->m_materialSID, m_selectedPlayerOffer->m_quality, amount );\r\n\t\t}\r\n\t}\r\n\telse if ( qParam == \"PlayerRight\" )\r\n\t{\r\n\t\tif ( m_selectedPlayerStock )\r\n\t\t{\r\n\t\t\tm_proxy->playerStocktoOffer( m_workshopID, m_selectedPlayerStock->m_itemSID, m_selectedPlayerStock->m_materialSID, m_selectedPlayerStock->m_quality, amount );\r\n\t\t}\r\n\t}\r\n}\r\n\r\nconst char* WorkshopModel::GetTraderValue() const\r\n{\r\n\treturn m_traderValue.Str();\r\n}\r\n\r\nconst char* WorkshopModel::GetPlayerValue() const\r\n{\r\n\treturn m_playerValue.Str();\r\n}\r\n\r\nvoid WorkshopModel::updateTraderValue( int value )\r\n{\r\n\tm_traderValue = QString::number( value ).toStdString().c_str();\r\n\tOnPropertyChanged( \"TraderValue\" );\r\n}\r\n\r\nvoid WorkshopModel::updatePlayerValue( int value )\r\n{\r\n\tm_playerValue = QString::number( value ).toStdString().c_str();\r\n\tOnPropertyChanged( \"PlayerValue\" );\r\n}\r\n\r\nvoid WorkshopModel::onTradeCmd( BaseComponent* param )\r\n{\r\n\tm_proxy->trade( m_workshopID );\r\n}\r\n\r\n#pragma endregion TraderSpecific\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nNS_BEGIN_COLD_REGION\r\n\r\nNS_IMPLEMENT_REFLECTION( WorkshopModel, \"IngnomiaGUI.WorkshopModel\" )\r\n{\r\n\tNsProp( \"Name\", &WorkshopModel::GetName, &WorkshopModel::SetName );\r\n\tNsProp( \"Suspended\", &WorkshopModel::GetSuspended, &WorkshopModel::SetSuspended );\r\n\tNsProp( \"AutoCraft\", &WorkshopModel::GetAutoCraftMissing, &WorkshopModel::SetAutoCraftMissing );\r\n\tNsProp( \"AcceptGenerated\", &WorkshopModel::GetAcceptGenerated, &WorkshopModel::SetAcceptGenerated );\r\n\tNsProp( \"LinkStockpile\", &WorkshopModel::GetLinkStockpile, &WorkshopModel::SetLinkStockpile );\r\n\tNsProp( \"ButcherCorpses\", &WorkshopModel::GetButcherCorpses, &WorkshopModel::SetButcherCorpses );\r\n\tNsProp( \"ButcherExcess\", &WorkshopModel::GetButcherExcess, &WorkshopModel::SetButcherExcess );\r\n\r\n\tNsProp( \"CatchFish\", &WorkshopModel::GetCatchFish, &WorkshopModel::SetCatchFish );\r\n\tNsProp( \"ProcessFish\", &WorkshopModel::GetProcessFish, &WorkshopModel::SetProcessFish );\r\n\r\n\tNsProp( \"Priorities\", &WorkshopModel::GetPrios );\r\n\tNsProp( \"SelectedPrio\", &WorkshopModel::GetSelectedPriority, &WorkshopModel::SetSelectedPriority );\r\n\r\n\tNsProp( \"Products\", &WorkshopModel::GetProducts );\r\n\tNsProp( \"Jobs\", &WorkshopModel::GetJobs );\r\n\r\n\tNsProp( \"NormalGui\", &WorkshopModel::GetNormalVisible );\r\n\tNsProp( \"ButcherGui\", &WorkshopModel::GetButcherVisible );\r\n\tNsProp( \"TraderGui\", &WorkshopModel::GetTraderVisible );\r\n\tNsProp( \"FisherGui\", &WorkshopModel::GetFisherVisible );\r\n\r\n\tNsProp( \"TraderStock\", &WorkshopModel::GetTraderStock );\r\n\tNsProp( \"TraderOffer\", &WorkshopModel::GetTraderOffer );\r\n\tNsProp( \"PlayerStock\", &WorkshopModel::GetPlayerStock );\r\n\tNsProp( \"PlayerOffer\", &WorkshopModel::GetPlayerOffer );\r\n\r\n\tNsProp( \"SelectedTraderStock\", &WorkshopModel::GetSelectedTraderStock, &WorkshopModel::SetSelectedTraderStock );\r\n\tNsProp( \"SelectedTraderOffer\", &WorkshopModel::GetSelectedTraderOffer, &WorkshopModel::SetSelectedTraderOffer );\r\n\tNsProp( \"SelectedPlayerStock\", &WorkshopModel::GetSelectedPlayerStock, &WorkshopModel::SetSelectedPlayerStock );\r\n\tNsProp( \"SelectedPlayerOffer\", &WorkshopModel::GetSelectedPlayerOffer, &WorkshopModel::SetSelectedPlayerOffer );\r\n\r\n\tNsProp( \"CmdTransfer\", &WorkshopModel::GetTransferCmd );\r\n\tNsProp( \"CmdTrade\", &WorkshopModel::GetTradeCmd );\r\n\r\n\tNsProp( \"Amount1\", &WorkshopModel::GetAmount1Checked, &WorkshopModel::SetAmount1Checked );\r\n\tNsProp( \"Amount10\", &WorkshopModel::GetAmount10Checked, &WorkshopModel::SetAmount10Checked );\r\n\tNsProp( \"Amount100\", &WorkshopModel::GetAmount100Checked, &WorkshopModel::SetAmount100Checked );\r\n\tNsProp( \"AmountAll\", &WorkshopModel::GetAmountAllChecked, &WorkshopModel::SetAmountAllChecked );\r\n\r\n\tNsProp( \"TraderValue\", &WorkshopModel::GetTraderValue );\r\n\tNsProp( \"PlayerValue\", &WorkshopModel::GetPlayerValue );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WsPriority )\r\n{\r\n\tNsProp( \"Name\", &WsPriority::GetName );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WsProduct )\r\n{\r\n\tNsProp( \"Name\", &WsProduct::GetName );\r\n\tNsProp( \"RequiredItems\", &WsProduct::requiredItems );\r\n\tNsProp( \"Craft\", &WsProduct::GetCmdBuild );\r\n\tNsProp( \"Mode\", &WsProduct::GetMode, &WsProduct::SetMode );\r\n\tNsProp( \"CraftNumber\", &WsProduct::GetCraftNumber, &WsProduct::SetCraftNumber );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WsRequiredItem )\r\n{\r\n\tNsProp( \"Name\", &WsRequiredItem::GetName );\r\n\tNsProp( \"Amount\", &WsRequiredItem::amount );\r\n\tNsProp( \"Materials\", &WsRequiredItem::availableMaterials );\r\n\tNsProp( \"SelectedMaterial\", &WsRequiredItem::GetSelectedMaterial, &WsRequiredItem::SetSelectedMaterial );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WsAvailableMaterial )\r\n{\r\n\tNsProp( \"Name\", &WsAvailableMaterial::GetName );\r\n\tNsProp( \"Amount\", &WsAvailableMaterial::amount );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WsCraftJob )\r\n{\r\n\tNsProp( \"Name\", &WsCraftJob::GetName );\r\n\tNsProp( \"Mode\", &WsCraftJob::GetMode, &WsCraftJob::SetMode );\r\n\tNsProp( \"CraftNumber\", &WsCraftJob::GetCraftNumber, &WsCraftJob::SetCraftNumber );\r\n\tNsProp( \"Suspended\", &WsCraftJob::GetSuspended, &WsCraftJob::SetSuspended );\r\n\tNsProp( \"MoveBack\", &WsCraftJob::GetMoveBack, &WsCraftJob::SetMoveBack );\r\n\tNsProp( \"ButtonCmd\", &WsCraftJob::GetButtonCmd );\r\n}\r\n\r\nNS_IMPLEMENT_REFLECTION( WsTradeItem )\r\n{\r\n\tNsProp( \"Name\", &WsTradeItem::GetName );\r\n\tNsProp( \"Count\", &WsTradeItem::GetCount );\r\n}\r\n"
  },
  {
    "path": "src/gui/xaml/workshopmodel.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#ifndef __WorkshopModel_H__\r\n#define __WorkshopModel_H__\r\n\r\n#include \"../aggregatorworkshop.h\"\r\n\r\n#include <NsApp/DelegateCommand.h>\r\n#include <NsApp/NotifyPropertyChangedBase.h>\r\n#include <NsCore/Noesis.h>\r\n#include <NsCore/Nullable.h>\r\n#include <NsCore/Ptr.h>\r\n#include <NsCore/ReflectionDeclare.h>\r\n#include <NsCore/ReflectionDeclareEnum.h>\r\n#include <NsCore/String.h>\r\n#include <NsGui/Collection.h>\r\n\r\n#include <QString>\r\n\r\nclass WorkshopProxy;\r\n\r\nnamespace Noesis\r\n{\r\ntemplate <class T>\r\nclass ObservableCollection;\r\n}\r\n\r\nnamespace IngnomiaGUI\r\n{\r\n\r\n#pragma region WsPriority\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WsPriority final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tWsPriority( const char* name );\r\n\r\n\tconst char* GetName() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\r\n\tNS_DECLARE_REFLECTION( WsPriority, Noesis::BaseComponent )\r\n};\r\n#pragma endregion WsPriority\r\n\r\n#pragma region RecipeTab\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WsAvailableMaterial final : public Noesis::BaseComponent\r\n{\r\npublic:\r\n\tWsAvailableMaterial( QString sid, int amount, QString item );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* sid() const;\r\n\tconst char* amount() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tNoesis::String _sid;\r\n\tNoesis::String _amount;\r\n\r\n\tNS_DECLARE_REFLECTION( WsAvailableMaterial, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WsRequiredItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tWsRequiredItem( GuiWorkshopComponent gwc );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* amount() const;\r\n\tconst QString sid();\r\n\r\n\tNoesis::ObservableCollection<WsAvailableMaterial>* availableMaterials() const;\r\n\r\n\tvoid SetSelectedMaterial( WsAvailableMaterial* mat );\r\n\tWsAvailableMaterial* GetSelectedMaterial() const;\r\n\r\nprivate:\r\n\tNoesis::String _name;\r\n\tQString _sid;\r\n\tNoesis::String _amount;\r\n\r\n\tWsAvailableMaterial* _selectedMaterial;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsAvailableMaterial>> _availableMaterials;\r\n\r\n\tNS_DECLARE_REFLECTION( WsRequiredItem, Noesis::BaseComponent )\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WsProduct final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tWsProduct( GuiWorkshopProduct gwp, WorkshopProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tint GetMode() const;\r\n\tvoid SetMode( int );\r\n\tconst char* GetCraftNumber() const;\r\n\tvoid SetCraftNumber( const char* value );\r\n\r\n\tQString sid() const;\r\n\tNoesis::ObservableCollection<WsRequiredItem>* requiredItems() const;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tQString m_sid;\r\n\tint m_mode = 0;\r\n\tNoesis::String m_craftNumber;\r\n\r\n\tWorkshopProxy* m_proxy = nullptr;\r\n\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsRequiredItem>> _requiredItems;\r\n\r\n\tvoid onCmdBuild( BaseComponent* param );\r\n\r\n\tconst NoesisApp::DelegateCommand* GetCmdBuild() const;\r\n\r\n\tNoesisApp::DelegateCommand _cmdBuild;\r\n\r\n\tNS_DECLARE_REFLECTION( WsProduct, Noesis::BaseComponent )\r\n};\r\n#pragma endregion RecipeTab\r\n\r\n#pragma region CraftingListTab\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WsCraftJob final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tWsCraftJob( CraftJob cj, WorkshopProxy* proxy );\r\n\r\n\tconst char* GetName() const;\r\n\r\n\tint GetMode() const;\r\n\tvoid SetMode( int );\r\n\tconst char* GetCraftNumber() const;\r\n\tvoid SetCraftNumber( const char* value );\r\n\tbool GetSuspended() const;\r\n\tvoid SetSuspended( bool value );\r\n\tbool GetMoveBack() const;\r\n\tvoid SetMoveBack( bool value );\r\n\r\n\tQString sid() const;\r\n\r\n\tconst NoesisApp::DelegateCommand* GetButtonCmd() const\r\n\t{\r\n\t\treturn &_buttonCmd;\r\n\t}\r\n\tvoid onButtonCmd( BaseComponent* param );\r\n\r\nprivate:\r\n\tunsigned int m_craftJobID;\r\n\tNoesis::String m_name;\r\n\tQString m_sid;\r\n\tint m_mode = 0;\r\n\tNoesis::String m_craftNumber;\r\n\r\n\tbool m_suspended = false;\r\n\tbool m_moveBack  = false;\r\n\r\n\tWorkshopProxy* m_proxy = nullptr;\r\n\r\n\tNoesisApp::DelegateCommand _buttonCmd;\r\n\r\n\tNS_DECLARE_REFLECTION( WsCraftJob, Noesis::BaseComponent )\r\n};\r\n\r\n#pragma endregion CraftingListTab\r\n\r\n#pragma region TradeItems\r\n\r\nenum class CheckedAmount : unsigned char\r\n{\r\n\tAmount1,\r\n\tAmount10,\r\n\tAmount100,\r\n\tAmountAll,\r\n};\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WsTradeItem final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tWsTradeItem( QString name, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\r\n\tconst char* GetName() const;\r\n\tconst char* GetCount() const;\r\n\r\n\tvoid SetCount( int count );\r\n\r\n\tQString m_itemSID;\r\n\tQString m_materialSID;\r\n\r\n\tunsigned char m_quality = 0;\r\n\tint m_count             = 0;\r\n\r\nprivate:\r\n\tNoesis::String m_name;\r\n\tNoesis::String m_countString;\r\n\r\n\tNS_DECLARE_REFLECTION( WsTradeItem, NoesisApp::NotifyPropertyChangedBase )\r\n};\r\n\r\n#pragma endregion TradeItems\r\n\r\n////////////////////////////////////////////////////////////////////////////////////////////////////\r\nclass WorkshopModel final : public NoesisApp::NotifyPropertyChangedBase\r\n{\r\npublic:\r\n\tWorkshopModel();\r\n\r\n\tvoid onUpdateInfo( const GuiWorkshopInfo& WorkshopInfo );\r\n\tvoid onUpdateCraftList( const GuiWorkshopInfo& WorkshopInfo );\r\n\r\n\tvoid updateTraderStock( const QList<GuiTradeItem>& items );\r\n\tvoid updatePlayerStock( const QList<GuiTradeItem>& items );\r\n\r\n\tvoid updateTraderStockItem( const GuiTradeItem& item );\r\n\tvoid updatePlayerStockItem( const GuiTradeItem& item );\r\n\r\n\tvoid updateTraderValue( int value );\r\n\tvoid updatePlayerValue( int value );\r\n\r\nprivate:\r\n\tconst char* GetName() const;\r\n\tvoid SetName( const char* value );\r\n\tbool GetSuspended() const;\r\n\tvoid SetSuspended( bool value );\r\n\tbool GetAutoCraftMissing() const;\r\n\tvoid SetAutoCraftMissing( bool value );\r\n\tbool GetAcceptGenerated() const;\r\n\tvoid SetAcceptGenerated( bool value );\r\n\tbool GetLinkStockpile() const;\r\n\tvoid SetLinkStockpile( bool value );\r\n\tbool GetButcherExcess() const;\r\n\tvoid SetButcherExcess( bool value );\r\n\tbool GetButcherCorpses() const;\r\n\tvoid SetButcherCorpses( bool value );\r\n\tbool GetCatchFish() const;\r\n\tvoid SetCatchFish( bool value );\r\n\tbool GetProcessFish() const;\r\n\tvoid SetProcessFish( bool value );\r\n\r\n\tconst char* GetNormalVisible() const;\r\n\tconst char* GetButcherVisible() const;\r\n\tconst char* GetTraderVisible() const;\r\n\tconst char* GetFisherVisible() const;\r\n\r\n\tconst char* GetTraderValue() const;\r\n\tconst char* GetPlayerValue() const;\r\n\r\n\tNoesis::ObservableCollection<WsPriority>* GetPrios() const;\r\n\tvoid SetSelectedPriority( WsPriority* prio );\r\n\tWsPriority* GetSelectedPriority() const;\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsPriority>> m_prios;\r\n\tWsPriority* m_selectedPrio;\r\n\r\n\tNoesis::ObservableCollection<WsProduct>* GetProducts() const\r\n\t{\r\n\t\treturn m_products;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsProduct>> m_products;\r\n\r\n\tNoesis::ObservableCollection<WsCraftJob>* GetJobs() const\r\n\t{\r\n\t\treturn m_jobs;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsCraftJob>> m_jobs;\r\n\r\n#pragma region TradeItemLists\r\n\tNoesis::ObservableCollection<WsTradeItem>* GetTraderStock() const\r\n\t{\r\n\t\treturn m_traderStock;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsTradeItem>> m_traderStock;\r\n\tWsTradeItem* m_selectedTraderStock = nullptr;\r\n\tvoid SetSelectedTraderStock( WsTradeItem* item );\r\n\tWsTradeItem* GetSelectedTraderStock() const;\r\n\r\n\tNoesis::ObservableCollection<WsTradeItem>* GetTraderOffer() const\r\n\t{\r\n\t\treturn m_traderOffer;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsTradeItem>> m_traderOffer;\r\n\tWsTradeItem* m_selectedTraderOffer = nullptr;\r\n\tvoid SetSelectedTraderOffer( WsTradeItem* item );\r\n\tWsTradeItem* GetSelectedTraderOffer() const;\r\n\r\n\tNoesis::ObservableCollection<WsTradeItem>* GetPlayerStock() const\r\n\t{\r\n\t\treturn m_playerStock;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsTradeItem>> m_playerStock;\r\n\tWsTradeItem* m_selectedPlayerStock = nullptr;\r\n\tvoid SetSelectedPlayerStock( WsTradeItem* item );\r\n\tWsTradeItem* GetSelectedPlayerStock() const;\r\n\r\n\tNoesis::ObservableCollection<WsTradeItem>* GetPlayerOffer() const\r\n\t{\r\n\t\treturn m_playerOffer;\r\n\t}\r\n\tNoesis::Ptr<Noesis::ObservableCollection<WsTradeItem>> m_playerOffer;\r\n\tWsTradeItem* m_selectedPlayerOffer = nullptr;\r\n\tvoid SetSelectedPlayerOffer( WsTradeItem* item );\r\n\tWsTradeItem* GetSelectedPlayerOffer() const;\r\n\r\n\tCheckedAmount m_amountToTransfer = CheckedAmount::Amount1;\r\n\r\n\tbool GetAmount1Checked() const;\r\n\tbool GetAmount10Checked() const;\r\n\tbool GetAmount100Checked() const;\r\n\tbool GetAmountAllChecked() const;\r\n\r\n\tvoid SetAmount1Checked( bool checked );\r\n\tvoid SetAmount10Checked( bool checked );\r\n\tvoid SetAmount100Checked( bool checked );\r\n\tvoid SetAmountAllChecked( bool checked );\r\n\r\n\tvoid onTransferCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetTransferCmd() const\r\n\t{\r\n\t\treturn &m_transferCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_transferCmd;\r\n\r\n\tNoesis::String m_traderValue = \"0\";\r\n\tNoesis::String m_playerValue = \"0\";\r\n\r\n\tvoid onTradeCmd( BaseComponent* param );\r\n\tconst NoesisApp::DelegateCommand* GetTradeCmd() const\r\n\t{\r\n\t\treturn &m_tradeCmd;\r\n\t}\r\n\tNoesisApp::DelegateCommand m_tradeCmd;\r\n\r\n#pragma endregion TradeItemLists\r\n\r\n\tWorkshopProxy* m_proxy = nullptr;\r\n\r\n\tunsigned int m_workshopID = 0;\r\n\tNoesis::String m_name     = \"-Workshop-\";\r\n\tbool m_suspended          = false;\r\n\tbool m_acceptGenerated    = false;\r\n\tbool m_autoCraftMissing   = false;\r\n\tbool m_connectStockpile   = false;\r\n\tbool m_butcherCorpses     = false;\r\n\tbool m_butcherExcess      = false;\r\n\tbool m_catchFish          = false;\r\n\tbool m_processFish        = false;\r\n\r\n\tQString m_gui;\r\n\r\n\tNS_DECLARE_REFLECTION( WorkshopModel, NotifyPropertyChangedBase )\r\n};\r\n\r\n} // namespace IngnomiaGUI\r\n\r\n#endif\r\n"
  },
  {
    "path": "src/gui/xaml/workshopproxy.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"workshopproxy.h\"\r\n\r\n#include \"../../base/gamestate.h\"\r\n#include \"../../gfx/sprite.h\"\r\n#include \"../../gfx/spritefactory.h\"\r\n#include \"../../base/global.h\"\r\n#include \"../eventconnector.h\"\r\n\r\n#include <QDebug>\r\n#include <QPainter>\r\n\r\nWorkshopProxy::WorkshopProxy( QObject* parent ) :\r\n\tQObject( parent )\r\n{\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalUpdateInfo, this, &WorkshopProxy::onUpdateInfo, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalUpdateCraftList, this, &WorkshopProxy::onUpdateCraftList, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &WorkshopProxy::signalSetBasicOptions, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onSetBasicOptions, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalSetButcherOptions, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onSetButcherOptions, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalSetFisherOptions, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onSetFisherOptions, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalCraftItem, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onCraftItem, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalCraftJobCommand, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onCraftJobCommand, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalCraftJobParams, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onCraftJobParams, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &WorkshopProxy::signalRequestAllTradeItems, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onRequestAllTradeItems, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalTraderStock, this, &WorkshopProxy::onUpdateTraderStock, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalPlayerStock, this, &WorkshopProxy::onUpdatePlayerStock, Qt::QueuedConnection );\r\n\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalUpdateTraderStockItem, this, &WorkshopProxy::onUpdateTraderStockItem, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalUpdatePlayerStockItem, this, &WorkshopProxy::onUpdatePlayerStockItem, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalUpdateTraderValue, this, &WorkshopProxy::onUpdateTraderValue, Qt::QueuedConnection );\r\n\tconnect( Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::signalUpdatePlayerValue, this, &WorkshopProxy::onUpdatePlayerValue, Qt::QueuedConnection );\r\n\r\n\tconnect( this, &WorkshopProxy::signalTraderStocktoOffer, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onTraderStocktoOffer, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalTraderOffertoStock, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onTraderOffertoStock, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalPlayerStocktoOffer, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onPlayerStocktoOffer, Qt::QueuedConnection );\r\n\tconnect( this, &WorkshopProxy::signalPlayerOffertoStock, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onPlayerOffertoStock, Qt::QueuedConnection );\r\n\t\r\n\tconnect( this, &WorkshopProxy::signalTrade, Global::eventConnector->aggregatorWorkshop(), &AggregatorWorkshop::onTrade, Qt::QueuedConnection );\r\n}\r\n\r\nWorkshopProxy::~WorkshopProxy()\r\n{\r\n}\r\n\r\nvoid WorkshopProxy::setParent( IngnomiaGUI::WorkshopModel* parent )\r\n{\r\n\tm_parent = parent;\r\n}\r\n\r\nvoid WorkshopProxy::onUpdateInfo( const GuiWorkshopInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_workshopID = info.workshopID;\r\n\t\tm_parent->onUpdateInfo( info );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::setBasicOptions( unsigned int WorkshopID, QString name, int priority, bool suspended, bool acceptGenerated, bool autoCraftMissing, bool connectStockpile )\r\n{\r\n\tif( !m_blockWriteBack )\r\n\t{\r\n\t\temit signalSetBasicOptions( WorkshopID, name, priority, suspended, acceptGenerated, autoCraftMissing, connectStockpile );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::craftItem( QString craftID, int mode, int number, QStringList mats )\r\n{\r\n\temit signalCraftItem( m_workshopID, craftID, mode, number, mats );\r\n}\r\n\r\nvoid WorkshopProxy::onUpdateCraftList( const GuiWorkshopInfo& info )\r\n{\r\n\tif ( m_parent )\r\n\t{\r\n\t\tm_parent->onUpdateCraftList( info );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::craftJobCommand( unsigned int craftJobID, QString command )\r\n{\r\n\temit signalCraftJobCommand( m_workshopID, craftJobID, command );\r\n}\r\n\r\nvoid WorkshopProxy::craftJobParams( unsigned int craftJobID, int mode, QString numString, bool suspended, bool moveBack )\r\n{\r\n\tint num = qMax( 1, numString.toInt() );\r\n\temit signalCraftJobParams( m_workshopID, craftJobID, mode, num, suspended, moveBack );\r\n}\r\n\r\nvoid WorkshopProxy::setButcherOptions( unsigned int workshopID, bool butcherCorpses, bool butcherExcess )\r\n{\r\n\temit signalSetButcherOptions( workshopID, butcherCorpses, butcherExcess );\r\n}\r\n\r\nvoid WorkshopProxy::requestAllTradeItems( unsigned int workshopID )\r\n{\r\n\temit signalRequestAllTradeItems( workshopID );\r\n}\r\n\r\nvoid WorkshopProxy::onUpdateTraderStock( const QList<GuiTradeItem>& items )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateTraderStock( items );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::onUpdatePlayerStock( const QList<GuiTradeItem>& items )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updatePlayerStock( items );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::traderStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\temit signalTraderStocktoOffer( workshopID, itemSID, materialSID, quality, count );\r\n}\r\n\t\r\nvoid WorkshopProxy::traderOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\temit signalTraderOffertoStock( workshopID, itemSID, materialSID, quality, count );\r\n}\r\n\r\nvoid WorkshopProxy::playerStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\temit signalPlayerStocktoOffer( workshopID, itemSID, materialSID, quality, count );\r\n}\r\n\r\nvoid WorkshopProxy::playerOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count )\r\n{\r\n\temit signalPlayerOffertoStock( workshopID, itemSID, materialSID, quality, count );\r\n}\r\n\r\nvoid WorkshopProxy::onUpdateTraderStockItem( const GuiTradeItem& item )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateTraderStockItem( item );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::onUpdatePlayerStockItem( const GuiTradeItem& item )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updatePlayerStockItem( item );\r\n\t}\r\n}\r\n\r\n\r\nvoid WorkshopProxy::onUpdateTraderValue( int value )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updateTraderValue( value );\r\n\t}\r\n}\r\n\t\r\nvoid WorkshopProxy::onUpdatePlayerValue( int value )\r\n{\r\n\tif( m_parent )\r\n\t{\r\n\t\tm_parent->updatePlayerValue( value );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::trade( unsigned int workshopID )\r\n{\r\n\temit signalTrade( workshopID );\r\n}\r\n\r\nvoid WorkshopProxy::setFisherOptions( unsigned int WorkshopID, bool catchFish, bool processFish )\r\n{\r\n\tif( !m_blockWriteBack )\r\n\t{\r\n\t\temit signalSetFisherOptions( WorkshopID, catchFish, processFish );\r\n\t}\r\n}\r\n\r\nvoid WorkshopProxy::blockWriteBack()\r\n{\r\n\tm_blockWriteBack = true;\r\n}\r\n\t\r\nvoid WorkshopProxy::unblockWriteBack()\r\n{\r\n\tm_blockWriteBack = false;\r\n}"
  },
  {
    "path": "src/gui/xaml/workshopproxy.h",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#pragma once\r\n\r\n#include \"../aggregatorworkshop.h\"\r\n#include \"workshopmodel.h\"\r\n\r\n#include <QObject>\r\n\r\nclass WorkshopProxy : public QObject\r\n{\r\n\tQ_OBJECT\r\n\r\npublic:\r\n\tWorkshopProxy( QObject* parent = nullptr );\r\n\t~WorkshopProxy();\r\n\r\n\tvoid setParent( IngnomiaGUI::WorkshopModel* parent );\r\n\r\n\tvoid setBasicOptions( unsigned int WorkshopID, QString name, int priority, bool suspended, bool acceptGenerated, bool autoCraftMissing, bool connectStockpile );\r\n\tvoid setButcherOptions( unsigned int WorkshopID, bool butcherCorpses, bool butcherExcess );\r\n\tvoid setFisherOptions( unsigned int WorkshopID, bool catchFish, bool processFish );\r\n\r\n\tvoid craftItem( QString sid, int mode, int number, QStringList mats );\r\n\r\n\tvoid craftJobCommand( unsigned int craftJobID, QString command );\r\n\tvoid craftJobParams( unsigned int craftJobID, int mode, QString numString, bool suspended, bool moveBack );\r\n\r\n\tvoid requestAllTradeItems( unsigned int workshopID );\r\n\r\n\tvoid traderStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid traderOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid playerStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid playerOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\r\n\tvoid trade( unsigned int workshopID );\r\n\r\n\tvoid blockWriteBack();\r\n\tvoid unblockWriteBack();\r\n\r\nprivate:\r\n\tIngnomiaGUI::WorkshopModel* m_parent = nullptr;\r\n\r\n\tunsigned int m_workshopID = 0;\r\n\r\n\tbool m_blockWriteBack = false;\r\n\r\nprivate slots:\r\n\tvoid onUpdateInfo( const GuiWorkshopInfo& info );\r\n\tvoid onUpdateCraftList( const GuiWorkshopInfo& info );\r\n\r\n\tvoid onUpdateTraderStock( const QList<GuiTradeItem>& items );\r\n\tvoid onUpdatePlayerStock( const QList<GuiTradeItem>& items );\r\n\t\r\n\tvoid onUpdateTraderStockItem( const GuiTradeItem& item );\r\n\tvoid onUpdatePlayerStockItem( const GuiTradeItem& item );\r\n\r\n\tvoid onUpdateTraderValue( int value );\r\n\tvoid onUpdatePlayerValue( int value );\r\n\r\nsignals:\r\n\tvoid signalSetBasicOptions( unsigned int WorkshopID, QString name, int priority, bool suspended, bool acceptGenerated, bool autoCraftMissing, bool connectStockpile );\r\n\tvoid signalSetButcherOptions( unsigned int WorkshopID, bool butcherCorpses, bool butcherExcess );\r\n\tvoid signalSetFisherOptions( unsigned int WorkshopID, bool catchFish, bool processFish );\r\n\tvoid signalCraftItem( unsigned int WorkshopID, QString craftID, int mode, int number, QStringList mats );\r\n\tvoid signalCraftJobCommand( unsigned int workshopID, unsigned int craftJobID, QString command );\r\n\tvoid signalCraftJobParams( unsigned int workshopID, unsigned int craftJobID, int mode, int numToCraft, bool suspended, bool moveBack );\r\n\tvoid signalRequestAllTradeItems( unsigned int workshopID );\r\n\r\n\tvoid signalTraderStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid signalTraderOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid signalPlayerStocktoOffer( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\tvoid signalPlayerOffertoStock( unsigned int workshopID, QString itemSID, QString materialSID, unsigned char quality, int count );\r\n\r\n\tvoid signalTrade( unsigned int workshopID );\r\n};\r\n"
  },
  {
    "path": "src/main.cpp",
    "content": "/*\t\r\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\r\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Affero General Public License as\r\n    published by the Free Software Foundation, either version 3 of the\r\n    License, or (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Affero General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Affero General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n#include \"base/config.h\"\r\n#include \"base/db.h\"\r\n#include \"base/io.h\"\r\n#include \"base/crashhandler.h\"\r\n#include \"base/global.h\"\r\n\r\n#include \"game/gamemanager.h\"\r\n\r\n#include \"gui/mainwindow.h\"\r\n#include \"gui/strings.h\"\r\n\r\n#include <QApplication>\r\n#include <QDateTime>\r\n#include <QDebug>\r\n#include <QDesktopWidget>\r\n#include <QDir>\r\n#include <QFileIconProvider>\r\n#include <QStandardPaths>\r\n#include <QSurfaceFormat>\r\n#include <QWindow>\r\n#include <QtWidgets/QApplication>\r\n\r\n#include <iostream>\r\n#ifdef _WIN32\r\n#include <windows.h>\r\n#endif\r\n#include \"version.h\"\r\n\r\nQTextStream* out = 0;\r\nbool verbose     = false;\r\n\r\nvoid clearLog()\r\n{\r\n\tQString folder   = IO::getDataFolder();\r\n\tbool ok          = true;\r\n\tQString fileName = \"log.txt\";\r\n\tif ( QDir( folder ).exists() )\r\n\t{\r\n\t\tfileName = folder + \"/\" + fileName;\r\n\t}\r\n\r\n\tQFile file( fileName );\r\n\tfile.open( QIODevice::WriteOnly );\r\n\tfile.close();\r\n}\r\n\r\nQPointer<QFile> openLog()\r\n{\r\n\tQString folder   = IO::getDataFolder();\r\n\tbool ok          = true;\r\n\tQString fileName = \"log.txt\";\r\n\tif ( QDir( folder ).exists() )\r\n\t{\r\n\t\tfileName = folder + \"/\" + fileName;\r\n\t}\r\n\r\n\tQPointer<QFile> outFile(new QFile( fileName ));\r\n\tif(outFile->open( QIODevice::WriteOnly | QIODevice::Append ))\r\n\t{\r\n\t\treturn outFile;\r\n\t}\r\n\telse\r\n\t{\r\n\t\treturn nullptr;\r\n\t}\r\n}\r\n\r\nvoid logOutput( QtMsgType type, const QMessageLogContext& context, const QString& message )\r\n{\r\n\tif ( message.startsWith( \"libpng warning:\" ) )\r\n\t\treturn;\r\n\r\n\tQString filedate  = QDateTime::currentDateTime().toString( \"yyyy.MM.dd hh:mm:ss:zzz\" );\r\n#ifdef _WIN32\r\n\tif ( IsDebuggerPresent() )\r\n#else\r\n\tif (verbose)\r\n#endif // _WIN32\r\n\t{\r\n\t\tQString debugdate = QDateTime::currentDateTime().toString( \"hh:mm:ss:zzz\" );\r\n\r\n\t\tswitch ( type )\r\n\t\t{\r\n\t\t\tcase QtDebugMsg:\r\n\t\t\t\tdebugdate += \" [D]\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase QtInfoMsg:\r\n\t\t\t\tdebugdate += \" [I]\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase QtWarningMsg:\r\n\t\t\t\tdebugdate += \" [W]\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase QtCriticalMsg:\r\n\t\t\t\tdebugdate += \" [C]\";\r\n\t\t\t\tbreak;\r\n\t\t\tcase QtFatalMsg:\r\n\t\t\t\tdebugdate += \" [F]\";\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t\tQString text    = debugdate + \" \" + message + \"\\n\";\r\n\t\tstd::string str = text.toStdString();\r\n\r\n#ifdef _WIN32\r\n\t\tOutputDebugStringA( str.c_str() );\r\n#else\r\n\t\tstd::cerr << str;\r\n#endif\r\n\t}\r\n\tstatic QPointer<QFile> outFile = openLog();\r\n\tstatic std::mutex guard;\r\n\r\n\tif ( outFile )\r\n\t{\r\n\t\tstd::lock_guard<std::mutex> lock( guard );\r\n\t\tQTextStream ts( outFile );\r\n\t\tts << filedate << \" \" << message << endl;\r\n\t}\r\n}\r\n\r\nint main( int argc, char* argv[] )\r\n{\r\n\tsetupCrashHandler();\r\n\tclearLog();\r\n\tqInstallMessageHandler( &logOutput );\r\n\tqInfo() << PROJECT_NAME << \"version\" << PROJECT_VERSION;\r\n#ifdef GIT_REPO\r\n\tqInfo() << \"Built from\" << GIT_REPO << GIT_REF << \"(\" << GIT_SHA << \")\"\r\n\t\t\t<< \"build\" << BUILD_ID;\r\n#endif // GIT_REPO\r\n\r\n\t// Disable use of ANGLE, as it supports OpenGL 3.x at most\r\n\tQCoreApplication::setAttribute( Qt::AA_UseDesktopOpenGL );\r\n\t// Require use of shared base context, so OpenGL context won't get invalidated on fullscreen toggles etc.\r\n\tQCoreApplication::setAttribute( Qt::AA_ShareOpenGLContexts );\r\n\t// Enable correct render surface scaling with HDPI setups.\r\n\tQCoreApplication::setAttribute( Qt::AA_EnableHighDpiScaling );\r\n\t// Enable fractional DPI support (e.g. 150%)\r\n\tQGuiApplication::setHighDpiScaleFactorRoundingPolicy( Qt::HighDpiScaleFactorRoundingPolicy::PassThrough );\r\n\r\n\tQApplication a( argc, argv );\r\n\tQCoreApplication::addLibraryPath( QCoreApplication::applicationDirPath() );\r\n\tQCoreApplication::setOrganizationDomain( PROJECT_HOMEPAGE_URL );\r\n\tQCoreApplication::setOrganizationName( \"Roest\" );\r\n\tQCoreApplication::setApplicationName( PROJECT_NAME );\r\n\tQCoreApplication::setApplicationVersion( PROJECT_VERSION );\r\n\r\n\tGlobal::cfg = new Config;\r\n\r\n\tif ( !Global::cfg->valid() )\r\n\t{\r\n\t\tqDebug() << \"Failed to init Config.\";\r\n\t\tabort();\r\n\t}\r\n\r\n\tDB::init();\r\n\tDB::initStructs();\r\n\r\n\tif ( !S::gi().init() )\r\n\t{\r\n\t\tqDebug() << \"Failed to init translation.\";\r\n\t\tabort();\r\n\t}\r\n\r\n\tGlobal::cfg->set( \"CurrentVersion\", PROJECT_VERSION );\r\n\r\n\tQStringList args = a.arguments();\r\n\r\n\tfor ( int i = 1; i < args.size(); ++i )\r\n\t{\r\n\t\tif ( args.at( i ) == \"-h\" || args.at( i ) == \"?\" )\r\n\t\t{\r\n\t\t\tqDebug() << \"Command line options:\";\r\n\t\t\tqDebug() << \"-h : displays this message\";\r\n\t\t\tqDebug() << \"-v : toggles verbose mode, warning: this will spam your console with messages\";\r\n\t\t\tqDebug() << \"---\";\r\n\t\t}\r\n\t\tif ( args.at( i ) == \"-v\" )\r\n\t\t{\r\n\t\t\tverbose = true;\r\n\t\t}\r\n\t\tif ( args.at( i ) == \"-ds\" )\r\n\t\t{\r\n\t\t\tGlobal::debugSound = true;\r\n\t\t}\r\n\t}\r\n\r\n\tint width  = qMax( 1200, Global::cfg->get( \"WindowWidth\" ).toInt() );\r\n\tint height = qMax( 675, Global::cfg->get( \"WindowHeight\" ).toInt() );\r\n\r\n\tauto defaultFormat = QSurfaceFormat::defaultFormat();\r\n\tdefaultFormat.setRenderableType( QSurfaceFormat::OpenGL );\r\n\tdefaultFormat.setSwapBehavior( QSurfaceFormat::TripleBuffer );\r\n\tdefaultFormat.setColorSpace( QSurfaceFormat::sRGBColorSpace );\r\n\tdefaultFormat.setDepthBufferSize( 16 );\r\n\t// 0 = unthrottled, 1 = vysnc full FPS, 2 = vsync half FPS\r\n\tdefaultFormat.setSwapInterval( 0 );\r\n\tdefaultFormat.setVersion( 4, 3 );\r\n\tdefaultFormat.setRenderableType( QSurfaceFormat::OpenGL );\r\n\tdefaultFormat.setProfile( QSurfaceFormat::CoreProfile );\r\n\tdefaultFormat.setOption( QSurfaceFormat::DebugContext );\r\n\tQSurfaceFormat::setDefaultFormat( defaultFormat );\r\n\r\n\tGameManager* gm = new GameManager;\r\n\tQThread gameThread;\r\n\tgameThread.start();\r\n\tgm->moveToThread( &gameThread );\r\n\r\n\r\n\t//MainWindow w;\r\n\tMainWindow w;\r\n\t\r\n\tw.setIcon( QIcon( QCoreApplication::applicationDirPath() + \"/content/icon.png\" ) );\r\n\tw.resize( width, height );\r\n\tw.setPosition( Global::cfg->get( \"WindowPosX\" ).toInt(), Global::cfg->get( \"WindowPosY\" ).toInt() );\r\n\tw.show();\r\n\tif( Global::cfg->get( \"fullscreen\" ).toBool() )\r\n\t{\r\n\t\tw.onFullScreen( true );\r\n\t}\r\n\r\n\tauto ret = a.exec();\r\n\r\n\tgameThread.terminate();\r\n\tgameThread.wait();\r\n\r\n\treturn ret;\r\n}\r\n\r\n#ifdef _WIN32\r\nINT WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow )\r\n{\r\n\treturn main( 0, nullptr );\r\n}\r\n\r\nextern \"C\"\r\n{\r\n\t// Request use of dedicated GPUs for NVidia/AMD/iGPU mixed setups\r\n\t__declspec( dllexport ) DWORD NvOptimusEnablement                  = 1;\r\n\t__declspec( dllexport ) DWORD AmdPowerXpressRequestHighPerformance = 1;\r\n}\r\n#endif // _WIN32\r\n\r\n"
  },
  {
    "path": "src/pch.h",
    "content": "/*\t\n\tThis file is part of Ingnomia https://github.com/rschurade/Ingnomia\n    Copyright (C) 2017-2020  Ralph Schurade, Ingnomia Team\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Affero General Public License as\n    published by the Free Software Foundation, either version 3 of the\n    License, or (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Affero General Public License for more details.\n\n    You should have received a copy of the GNU Affero General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n#pragma once\n\n#include \"base/global.h\"\n\n#include <NoesisPCH.h>\n\n#include <QWidget>\n#include <QtCore>\n"
  },
  {
    "path": "src/version.h.in",
    "content": "// DO NOT CHANGE MANUALLY\n// READ THE DOCUMENTATION ON HOW TO CONFIGURE CMAKE\n\n#define PROJECT_NAME \"@PROJECT_NAME@\"\n#define PROJECT_VERSION \"@PROJECT_VERSION@\"\n#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@\n#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@\n#define PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@\n#define PROJECT_VERSION_TWEAK @PROJECT_VERSION_TWEAK@\n#define PROJECT_VERSION_COMMA @PROJECT_VERSION_MAJOR@, @PROJECT_VERSION_MINOR@, @PROJECT_VERSION_PATCH@, @PROJECT_VERSION_TWEAK@\n#define PROJECT_DESCRIPTION \"@PROJECT_DESCRIPTION@\"\n#define PROJECT_HOMEPAGE_URL \"@PROJECT_HOMEPAGE_URL@\"\n#cmakedefine GIT_REPO \"@GIT_REPO@\"\n#cmakedefine GIT_REF \"@GIT_REF@\"\n#cmakedefine GIT_SHA \"@GIT_SHA@\"\n#cmakedefine BUILD_ID \"@BUILD_ID@\"\n#cmakedefine BUGSPLAT_DB \"@BUGSPLAT_DB@\"\n"
  },
  {
    "path": "windows/Ingnomia.manifest",
    "content": "<?xml version=\"1.0\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n  <application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n    <windowsSettings xmlns=\"http://schemas.microsoft.com/SMI/2017/WindowsSettings\">\n      <dpiAware>true</dpiAware>\n      <gdiScaling>false</gdiScaling>\n    </windowsSettings>\n  </application>\n  <compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n    <application>\n      <!-- Windows 10 -->\n      <supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n      <!-- Windows 8.1 -->\n      <supportedOS Id=\"{1f676c76-80e1-4239-95bb-83d0f6d0da78}\"/>\n      <!-- Windows 8 -->\n      <supportedOS Id=\"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}\"/>\n      <!-- Windows 7 -->\n      <supportedOS Id=\"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}\"/>\n      <!-- Windows Vista -->\n      <supportedOS Id=\"{e2011457-1546-43c5-a5fe-008deee3d3f0}\"/>\n    </application>\n  </compatibility>\n  <trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n    <security>\n      <requestedPrivileges>\n        <requestedExecutionLevel level=\"asInvoker\" uiAccess=\"false\" />\n      </requestedPrivileges>\n    </security>\n  </trustInfo>\n</assembly>"
  },
  {
    "path": "windows/Ingnomia.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#include \"../src/version.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"winres.h\"\n\n/////////////////////////////////////////////////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n/////////////////////////////////////////////////////////////////////////////\n// German (Germany) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)\nLANGUAGE LANG_GERMAN, SUBLANG_GERMAN\n\n#ifdef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE \nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE \nBEGIN\n    \"#include winres.h\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE \nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nIDI_ICON1               ICON                    \"../Ingnomia.ico\"\n\n#endif    // German (Germany) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n/////////////////////////////////////////////////////////////////////////////\n// English (United States) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n\n/////////////////////////////////////////////////////////////////////////////\n//\n// Version\n//\n\nVS_VERSION_INFO VERSIONINFO\n FILEVERSION PROJECT_VERSION_COMMA\n PRODUCTVERSION PROJECT_VERSION_COMMA\n FILEFLAGSMASK 0x3fL\n#ifdef _DEBUG\n FILEFLAGS 0x1L\n#else\n FILEFLAGS 0x0L\n#endif\n FILEOS 0x40004L\n FILETYPE 0x1L\n FILESUBTYPE 0x0L\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"040904b0\"\n        BEGIN\n            VALUE \"CompanyName\", \"TODO: <Company name>\"\n            VALUE \"FileDescription\", \"Ingnomia\"\n            VALUE \"FileVersion\", PROJECT_VERSION\n            VALUE \"InternalName\", PROJECT_NAME\n            VALUE \"LegalCopyright\", \"Copyright (C) 2020\"\n            VALUE \"OriginalFilename\", PROJECT_NAME \".exe\"\n            VALUE \"ProductName\", PROJECT_NAME\n            VALUE \"ProductVersion\", PROJECT_VERSION\n        END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x409, 1200\n    END\nEND\n\n#endif    // English (United States) resources\n/////////////////////////////////////////////////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n/////////////////////////////////////////////////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n/////////////////////////////////////////////////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n\n"
  },
  {
    "path": "windows/resource.h",
    "content": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by Ingnomia.rc\n//\n#define IDI_ICON1                       101\n\n// Next default values for new objects\n// \n#ifdef APSTUDIO_INVOKED\n#ifndef APSTUDIO_READONLY_SYMBOLS\n#define _APS_NEXT_RESOURCE_VALUE        102\n#define _APS_NEXT_COMMAND_VALUE         40001\n#define _APS_NEXT_CONTROL_VALUE         1001\n#define _APS_NEXT_SYMED_VALUE           101\n#endif\n#endif\n"
  }
]